Why React PureComponent’s Shallow Comparison Fails on Nested Objects

This article explains the shallow comparison used by React's PureComponent, details the implementation of shallowEqual and Object.is, and shows why such a shallow check cannot correctly compare nested objects, providing code examples and clear explanations.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Why React PureComponent’s Shallow Comparison Fails on Nested Objects

Introduction

When learning React PureComponent, you encounter the statement that its shouldComponentUpdate performs a shallow comparison of props and state, which does not work for nested objects. This article explains what a shallow comparison is and why it fails for nested structures.

shallowEqual

In React, the source of shouldComponentUpdate contains:

if (this._compositeType === CompositeTypes.PureClass) {
  shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);
}

Thus PureComponent uses a shallow comparison of props and state. The implementation of shallowEqual is:

const hasOwn = Object.prototype.hasOwnProperty;
function is(x, y) {
  if (x === y) {
    return x !== 0 || y !== 0 || 1 / x === 1 / y;
  } else {
    return x !== x && y !== y;
  }
}
export default function shallowEqual(objA, objB) {
  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;
  for (let i = 0; i < keysA.length; i++) {
    if (!hasOwn.call(objB, keysA[i]) ||
        !is(objA[keysA[i]], objB[keysA[i]])) {
      return false;
    }
  }
  return true;
}

Object.is()

Before diving into shallowEqual, understand Object.is(), a function that determines whether two values are the same. It differs from == (which performs type coercion) and === (which fails for +0 vs -0 and NaN). Object.is fixes these edge cases.

function is(x, y) {
  if (x === y) {
    return x !== 0 || 1 / x === 1 / y;
  } else {
    return x !== x && y !== y;
  }
}
Object.is

returns true for:

both undefined

both null

both true or both false

identical strings

the same object reference

numbers that are the same, including +0, -0, and NaN

Analyzing shallowEqual

The function first uses Object.is to compare primitive values. If either argument is not an object, it returns false. For objects, it compares the sets of keys; if the key counts differ, it returns false. Then it iterates over the keys, ensuring each key exists in the other object and that the corresponding values are equal according to Object.is. Because the value comparison is shallow, nested objects are compared by reference, leading to unexpected results when the nested structures differ.

Conclusion

Shallow comparison cannot handle nested objects because it only checks the top‑level keys and uses Object.is on the values. If a value itself is an object, the comparison is by reference, not by deep structure, which explains why PureComponent’s shallow check fails for nested data.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendReactPureComponentObject.isshallowEqual
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.