banner
SlhwSR

SlhwSR

热爱技术的一名全栈开发者
github
bilibili

render timing

1. Principle#

First, the render function has two forms in react:

In class components, it refers to the render method:

class Foo extends React.Component {
    render() {
        return <h1> Foo </h1>;
    }
}

In function components, it refers to the function component itself:

function Foo() {
    return <h1> Foo </h1>;
}

In the render function, we write jsx, which is compiled into the familiar js format using babel, as follows:

return (
  <div className='cn'>
    <Header> hello </Header>
    <div> start </div>
    Right Reserve
  </div>
)

After babel compilation:

return (
  React.createElement(
    'div',
    {
      className : 'cn'
    },
    React.createElement(
      Header,
      null,
      'hello'
    ),
    React.createElement(
      'div',
      null,
      'start'
    ),
    'Right Reserve'
  )
)

From the name, the createElement method is used for creating elements.

In react, these elements are nodes in the virtual DOM tree, which accept three parameters:

  • type: tag
  • attributes: tag attributes, if none, it is null
  • children: tag's child nodes

These virtual DOM trees are eventually rendered into real DOM.

During the render process, React compares the tree returned by the newly called render function with the old version of the tree. This step is a necessary step to determine how to update the DOM. Then it performs a diff comparison and updates the DOM tree.

2. Trigger Timing#

The execution timing of render can be divided into two parts:

  • Class component calls setState to modify state
class Foo extends React.Component {
  state = { count: 0 };

  increment = () => {
    const { count } = this.state;

    const newCount = count < 10 ? count + 1 : count;

    this.setState({ count: newCount });
  };

  render() {
    const { count } = this.state;
    console.log("Foo render");

    return (
      <div>
        <h1> {count} </h1>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

When the button is clicked, the setState method is called, and regardless of whether count has changed, Foo render will be output to the console, indicating that render has been executed.

  • Function component modifies state using useState hook
function Foo() {
  const [count, setCount] = useState(0);

  function increment() {
    const newCount = count < 10 ? count + 1 : count;
    setCount(newCount);
  }

  console.log("Foo render");
  
  return (
    <div>
      <h1> {count} </h1>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

The function component updates data using the useState form. If the value of the array does not change, render will not be triggered.

  • Class component re-renders
class App extends React.Component {
  state = { name: "App" };
  render() {
    return (
      <div className="App">
        <Foo />
        <button onClick={() => this.setState({ name: "App" })}>
          Change name
        </button>
      </div>
    );
  }
}

function Foo() {
  console.log("Foo render");

  return (
    <div>
      <h1> Foo </h1>
    </div>
  );
}

Whenever the Change name button inside the App component is clicked, regardless of the specific implementation of Foo, it will be re-rendered.

  • Function component re-renders
function App(){
    const [name,setName] = useState('App')

    return (
        <div className="App">
            <Foo />
            <button onClick={() => setName("aaa")}>
                { name }
            </button>
      </div>
    )
}

function Foo() {
  console.log("Foo render");

  return (
    <div>
      <h1> Foo </h1>
    </div>
  );
}

It can be observed that when using useState to update the state, Foo render is only triggered once, and it does not trigger Foo render afterwards.

3. Summary#

The render function can write JSX inside it, which is converted into the createElement form to generate a virtual DOM, which is eventually converted into a real DOM.

In React, whenever a class component executes the setState method, the render function is always triggered, while a function component using useState to change the state does not necessarily trigger a re-render.

If the props of a component change, it does not necessarily trigger the execution of the render function. However, if the value of props comes from the state of a parent or ancestor component, in this case, if the state of the parent or ancestor component changes, it will cause the child component to be re-rendered.

Therefore, once setState is executed, the render method is executed. useState determines whether to execute the render method based on whether the current value has changed. Once the parent component is rendered, the child component will also be rendered.

image

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.