Pre-knowledge:

  1. This article is not intended for newcomers to the react/vue foundation
  2. What is the virtual DOM

Render function

One of the features of React is the introduction of the concept of VNode, which operates virtual DOM trees instead of real DOM trees to reduce performance loss

When the Render () method of React is called, a tree of React elements is created. The next time the States or props are updated, the same render() method returns a different tree. React diff the two trees to find the differences and render only the parts that are different

React was optimized to reduce the complexity of O(n), whereas traditional diff required O(n^3) :

  • Assuming that two elements of different types produce different trees, when a node type is different, simply delete the entire node and rebuild it without further unnecessary (or less profitable) diff
  • Developers can do this by settingkeyProperty to tell the render which child elements can be saved unchanged from one render to another, useful in loop rendering

For details about nodes, see the React official statement

React does diff when it calls the render function. Diff sees the difference between the two VDOM’s and starts manipulating the DOM to do actual UI rendering. In function components, the entire function execution is equivalent to calling the render function, so in a sense React rendering is the execution process of function components

The relationship between the render function and UI rendering

When is render executed, or when is the function component called?

  1. When a component’s state (propsstates) when a change occurs
  2. When the parent componentre-renderThe child components will alsore-renderUnless the child component isReact.memodecoration

The Render function is executed when a component’s state (props or States) changes, but this does not mean a UI update is performed. This is where the advantages of the virtual DOM come into play. React diff the entire virtual DOM tree, rendering only the parts that differ

React render and DOM UI redraw are used to check whether the props/states are changed by bailing out the React render

First we need to install React Developer Tools. After installing React, we will open the Render Highlight of React in the console. This plugin may be blocked by the wall, can not download from the official store friends please find their own resources 😅)

Let’s write a simple Demo:

  • The parent componentAppThere are two child componentsSon, a button, and a MSGstate
  • The child component receives MSG from the parent component
  • Clicking the button of the parent component sets the MSG
// Parent App
import React, { useState } from "react";
import Son from "./Son";

function App() {
  const [msg, setMsg] = useState("");
  return (
    <>
      <Son msg={msg} />
      <Son />
      <button onClick={()= > setMsg("Hello")}>set msg</button>
    </>
  );
}

export default App;
Copy the code
// Child component Son
import React, { FC } from "react";

interfaceSonProps { msg? :string;
}
const Son: FC<SonProps> = (props) = > {
  return <div>The message is: {props.msg}</div>;
};

export default Son;
Copy the code

We click the button, MSG’s state is assigned, the render function is triggered, and the render component on the page is highlighted

As we said above, the execution of a function component in a function group can be understood as the execution of the render function. So the above code executes the render function 3 times (once for App and once for both Son components)

We found that even though the second Son component didn’t have any props, its render function was called, but that didn’t mean the UI was rerendered three times. React will use diff to determine that the App component has not changed from the second Son component, so the actual UI rendering will only render the first Son component

Let’s turn off React highlighting and turn on UI thread rendering highlighting

Refresh the page and click the button again

Only the first Son is highlighted. After React diff, we know that the second Son component doesn’t need to be re-rendered, so we only use the real Dom to render the first component

As for why the button is highlighted, it is because the Chrome Render thread is currently turning on its actual Render highlighting. Button hover and click styles will change, so the render thread will also be highlighted

React uses object. is to check whether the React state is the same or not.

  • React render functions 1 → 1
  • Functions 1 → 2 (React render)
  • Functions by {a:1} → {a:1} (react render execution)
  • Functions by {a:1} → {a:2} (react render execution)

Optimizations that developers can make

React does a lot of work on performance at the framework level, and it does its best. But that’s not enough. Some optimizations need to be done by developers themselves.

key

Let’s start with a very simple DOM structure

<! -- before -->
<ul>
  <li>A</li>
  <li>B</li>
</ul>

<! -- after -->
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>
Copy the code

If we want to insert a node in a UL, let’s say at the end, then it’s easy. React compares the first two nodes, no difference is found, and the last node is newly inserted

But what if this is the case

<! -- before -->
<ul>
  <li>A</li>
  <li>B</li>
</ul>

<! -- after -->
<ul>
  <li>C</li>
  <li>A</li>
  <li>B</li>
</ul>
Copy the code

If we insert it at the beginning, React gets confused. It compares the first LI node and finds something different; Comparing the second and third nodes, we found differences, and we need to do an update for each node with differences

But the truth is, as developers, we know: A and B are still A and B, with C inserted at the beginning of the list. In this case, we can bind each node to a unique identifier and actively tell React who the node is

<! -- before -->
<ul>
  <li key="1">A</li>
  <li key="2">B</li>
</ul>

<! -- after -->
<ul>
  <li key="3">C</li>
  <li key="1">A</li>
  <li key="2">B</li>
</ul>
Copy the code

React tells you: Oh, this A and B are the same as that A and B

Note that since the key we bind is equivalent to giving the element an ID card, the tag must be unique and unchanging, otherwise it cannot prove that “this node is the guy”. So key cannot use randomly generated unstable values like math.random ()

This is also easy to understand, imagine if your ID number is not unique, when there is a person with the same ID as you, how can you prove that you are you?

More optimizations

Let’s go back to the Demo above. React has made a number of optimizations, such as reducing unnecessary UI rendering through vDOM, and even going through a lot of trouble with diff to get the best diff performance. But there are still two hurdles it must face:

1. React must run the diff algorithm on each component to check if it should update the UI. 2. All code in these rendering functions or function components will be executed again.

On both counts, React itself cannot be optimized from the framework layer because it cannot know the component differences before diff

Wait, what if we told React in advance? For example, is it possible to actively tell React that “the current node needs to be updated or not updated”, like an assertion?

The answer is yes. This part of optimization involves new concepts such as React.memo, useCallback, useMemo, etc. I will use a separate article to explain these optimization methods

conclusion

Q1: How does React render relate to UI rendering? A1: When the component render function is executed, it does not mean that the corresponding DOM UI of each component is rerendered. React does diff, so UI changes don’t trigger UI drawing

Q2: React when to execute the render function? A2: When the props or States are changed. If component nesting is involved, when the parent component render, the child component also render

Q3: How does React determine whether props/States are changed? A3: the Object is

Q4: What is key used for loop rendering? A4: Identification, improve diff accuracy

Be warned, in the next post I’ll talk about React rendering optimizations