React.memo 是什么?
在写函数式组件的时候,为了避免无效的渲染,可以通过 React.memo
函数来实现,类似于 React.PureCompnent
的功能,对 props
进行浅比较,代码如下
function MyComponent(props) {}function areEqual(prevProps, nextProps) { // 手动判断是否需要重新渲染 // return true不渲染,false则渲染}export default React.memo(MyComponent, areEqual);
React.memo
第二个参数不用的话默认就 props 浅比较
React.memo
在跟某些 hooks 配合使用的情况下会失效,例如在组件内部使用 useState
,useReducer
,useContext
,当 state 或者 context 改变时,组件还是会重新渲染
React.memo 和 useContext
在配合 useContext 使用的情况下,当 context 变化,函数组件会重新渲染,如何解决呢?
避免 context 的值太过于复杂,尽量拆分细粒度的 context 值
拆分组件多个 context,比如 AppContext,ThemeContext,AudioContext 等等,这样其他 context 改变就不会导致无关组件的渲染
function Button() { let theme = useContext(ThemeContext); return <ExpensiveTree className={theme} />;}
拆分组件,与使用 context 组件分离,在 render 阶段单独通过 memo 来缓存组件
const Button = () => { const { theme } = useContext(ThemeContext); return <button>click {theme}</button>;};export default momo(Button);
改写为
const ThemeButton = memo(({ theme }) => { return <button>click {theme}</button>;});const Button = () => { const { theme } = useContext(ThemeContext); return <ThemeButton theme={theme} />;};export default Button;
配合 useMemo 来渲染组件
function Button() { let { theme } = useContext(AppContext); return useMemo(() => { return <ExpensiveTree className={theme} />; }, [theme]);}