使用
const Context = React.createContext(defaultValue)
<Context.Provider value={}>
...
</Context.Provider>
const context = useContext(Context)
createContext源码
function createContext(defaultValue) {
// 1. 创建一个 context
const context = {
$$typeof: REACT_CONTEXT_TYPE,
_currentValue: defaultValue,
Provider: null, // 组件
Consumer, // 组件
_defaultValue: null,
};
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context,
}
return context;
}
Provider
function updateContextProvider(current, workInProgress) {
// 1. 保存 props.value 进context._currentValue
pushProvider(workInProgress, workInProgress.type._context, newValue)
// 2. 更新过程的优化
propagateContextChange(workInProgress, context, renderLanes)
/*
如果一个组件消费了context,那么fiber.dependencies = list
由于函数组件可以使用多个 context,所以这个list被设计成了链表结构
在 Provider 组件的props.value 改变时会先遍历后代组件,根据
fiber.dependencies 上保存的 Context,知道这个后代组件是否依赖了
当前这个 Provider,来判断是否需要更新。
*/
reconcileChildren(current, workInProgress, props.children)
return workInProgress.child
}
useContext
useContext(Context)
// 组件的fiber.dependencies就会保存这个Context
// 返回 Context._currentValue
每一个 context 会推入一个stack, 在completeUnitOfWork时pop出来