React 中 useContext 和 useMemo 一般性使用
通常,需要从某组件传递状态给深层嵌套的后代组件时,context 是一种可选方案。场景如应用“黑暗模式”主题等。
以下是一个类似的简单 demo,简单说下主要 3 个组件的关系,根组件(App)下有个工具栏(Toolbar/ToolbarExpensive)组件,工具栏组件中有个按钮(IButton/IButtonDefaultContextValue/IButtonExpensive)组件会随着主题变化而改变外观。
以上代码,我们看到有 context 的 Provider,有各种 Toolbar 组件,有各种 IButton 组件,Toolbar 外的 IButtonDefaultContextValue 组件用于体现 context 的默认值,我们可以点击各种 button 让不同的 IButton 组件外观发生变化。
当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值。即使祖先使用 React.memo 或 shouldComponentUpdate,也会在组件本身使用 useContext 时重新渲染。
调用了 useContext 的组件总会在 context 值变化时重新渲染。如果重渲染组件的开销较大,你可以通过使用 memoization 来优化。
鉴于以上官方文档的说法,接下来我们看看如何使用 useMemo 来优化昂贵渲染开销的 IButtonExpensive 组件。
接着我们看看界面和按钮操作
首先我们点击 App 组件中的 change ibutton exprensive theme 按钮,Theme.Provider 更新(其 value 发生变化),App 组件内所有用到 useContext hook 的组件统统触发重渲染。我们注意看组件 IButtonExpensive,其被包裹在 useMemo 中,其父组件 ToobarExpensive 中有 useContext hook,触发重渲染时,useMemo 观察到 theme 有变化,IButtonExpensive 组件就要重渲染了。我们再点击 App 组件中 change ibutton theme 按钮,Theme.Provider 更新,照理说 App 组件内所有用到 useContext hook 的组件统统触发重渲染,但是组件 IButtonExpensive 在 ToobarExpensive 组件中的被 useMemo 包裹,如果 theme 没有变化,那么 IButtonExpensive 组件就不会重渲染了。
以下是 ToobarExpensive 组件和 IButtonExpensive 组件的另一种写法:
以上的写法即使有 useMemo,但是并不能阻止 IButtonExpensive 重渲染,因为如官方文档所说“调用了 useContext
的组件总会在 context 值变化时重新渲染。”
OK!就到这里。不周之处,请不吝拍砖!
版权声明: 本文为 InfoQ 作者【sadhu】的原创文章。
原文链接:【http://xie.infoq.cn/article/b3fe8eb744fd0eaf32d589429】。
本文遵守【CC BY-NC-SA】协议,转载请保留原文出处及本版权声明。
评论