天天看點

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>​把子元件更加細化。