简体   繁体   中英

Why does React re-renders children when props does not change?

Consider the following example:

import "./styles.css";
import React from "react";

function Children(props) {
  const counter = props.counter2;
  console.log("re-rendering children");
  return (
    <div className="App">
      <p>counter2 value = {counter} </p>
    </div>
  );
}

export default function App() {
  const [counter, setCounter] = React.useState(0);
  const [counter2] = React.useState(0);
  return (
    <div className="App">
      <p>counter value = {counter} </p>
      <button onClick={(e) => setCounter((c) => c + 1)}>increment</button>
      <Children counter2={counter2} />
    </div>
  );
}

The Children component does not depend on the parent state counter , but when I click the button I can see that re-rendering log printed every time I click. If I am not mistaken then it means the Children component is re-rendered. My question is why? It should not re-render as the props did not change.

code sandbox: https://codesandbox.io/s/modern-dawn-xj9b8

Because of the lifecycle of React, when you are using a functional component, it is also considered stateless and will re-render every time there is an update in its parent component, whether there is a change in props passing into the child.

There are two ways you can do to change this behaviour,

  1. use class component and decide whether to update it using shouldComponentUpdate

  2. or the recommended way using React.memo ,

import "./styles.css";
import React from "react";

function Children(props) {
  const counter = props.counter2;
  console.log("re-rendering children");
  return (
    <div className="App">
      <p>counter2 value = {counter} </p>
    </div>
  );
}

const MemoChild = React.memo(Children);

export default function App() {
  const [counter, setCounter] = React.useState(0);
  const [counter2] = React.useState(0);
  return (
    <div className="App">
      <p>counter value = {counter} </p>
      <button onClick={(e) => setCounter((c) => c + 1)}>increment</button>
      <MemoChild counter2={counter2} />
      {/* <Children counter2={counter2} /> */}
    </div>
  );
}

More on React.memo in the docs

If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.

this answer is true that you can use React.memo but before start using, check some articles to figure out when it's valuable to use it. using it inappropriate could damage your performance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM