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配合使用的情况下会失效,例如在组件内部使用 useStateuseReduceruseContext ,当 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])
}