React 中最常用的组件的间的通信:数据是通过props属性自上而下(由父传子)一级一级进行传递的,这种传递最常用但是最麻烦,有些情况也实现不了比如:你和爷爷有小秘密不想让父传递,想自己亲口告诉你。Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法(无需显示的通过组建树逐层传递)。
如何使用Context
1.创建Context对象
const Context = React.createContext(defaultValue);
只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue
参数才会生效。此默认值有助于在不使用 Provider 包装组件的情况下对组件进行测试。注意:将 undefined
传递给 Provider 的 value 时,消费组件的 defaultValue
不会生效。比如:defaultValue:'zh'
2.创建Provider,传递value
<Context.Provider value={/* 某个值 */}>
当 Provider 的 value
值发生变化时,它内部的所有消费组件都会重新渲染。
3.子组件消费value(有三种途径:contextType,useContext,Consumer)
这三种的区别:
contextType:只能用类组件,只能订阅单一的context;useContext:函数组件(自定hook);Consumer:不限制函数组件还是类组件使用
注意事项
因为 context 会根据引用标识来决定何时进行渲染(本质上是 value 属性值的浅比较),所以这里可能存在一些陷阱,当 provider 的父组件进行重渲染时,可能会在 consumers 组件中触发意外的渲染。举个例子,当每一次 Provider 重渲染时,以下的代码会重渲染所有下面的 consumers 组件,因为 value 属性总是被赋值为新的对象:
class App extends React.Component {
render() {
return (
<Context.Provider value={{something: 'something'}}>
<Toolbar />
</Context.Provider>
);
}
}
为了防止这种情况,将 value 状态提升到父节点的 state 里:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: {something: 'something'},
};
}
render() {
return (
<Context.Provider value={this.state.value}>
<Toolbar />
</Context.Provider>
);
}
}
总结:如果value是个对象记得要提出来,如果是 string,number,可以不用提,两个对象相比一直是false,那么组件每次都会刷新。