组件通信
React 组件通信主要有父子通信 props/callback、React Context 和 Redux/Mobx
props/callback
常规的父子组件通信
props 需要确保只读,保证数据单向流动,但在 react18 中修改 props 的引用属性表现为不报错,可以修改成功,但直接赋值覆盖或者新增删除值均无效
// props: { data: {} }
// Object.getOwnPropertyDescriptors(props)
data: {
value: Object;
writable: false;
enumerable: true;
configurable: false;
}
因此 props 应该是对 fiber.memorizedProps 做了类似的约束配置
Context
通过 createContext
创建一个 context
Provider
传递流程:Provider
组件在 React render 过程中,会遍历子代FiberNode
,消费context
的FiberNode
会提升更新优先级。对于类组件的FiberNode
,会forceUpdate
。接下来所有消费的FiberNode
,都会执行beginWork
Context
订阅流程:Consumer
组件会内部调用readContext
,readContext
会把FiberNode
上的dependencies
属性和context
建立起关联(useContext
)
多个 Provider
React 用栈的形式维护多个 Provider
,确保组件取得的是最近的 Priovider
的 value
- 在
performUnitOfWork
中会调用updateContextProvider
,该函数会调用pushProvider
将cursor.current
放到栈顶,然后新的 value 放到 cursor.current 上。 - react render 过程遇到
context.consumer
的时候,会去读取这个cursor.current
的值,传值到Consumer
- 最后调用
completeUnitOfWork
的时候又会去popPrivider
,将栈顶的 value 恢复到cursor.current
。所以永远取得的是最近的Priovider
的 value
Context 穿透问题,如何优化?
它是可以穿透 React.memo 或者 shouldComponentUpdate 的比对的,也就是说,一旦 Context 的 Value 变动,所有依赖该 Context 的组件会全部 forceUpdate
优化方法:
- 细粒度订阅
- 借助顶层组件 props 共享状态给子组件
- 用 mobx
react-redux 工作原理?
- 通过 Provider 把 redux 中的 store 注入到组件中