关于 context

106 阅读1分钟

使用

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出来