先来看官网解释:
const value = useContext(MyContext);
- 接收一个 context 对象(
React.createContext
的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的<MyContext.Provider>
的value
prop 决定。- 当组件上层最近的
<MyContext.Provider>
更新时,该 Hook 会触发重渲染,并使用最新传递给MyContext
provider 的 contextvalue
值。即使祖先使用React.memo
或shouldComponentUpdate
,也会在组件本身使用useContext
时重新渲染。- 调用了 useContext 的组件总会在 context 值变化时重新渲染。
- useContext(MyContext) 只是让你能够读取 context 的值以及订阅 context 的变化。
据以上,来讲讲自己的理解:看到Context这个名字,可以猜想到它应该是解决组件间环境中某些问题。而实际上,它确实提供了组件之间状态的自由传递的解决方案。
具体的来说,useContext让一个组件能够接收到父级组件传入的状态,不必使用props、不用担心多层组件间嵌套就能够跨多层组件实现状态共享、变更。
根据以上理解,将react官网的demo拿来稍微改造看看如何使用useContext:
import React, { useContext, useState } from "react";
import ReactDOM from "react-dom";
const ThemeContext = React.createContext();
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<>
<div style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</div>
<button onClick={theme.toggleColor}>toggleColor</button>
</>
);
}
function App() {
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee",
toggleColor: () => {
setThemeType("dark");
}
},
dark: {
foreground: "#ffffff",
background: "#222222",
toggleColor: () => {
setThemeType("light");
}
}
};
const [themeType, setThemeType] = useState("light");
return (
<ThemeContext.Provider value={themes[themeType]}>
<Toolbar />
</ThemeContext.Provider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
App
组件在内部使用React.createContext
方法创建出一个context空间ThemeContext
,然后使用ThemeContext.Provider
包裹子组件。子(或更子级别)组件使用useContext(ThemeContext)
接收父级组件provide的状态。
useContext
的缺点就是它并没有提供像setContext
这样的API来供各组件改变context中的状态,因此要想改变context中的状态,只能在使用了ThemeContext.Provider
父组件中操作,这个时候如果子组件想要来行使这个特权该怎么办呢?可以在context中包含一个事件给到子组件来触发即可,这demo中<toggleColor/>按钮点击后就是触发的context中的事件:
网友评论