useContext
useContext 是一个 React Hook,可以让你读取和订阅组件中的 context。
语法
const value = useContext(SomeContext);
用法
基础用法
import { createContext, useContext } from "react"; // const ThemeContext = createContext(null); const ThemeContext = createContext("light"); // 给默认值 export default function MyApp() { const [theme, setTheme] = useState("dark"); return ( <ThemeContext.Provider value={theme}> <Form /> </ThemeContext.Provider> ); } function Form() { return ( <Panel title="Welcome"> <Button>Sign up</Button> <Button>Log in</Button> </Panel> ); } function Panel({ title, children }) { const theme = useContext(ThemeContext); const className = "panel-" + theme; return ( <section className={className}> <h1>{title}</h1> {children} </section> ); } function Button({ children }) { const theme = useContext(ThemeContext); const className = "button-" + theme; return <button className={className}>{children}</button>; }
useContext 返回你向 context 传递的 context value。为了确定 context 值,React 搜索组件树,为这个特定的 context 向上查找最近的 context provider。
useContext() 总是在调用它的组件 上面 寻找最近的 provider。它向上搜索, 不考虑 调用 useContext() 的组件中的 provider。
覆盖组件树一部分的 context
通过在 provider 中使用不同的值包装树的某个部分,可以覆盖该部分的 context。
<ThemeContext.Provider value="dark"> <ThemeContext.Provider value="light"> <Footer /> </ThemeContext.Provider> </ThemeContext.Provider>
在传递对象和函数时优化重新渲染
你可以通过 context 传递任何值,包括对象和函数。
function MyApp() { const [currentUser, setCurrentUser] = useState(null); function login(response) { storeCredentials(response.credentials); setCurrentUser(response.user); } return ( <AuthContext.Provider value={{ currentUser, login }}> <Page /> </AuthContext.Provider> ); }
常见问题
我的组件获取不到 provider 传递的值
这里有几种常见的情况会引起这个问题:
- 你在调用 useContext() 的同一组件(或下层)渲染 <SomeContext.Provider>。把 <SomeContext.Provider> 向调用 useContext() 组件 之上和之外 移动。
- 你可能忘记了使用 <SomeContext.Provider> 包装组件,或者你可能将组件放在树的不同部分。使用 React DevTools 检查组件树的层级是否正确。
- 你的工具可能会遇到一些构建问题,导致你在传值组件中的所看到的 SomeContext 和读值组件中所看到的 SomeContext 是两个不同的对象。例如,如果使用符号链接,就会发生这种情况。你可以通过将它们赋值给全局对象如 window.SomeContext1 和 window.SomeContext2 来验证这种情况。然后在控制台检查 window.SomeContext1 === window.SomeContext2 是否相等。如果它们是不相等的,就在构建工具层面修复这个问题。
尽管设置了不一样的默认值,但是我总是从 context 中得到 undefined
你可能在组件树中有一个没有设置 value 的 provider, 如果你忘记了指定 value,它会像这样传值 value={undefined}。
<ThemeContext.Provider> <Button /> </ThemeContext.Provider>
你可能还错误地使用了一个不同的 prop 名:
// 🚩 不起作用:prop 应该是“value” value={theme} <ThemeContext.Provider theme={theme}> <Button /> </ThemeContext.Provider>