A brief comparison of Props in React

A brief comparison of Props in React

When I went for an interview last week, the interviewer asked me how to compare props in PureComponent . The concept was already memorized in my mind, and the first thing I blurted out was shallow comparison. Then the interviewer asked me how I did the shallow comparison, but I couldn't answer.

Take advantage of the weekend to see how it is implemented in the source code.

Props comparison of class components

Whether the class component needs to be updated needs to implement the shouldComponentUpdate method. Generally speaking, if it inherits PureComponent, there will be a default shallow comparison implementation.

// ReactBaseClasses.js
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;

/**
 * Convenience component with default shallow equality check for sCU.
 */
function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;

The implementation of PureComponent is as above. I used to think that the shouldComponentUpdate method would be implemented by default when declaring it, but in fact there is no default method.

Next, let's look at the call to shouldComponentUpdate method.

// ReactFiberClassComponent.js
function checkShouldComponentUpdate(
  workInProgress,
  ctor,
  oldProps,
  newProps,
  oldState,
  newState,
  nextContext,
) {
  const instance = workInProgress.stateNode;
  // If the instance implements shouldComponentUpdate, return the result of calling it if (typeof instance.shouldComponentUpdate === 'function') {
    const shouldUpdate = instance.shouldComponentUpdate(
      newProps,
      newState,
      nextContext,
    );
    return shouldUpdate;
  }

  // Shallow comparison when using PureReactComponent if (ctor.prototype && ctor.prototype.isPureReactComponent) {
    return (
      !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)
    );
  }

  return true;
}

It can be seen that there is actually no separate shouldComponentUpdate method written for PureReactComponent, but the result of shallow comparison is returned during comparison.

The answers to the shallow comparisons are all in the shallowEqual method.

shallowEqual shallow comparison

// shallowEqual.js
function shallowEqual(objA: mixed, objB: mixed): boolean {
  // The same object returns true
  if (Object.is(objA, objB)) {
    return true;
  }

  // If it is not an object or null, return false
  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false;
  }

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

  // If the number of keys is different, return false
  if (keysA.length !== keysB.length) {
    return false;
  }

  // If the corresponding key values ​​are not the same, return false
  for (let i = 0; i < keysA.length; i++) {
    if (
      !hasOwnProperty.call(objB, keysA[i]) ||
      !Object.is(objA[keysA[i]], objB[keysA[i]])
    ) {
      return false;
    }
  }

  return true;
}

The principle of shallowEqual method is very simple

  1. First determine whether the two are the same object.
  2. Determine whether the value of both is not an object or is null.
  3. Compare the lengths of the two keys.
  4. Determine whether the values ​​corresponding to the two keys are the same.

It turns out that the principle is such a simple comparison. If I can recite the source code during the interview, will I get a higher salary?

A brief comparison of functional components

The shallow comparison method of function components is implemented using the React.memo method.

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

React.memo method also supports passing in a compare function as the second parameter.

The internal processing actually manually creates a ReactElement with $$typeof as REACT_MEMO_TYPE to facilitate subsequent type judgment.

The creation of the React.memo component is a little more complicated. Since a second custom compare function can be passed in, it is actually defined as two types of Fiber nodes internally.

  • The one without the compare function passed in is SimpleMemoComponent.
  • The one that passes in the custom compare function is MemoComponent.

However, the actual comparison of Props is the same, and the shallowEqual method is called by default for comparison.

updateSimpleMemoComponent

if (
  shallowEqual(prevProps, nextProps) &&
  current.ref === workInProgress.ref
) {
	// ...
}

updateMemoComponent

// ...
let compare = Component.compare;
compare = compare !== null ? compare : shallowEqual;
if (compare(prevProps, nextProps) && current.ref === workInProgress.ref) {
  return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
}
// ... 

As for why it is divided into two components, I don’t quite understand it. It is probably related to update scheduling.

The Fiber node of SimpleMemoComponent is actually equivalent to a function component with a changed name. The process will go directly to the function component, while MemoComponent is covered with a shell. You need to peel off the shell first to generate a child Fiber node, and then go to the function component based on the judgment of the child Fiber node.

The above is a brief analysis of Props.

The above is the detailed content of the shallow comparison of Props in React. For more information about the shallow comparison of Props in React, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • React's context and props explained
  • Detailed explanation of the use of props in React's three major attributes
  • Talk about the Render Props pattern in React
  • ES6 class chain inheritance, instantiation and react super (props) principle detailed explanation
  • An article to help you understand the principles of React Props

<<:  Detailed steps for completely uninstalling MySQL 5.7

>>:  Example of how to configure nginx in centos server

Recommend

How to view Linux ssh service information and running status

There are many articles about ssh server configur...

Solution to garbled display of Linux SecureCRT

Let's take a look at the situation where Secu...

MySQL foreign key constraint (FOREIGN KEY) case explanation

MySQL foreign key constraint (FOREIGN KEY) is a s...

MySQL 8.0.15 installation graphic tutorial and database basics

MySQL software installation and database basics a...

Node.js solves the problem of Chinese garbled characters in client request data

Node.js solves the problem of Chinese garbled cha...

Detailed explanation of Vue's monitoring properties

Table of contents Vue monitor properties What is ...

Install MySQL (including utf8) using Docker on Windows/Mac

Table of contents 1. Docker installation on Mac 2...

Use of filter() array filter in JS

Table of contents 1. Introduction 2. Introduction...

Tutorial on how to remotely connect to MySQL database under Linux system

Preface I recently encountered this requirement a...

Detailed explanation of JavaScript state container Redux

Table of contents 1. Why Redux 2. Redux Data flow...

Detailed explanation of how to create MySql scheduled tasks in navicat

Detailed explanation of creating MySql scheduled ...

Recommend several MySQL related tools

Preface: With the continuous development of Inter...

A brief discussion of four commonly used storage engines in MySQL

Introduction to four commonly used MySQL engines ...