跳至主要内容

上下文

基本示例

这是一个创建包含活动主题的上下文的简单示例。

import { createContext } from "react";

type ThemeContextType = "light" | "dark";

const ThemeContext = createContext<ThemeContextType>("light");

使用上下文提供程序包装需要上下文的组件

import { useState } from "react";

const App = () => {
const [theme, setTheme] = useState<ThemeContextType>("light");

return (
<ThemeContext.Provider value={theme}>
<MyComponent />
</ThemeContext.Provider>
);
};

调用 useContext 来读取和订阅上下文。

import { useContext } from "react";

const MyComponent = () => {
const theme = useContext(ThemeContext);

return <p>The current theme is {theme}.</p>;
};

无默认上下文值

如果您没有任何有意义的默认值,请指定 null

import { createContext } from "react";

interface CurrentUserContextType {
username: string;
}

const CurrentUserContext = createContext<CurrentUserContextType | null>(null);
const App = () => {
const [currentUser, setCurrentUser] = useState<CurrentUserContextType>({
username: "filiptammergard",
});

return (
<CurrentUserContext.Provider value={currentUser}>
<MyComponent />
</CurrentUserContext.Provider>
);
};

现在上下文的类型可以是 null,您会注意到,如果您尝试访问 username 属性,则会收到 'currentUser' 可能为 'null' 的 TypeScript 错误。您可以使用可选链来访问 username

import { useContext } from "react";

const MyComponent = () => {
const currentUser = useContext(CurrentUserContext);

return <p>Name: {currentUser?.username}.</p>;
};

但是,最好不必检查 null,因为我们知道上下文不会是 null。一种方法是提供一个自定义 Hook 来使用上下文,如果未提供上下文,则会在其中抛出错误

import { createContext } from "react";

interface CurrentUserContextType {
username: string;
}

const CurrentUserContext = createContext<CurrentUserContextType | null>(null);

const useCurrentUser = () => {
const currentUserContext = useContext(CurrentUserContext);

if (!currentUserContext) {
throw new Error(
"useCurrentUser has to be used within <CurrentUserContext.Provider>"
);
}

return currentUserContext;
};

在此使用运行时类型检查的好处是在组件包装不正确时在控制台中打印清晰的错误消息。现在可以访问 currentUser.username 而无需检查 null

import { useContext } from "react";

const MyComponent = () => {
const currentUser = useCurrentUser();

return <p>Username: {currentUser.username}.</p>;
};

类型断言作为替代方案

避免必须检查 null 的另一种方法是使用类型断言告诉 TypeScript 您知道上下文不是 null

import { useContext } from "react";

const MyComponent = () => {
const currentUser = useContext(CurrentUserContext);

return <p>Name: {currentUser!.username}.</p>;
};

另一种选择是使用空对象作为默认值并将其转换为预期的上下文类型

const CurrentUserContext = createContext<CurrentUserContextType>(
{} as CurrentUserContextType
);

您还可以使用非空断言获得相同的结果

const CurrentUserContext = createContext<CurrentUserContextType>(null!);

当您不知道选择什么时,优先选择运行时检查和抛出而不是类型断言。