Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does React re-render children when the parent changes?

Tags:

reactjs

If a parent re-renders, children in React are also re-rendered, no matter if the passed props changed or not.

Why is React doing that? What would be the issue if React wouldn't re-render children (without changed props) when the parent renders?

Update: I am talking about this in the React Devtools profiler: enter image description here

Sample code:

App.tsx:

 import React, { useMemo, useState } from "react";
    import "./App.css";
    import { Item, MyList } from "./MyList";
    
    function App() {
      console.log("render App (=render parent)");
    
      const [val, setVal] = useState(true);
      const initialList = useMemo(() => [{ id: 1, text: "hello world" }], []); // leads to "The parent component rendered"
      //const initialList: Item[] = []; // leads to "Props changed: (initialList)"
    
      return (
        <div style={{ border: "10px solid red" }}>
          <button type="button" onClick={() => setVal(!val)}>
            re-render parent
          </button>
          <MyList initialList={initialList} />
        </div>
      );
    }
    
    export default App;

MyList.tsx:

import { FC, useState } from "react";

export interface Item {
  id: number;
  text: string;
}

interface Props {
  initialList: Item[];
  //onItemsChanged: (newItems: Item[]) => void;
}

export const MyList: FC<Props> = ({
  initialList,
  //onItemsChanged,
}) => {
  console.log("render MyList");

  const [items, setItems] = useState(initialList);

  return (
    <div style={{ border: "5px solid blue" }}>
      <ul>
        {items.map((item) => (
          <li key={item.id}>{item.text}</li>
        ))}
      </ul>
      <button type="button">add list item (to be implemented)</button>
    </div>
  );
};
like image 654
stefan.at.wpf Avatar asked Jan 09 '21 14:01

stefan.at.wpf


People also ask

Does React update all children components once the state of a parent has changed?

React schedules a render every time the state of a component changes.

Do kids Rerender when parent Rerenders React?

“children” is a <ChildComponent /> element that is created in SomeOutsideComponent . When MovingComponent re-renders because of its state change, its props stay the same. Therefore any Element (i.e. definition object) that comes from props won't be re-created, and therefore re-renders of those components won't happen.

Does child component Rerender if parent state changes?

State changes in Child component doesn't effect on the parent component, but when a state of parent component changes all the child components render.

How do you prevent a child component from re-rendering in React?

Memoization enables your code to re-render components only if there's a change in the props. With this technique, developers can avoid unnecessary renderings and reduce the computational load in applications. React provides two Hooks to implement memoization: useMemo()


3 Answers

Memoization generates an additional cost corresponding to cache-related computations, this is why React re-renders components even when the props are referentially the same, unless you choose to memoize things using React.memo for instance.

If you consider for example a component that re-renders with different props very often, and if memoization was an internal implementation detail, then React would have to do 2 jobs on every re-rendering:

  • Check if the old and current props are referentially the same.
  • Because props comparison almost always returns false, React would then perform the diff of previous and current render results.

which means that you might end up with worse performance.

like image 119
Hamza El Aoutar Avatar answered Oct 21 '22 10:10

Hamza El Aoutar


React achieves a fast and responsive UI by re-rendering components on every state change (using setState) or from changes of props, followed by React’s reconciliation diffing algorithm that diffs previous renders with current render output to determine if React should commit changes to the component tree (e.g. DOM) with the new updates.

However, unnecessary component re-renders will happen and can be expensive, It’s been a common performance pitfall in every single React project that I’ve been working on. SOURCE

Solution for this issue : A component can re-render even if its props don’t change. More often than not this is due to a parent component re-rendering causing the child to re-render.

To avoid this, we can wrap the child component in React.memo() to ensure it only re-renders if props have changed:

function SubComponent({ text }) {
  return (
    <div>
      SubComponent: { text }
    </div>
  );
}
const MemoizedSubComponent = React.memo(SubComponent);

SOURCE

like image 20
gmj Avatar answered Oct 21 '22 10:10

gmj


Wrapp your component with React.memo and it will not re-render

export const MyList: FC<Props> = React.memo(({
  initialList,
  //onItemsChanged,
}) => {
  console.log("render MyList");

  const [items, setItems] = useState(initialList);

  return (
    <div style={{ border: "5px solid blue" }}>
      <ul>
        {items.map((item) => (
          <li key={item.id}>{item.text}</li>
        ))}
      </ul>
      <button type="button">add list item (to be implemented)</button>
    </div>
  );
})

If you are looking at reason, please see this

like image 36
ARZMI Imad Avatar answered Oct 21 '22 11:10

ARZMI Imad