跳到主要内容

认识

一、认识


Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法

1.1 prop drilling

在构建 React 应用程序时,在多层嵌套组件来使用另一个嵌套组件提供的数据。最简单的方法是将一个 prop 从每个组件一层层的传递下去,从源组件传递到深层嵌套组件,这叫做prop drilling

prop drilling的主要缺点是原本不需要数据的组件变得不必要地复杂,并且难以维护。

为了避免prop drilling,一种常用的方法是使用React Context。通过定义提供数据的Provider组件,并允许嵌套的组件通过Consumer组件或useContext Hook 使用上下文数据。

二、问题


2.1 Context 使用后, 会暴露出那些问题呢?

  1. 通过 Provider 传递的状态, 如果不使用 useMemouseCallback 封装,以及 Child 不使用 memo,在 Provider 的组件 re-render 时,所有使用到 context 的地方都会被重新渲染。

  2. 如果 provider 传递的状态越来越多时,经常会因为 provider 的其中一状态改变导致整颗子树都 re-render。要解决这个问题则是要把 Provider 的状态切分的更细,用不同的 Provider 分离状态。但如果分成多个 Provider,随着需要管理的状态越来越多,Provider 也会越来越多,介时也不好管理。

2.2 通过Provider发布状态时,为什么要将value提升到父节点的state里?

答: 因为context会使⽤参考标识(reference identity)来决定何时进⾏渲染,这⾥可能会有⼀些陷阱,当provider的⽗组件进⾏重渲染时,可能会在consumers组件中触发意外的渲染。举个例⼦,当每⼀次Provider重渲染时,以下的代码会重渲染所有下⾯的consumers组件,因为value属性总是被赋值为新的对象:

class App extends React.Component {
render() {
return (
<Provider value={{something:
'something'}}>
<Toolbar />
</Provider>
);
}
}

为了防⽌这种情况,将value状态提升到⽗节点的state⾥:

class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: {something: 'something'},
};
}
render() {
return (
<Provider value={this.state.value}>
<Toolbar />
</Provider>
);
}
}