# memo

# 定义

memo 源码也是非常简单如下:

export default function memo<Props>(
  type: React$ElementType,
  compare?: (oldProps: Props, newProps: Props) => boolean,
) {
  return {
    $$typeof: REACT_MEMO_TYPE,
    type,
    compare: compare === undefined ? null : compare,
  };
}

React.memo 是一个高阶组件,它和 React.PureComponent 非常相似,但是只适用于函数组件

memo 的定义很简单,传入两个参数,第一个是 React 组件,第二个是一个比较函数,函数参数是旧的 props 和新的 props,返回值是 boolean,如果为 true 表示该组件不需要重新渲染,如果为 false 表示重新渲染该组件

默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。

# updateMemoComponent

标记了 tag 后在 begninWork 中会走到 MemoComponent 里面调用 updateMemoComponent 方法如下:

function updateMemoComponent(
  current: Fiber | null,
  workInProgress: Fiber,
  Component: any,
  nextProps: any,
  updateExpirationTime,
  renderExpirationTime: ExpirationTime,
): null | Fiber {

  // 省略...
  let currentChild = ((current.child: any): Fiber); 
  if (updateExpirationTime < renderExpirationTime) {
    const prevProps = currentChild.memoizedProps;
    // Default to shallow comparison
    let compare = Component.compare;
    compare = compare !== null ? compare : shallowEqual;
    if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) {
      return bailoutOnAlreadyFinishedWork(
        current,
        workInProgress,
        renderExpirationTime,
      );
    }
  }
  // React DevTools reads this flag.
  workInProgress.effectTag |= PerformedWork;
  let newChild = createWorkInProgress(currentChild, nextProps);
  newChild.ref = workInProgress.ref;
  newChild.return = workInProgress;
  workInProgress.child = newChild;
  return newChild;
}

可以看到如果我们传入了自定义的比较那么就会走自己的,否则就会走 默认的 shallowEqual 进行浅比较,然后自己走 bailoutOnAlreadyFinishedWork 执行 cloneChildFibers 进行复用 返回 workInProgress

更新时间: 11/2/2020, 10:53:13 PM