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:
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>
);
};
React schedules a render every time the state of a component changes.
“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.
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.
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()
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:
which means that you might end up with worse performance.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With