美文网首页
PureComponent shallowEqual

PureComponent shallowEqual

作者: 别过经年 | 来源:发表于2018-11-07 12:19 被阅读79次

react@16.6.1
ReactFiberClassComponent

function checkShouldComponentUpdate(
  workInProgress,
  ctor,
  oldProps,
  newProps,
  oldState,
  newState,
  nextContext,
) {
  const instance = workInProgress.stateNode;
  if (typeof instance.shouldComponentUpdate === 'function') {
    startPhaseTimer(workInProgress, 'shouldComponentUpdate');
    const shouldUpdate = instance.shouldComponentUpdate(
      newProps,
      newState,
      nextContext,
    );
    stopPhaseTimer();

    if (__DEV__) {
      warningWithoutStack(
        shouldUpdate !== undefined,
        '%s.shouldComponentUpdate(): Returned undefined instead of a ' +
          'boolean value. Make sure to return true or false.',
        getComponentName(ctor) || 'Component',
      );
    }

    return shouldUpdate;
  }

  if (ctor.prototype && ctor.prototype.isPureReactComponent) {
    return (
      !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
    );
  }

  return true;
}

ReactShallowRenderer.js

    let shouldUpdate = true;
    if (this._forcedUpdate) {
      shouldUpdate = true;
      this._forcedUpdate = false;
    } else if (typeof this._instance.shouldComponentUpdate === 'function') {
      shouldUpdate = !!this._instance.shouldComponentUpdate(
        props,
        state,
        context,
      );
    } else if (type.prototype && type.prototype.isPureReactComponent) {
      shouldUpdate =
        !shallowEqual(oldProps, props) || !shallowEqual(oldState, state);//在此做比对
    }

shallowEqual.js

const hasOwnProperty = Object.prototype.hasOwnProperty;

/**
 * inlined Object.is polyfill to avoid requiring consumers ship their own
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 */
function is(x, y) {
  // SameValue algorithm
  if (x === y) {
    // Steps 1-5, 7-10
    // Steps 6.b-6.e: +0 != -0
    // Added the nonzero y check to make Flow happy, but it is redundant
    return x !== 0 || y !== 0 || 1 / x === 1 / y;
  } else {
    // Step 6.a: NaN == NaN
    return x !== x && y !== y;
  }
}

/**
 * Performs equality by iterating through keys on an object and returning false
 * when any key has values which are not strictly equal between the arguments.
 * Returns true when the values of all keys are strictly equal.
 */
function shallowEqual(objA: mixed, objB: mixed): boolean {
  if (is(objA, objB)) {
    return true;
  }

  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false;
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

  // Test for A's keys different from B.
  for (let i = 0; i < keysA.length; i++) {
    if (
      !hasOwnProperty.call(objB, keysA[i]) ||
      !is(objA[keysA[i]], objB[keysA[i]])
    ) {
      return false;
    }
  }

  return true;
}

export default shallowEqual;

oldProps, newProps是所有属性的集合,就是个object,debug发现 好像每次两个对象的引用都是不同的,那么下面的这句话在比较oldProps, newProps总是返回false(猜测 有待证实)

  if (is(objA, objB)) {
    return true;
  }

在代码里有这么一段

    return list.map(item => (
      <AppItem
        key={item.id}
        onDeleteItem={() => this.confirmDeleteItem(item.id)}
        copyItem={this.copyAppItem}
        data={item}
      />
    ));

onDeleteItem的写法每次父组件数据更新,都是返回的新的函数,is(objA[keysA[i]], objB[keysA[i]])这句话永远不会成立,所以直接传递this.confirmDeleteItem进去,在AppItem内部传递id,这样PureComponent才会起作用

react源码

模拟props,对shallowEqual进行测试


const data = {
  list: [
    {
      name: "aaa",
      sex: "man"
    },
    {
      name: "bbb",
      sex: "woman"
    }
  ],
  status: true
};

const newData = { ...data };
//如果不解构再赋值因为引用是相同的,如果我改变newData.list[0].name = "geek",
//shallowEqual对比出来返回两者是true,不会重新render。
//但是如果解构,如果我没有改变任何数据shallowEqual返回的都是false,都会重新render
//但是在redux里面 如果我想改变数据才会发dispatch,
//自然需要更新数据(这里面可能会存在数据没改变不需要re-render的情况)

newData.list[0].name = "geek"; //newData和data的list是同一个引用

const props = { data };
const newProps = { data: newData };

console.info(props, newProps);

console.log(shallowEqual(props, newProps)); //false 走render

相关文章

网友评论

      本文标题:PureComponent shallowEqual

      本文链接:https://www.haomeiwen.com/subject/ehamxqtx.html