天天看点

createContext 你用对了吗?

前言

​<code>​createContext​</code>​是 react 提供的用于全局状态管理的一个 api,我们可以通过​<code>​Provider​</code>​组件注入状态,用​<code>​Consumer​</code>​组件或者​<code>​useContext​</code>​api 获取状态(推荐使用​<code>​useContext​</code>​方式,更加简洁)。

​<code>​createContext​</code>​让组件间的通信更为方便,但如果使用不当却会带来很大的性能问题。下面我们会讨论引起性能问题的原因以及如何优化。

性能问题的根源

先来看一个例子:​​createContext性能问题原因​​,注意例子中的2个问题点。

从这个例子可以看出来,用​<code>​ThemeCtx.Provider​</code>​直接包裹子组件,每次​<code>​ThemeCtx.Provider​</code>​组件渲染会导致所有子组件跟着重新渲染,原因是使用​<code>​React.createElement(type, props: {}, ...)​</code>​创建的组件,每次​<code>​props: {}​</code>​都会是一个新的对象。

​<code>​createContext​</code>​是根据发布订阅模式来实现的,​<code>​Provider​</code>​的​<code>​value​</code>​值每次发生变化都会通知所有使用它的组件(使用​<code>​useContext​</code>​的组件)重新渲染。

解决方案

上面我们分析了问题的根源,下面就开始解决问题。 同样先看一下优化后的例子:​​createContext性能优化​​。

把​<code>​ThemeContext​</code>​抽离出来,子组件通过​<code>​props​</code>​的​<code>​children​</code>​属性传递进来。即使​<code>​ThemeContext.Provider​</code>​重新渲染,​<code>​children​</code>​也不会改变。这样就不会因为​<code>​value​</code>​值改变导致所有子组件跟着重新渲染了。

通过上面的方式可以一刀切的解决整体重复渲染的问题,但局部渲染的问题就比较繁琐了,需要我们用​<code>​useMemo​</code>​一个个的修改子组件,或者使用​<code>​React.memo​</code>​把子组件更加细化。