Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent child component from re-rendering when using React hooks and memo?

Tags:

I just started experimenting with React hooks and I'm wondering how I can prevent a child component from re-rendering when it's parent re-renders. I'm looking for something similar to returning false in componentDidUpdate. My issue seems to stem from the click handler I'm calling in the child component to change state in the parent component. Since the function is created in the parent component, it is created new on each parent render which triggers a prop change in the child component, which then causes the child to re-render (I think). Here is some sample code to help illustrate the situation.

function Parent() {     const [item, setItem] = useState({ name: "item", value: 0 });      const handleChangeItem = () => {         const newValue = item.value + 1;         setItem({ ...item, value: newValue });     };      return <Child item={item} changeItem={handleChangeItem} />; }  const Child = React.memo(function Child({ item, changeItem }) {     function handleClick(){         changeItem();     }     return (         <div>             Name: {item.name} Value: {item.value}             <button onClick={handleClick}>change state in parent</button>         </div>     ); }); 

How do I prevent Child component from rendering every time Parent component renders? Should handleChangeItem in the parent live someplace else so that it is not re-created on each render? If so, how does it get access to item and setItem returned by useState?

I'm pretty new to react and just started playing with hooks so I'm probably missing something obvious.

like image 494
user1843640 Avatar asked Jan 03 '19 00:01

user1843640


People also ask

How do you stop Rerendering of child component?

If you don't want a component to re-render when its parent renders, wrap it with memo. After that, the component indeed will only re-render when its props change.

Do child components always re-render?

memo : MovingComponent will re-render, “children” function will be triggered, but its result will be memoized, so ChildComponent will never re-render.

How does UseCallback prevent re-rendering of a function?

A solution to prevent this, would be wrapping CountButton component with React. memo(). This will prevent a re-render on a component that didn't have any change on the props values.


1 Answers

In your case it doesn't really makes sense to memoize Child because if item changes, the child has to re-render. However if there is a case that props do not change , but still the child is re-rendering due to the functions getting recreated you would make use of useCallback hook to memoize the functions, on each render. Also since you have memoized the handler, you should make use of the callback method to update state since item inside the handler will only refer to the value it had when the function was initially created

function Parent() {   const [item, setItem] = useState({ name: "item", value: 0 });    const handleChangeItem = useCallback(() => {     setItem(prevItem => ({ ...prevItem, value: prevItem.value + 1 }));   }, []);    return (     <>       Name: {item.name} Value: {item.value}       <Child changeItem={handleChangeItem} />     </>   ); }  const Child = React.memo(function Child({ item, changeItem }) {   function handleClick() {     changeItem();   }   console.log("child render");   return (     <div>       <button onClick={handleClick}>change state in parent</button>     </div>   ); }); 

Working demo

P.S. Credit to @danAbramov for the direction

like image 93
Shubham Khatri Avatar answered Oct 05 '22 22:10

Shubham Khatri