语法:
somecontext = createContext(defaultValue);
作用: 避免了组件嵌套太深, 顶层变量层层传递的麻烦.
如何消费顶层数据
第一步: 用createContext声明一个context上下文变量
import { createContext } from 'react';export const GlobalContext = createContext({} as any);
● 参数defaultValue: 如果在组件的顶层树没有匹配到context Provider,就会使用defaultValue,它是静态的并且永远不会被改变. 如果你没有什么特别想声明的默认值, 写个null就行.
● 返回值: 返回一个context对象, 它本身不带有任何信息,它代表了其他组件可以提供和读取的上下文.生成的context对象有两个属性,分别是:
○ context.Provider: 让你用来给组件们提供context变量
○ context.Consumer: 另一种比较少用的, 用来消费context变量的方法( useContext出现之前的一种老的读取context的方法, 不推荐使用, 现在推荐用useContext )
第二步: 用context.Provider给下层组件传递要消费的值
像下面这样, 将你的子组件用context.Provider包裹, 并通过value向内部所有的组件们提供可用的值,
const globalData = Object.assign({}, {mydata,
}const [globalStore, dispatch] = useReducer(useCallback((preState, patchValue) => {return { ...preState, ...patchValue };}, []),globalData,
);function App(){return (<GlobalContext.Providervalue={{ globalStore}}<OtherComponents/></GlobalContext.Provider>)
}
第三步: 用useContext消费顶层树提供的数据
所有子组件就可以通过调用usecontext(ThemeContext)去读取这个context的变量,无论这些子组件嵌套有多深
const { globalStore } = useContext(GlobalContext);
function OtherComponents(){const theme = useContext(GlobalContext);return <button classname={theme}/>
}
只要来自父组件的context改变了, react就会重新渲染和更新ui
通常, 在不同文件的组件需要访问同一个context, 这就是为什么我们要在一个单独的文件里声明context, 然后将它export出去
// Contexts.js
import { createContext } from 'react';export const GlobalContextProvider = GlobalContext.Provider;export default GlobalContext;
如果想在子组件更新这些数据怎么办?
总不能从顶层传递一个setstate下来吧,这多麻烦啊, 特别是如果你的项目中组件嵌套很深的情况, 有个简单的方法,就是从context.Provider的value中 pass down 一个 dispatch 函数 from useReducer via context
const globalData = Object.assign({}, {mydata,
}const [globalStore, dispatch] = useReducer(useCallback((preState, patchValue) => {return { ...preState, ...patchValue };}, []),globalData,
);function App(){return (<GlobalContext.Providervalue={{ globalStore, dispatch}} //改动在这里<OtherComponents/></GlobalContext.Provider>)
}
这样TodosApp中所有的子组件就可以使用dispatch去更新顶层数据了
function DeepChild(props) {// If we want to perform an action, we can get dispatch from context. const dispatch = useContext(TodosDispatch);function handleClick() {dispatch({ type: 'add', text: 'hello' });}return (<button onClick={handleClick}>Add todo</button>);
}
参考自文档: https://legacy.reactjs.org/docs/hooks-faq.html#how-to-avoid-passing-callbacks-down