Context允许组件从远程父级接收信息,而无需将其作为 props 传递。 例如,Application的顶级组件可以将当前的 UI 主题传递给下面的所有组件,无论有多深。
-
useContext
读取和订阅一个上下文。
const value = useContext(SomeContext)
定义
useContext(SomeContext)
在组件的最上层调用useContext
订阅和读取context.
参数
-
SomeContext
: context 是使用 [createContext
]创建出来的(https://react.dev/reference/react/createContext). context不保存信息, 仅表示您可以提供或从组件中读取的信息类型。
返回值
useContext
返回调用组件的Context值, 它被确定为传递给树中调用组件上方最接近的“SomeContext.Provider”的“值”。如果没有这样的Provider,则返回的值将是传递给该上下文的 createContext
的 defaultValue
。 返回的值始终是最新的。 如果Context发生变化,React 会自动重新渲染读取某些Context的组件。
用法
1.将数据深入传递到树中
注意:
Form 拿到的值是light,因为最近的cotext就是默认值。
Panel拿到的值是dark,因为最近的cotext是from提供的dark
import { useContext, createContext } from "react";
const ThemeContext = createContext("light");
export function ContextDemo() {
return <span>context <Form></Form></span>
}
function Form() {
const theme = useContext(ThemeContext); //取初始值light
return <ThemeContext.Provider value="drak"><button>form {theme}<Panel></Panel></button>
</ThemeContext.Provider>
}
function Panel() {
const theme = useContext(ThemeContext);
return <div>panel {theme}</div>
}
![](https://img.haomeiwen.com/i117707/3ab5cb33c3909d34.png)
2.通过改变context更新值
更新上面的Form组件
function Form() {
// const theme = useContext(ThemeContext);
const [theme, setTheme] = useState("form-light");
return <ThemeContext.Provider value={theme}><button onClick={() => { setTheme("dark") }}>form Switch to {theme}<Panel></Panel></button>
</ThemeContext.Provider>
}
![](https://img.haomeiwen.com/i117707/5ab829843a803050.png)
3.通过Context更新object,使用useState,来改变context value的值。
import { useContext, createContext, useState } from "react";
const CurrentUserContext = createContext({
currentUser: "Tom",
setCurrentUser: (currentUser: string) => {},
});
export function ContextDemo() {
const [currentUser, setCurrentUser] = useState("lisa");
return (
<CurrentUserContext.Provider value={{ currentUser, setCurrentUser }}>
<span>
context <Form></Form>
</span>
</CurrentUserContext.Provider>
);
}
function Form() {
return <Panel></Panel>;
}
function Panel() {
const { currentUser, setCurrentUser } = useContext(CurrentUserContext);
return (
<div
onClick={() => {
setCurrentUser("layor");
}}
>
{" "}
panel {currentUser}
</div>
);
}
4.提取组件中的provider
function MyProviders({ children, theme, setTheme }) {
const [currentUser, setCurrentUser] = useState("lisa");
return (
<ThemeContext.Provider value={theme}>
<CurrentUserContext.Provider value={{ currentUser, setCurrentUser }}>
{children}
</CurrentUserContext.Provider>
</ThemeContext.Provider>
);
}
使用provider
function Form() {
const [theme, setTheme] = useState("form-light");
return (
<MyProviders theme={theme} setTheme={setTheme}>
<button
onClick={() => {
setTheme("dark");
}}
>
form Switch to {theme}
</button>
<Panel></Panel>
</MyProviders>
);
}
5.优化传递对象和函数时的重新渲染
import { useCallback, useMemo } from 'react';
function MyApp() {
const [currentUser, setCurrentUser] = useState(null);
const login = useCallback((response) => {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}, []);
const contextValue = useMemo(() => ({
currentUser,
login
}), [currentUser, login]);
return (
<AuthContext.Provider value={contextValue}>
<Page />
</AuthContext.Provider>
);
}
即使 MyApp 需要重新渲染,调用 useContext(AuthContext) 的组件也不需要重新渲染,除非 currentUser 已更改。
遇到的问题
// 🚩 Doesn't work: no value prop
<ThemeContext.Provider>
<Button />
</ThemeContext.Provider>
// 🚩 Doesn't work: prop should be called "value"
<ThemeContext.Provider theme={theme}>
<Button />
</ThemeContext.Provider>
好了,那我们的useContext到这里就结束了。
宝子们可以收藏评论交流哦
网友评论