C D
C D

Reputation: 223

How can I prevent re-render after state changed in React Hooks?

I am trying to build an app but the problem is when I change a state, all the components re-render.

const App=()=>{
   const [showMenu,setshowMenu]=useState(false)
   

 return(
     <>

     <Header showMenu={showMenu} setShowMenu={setShowMenu}/>

     <MainArea/>

     {showMenu ? <Menu/> : null}

     <Footer/>

    </>
 )

}

When I set showMenu to true by button, a menu appears but the problem is all my components (Header,MainArea,Footer) do re-render. I don't want that. How can I solve this problem?

Upvotes: 18

Views: 53386

Answers (5)

Rahul Roy
Rahul Roy

Reputation: 51

Firstly, whenever state changes, the component re-renders. You can only make some specific components to no re-render when state change occurs using useMemo.

If you need to store information, without the information causing any re-renders, you can use useRef. Like state, refs are retained by React between re-renders. However, setting state re-renders a component. Changing a ref does not! You can access the current value of that ref through the ref.current property.

export default function Counter() {
  let ref = useRef(0);

  function handleClick() {
    ref.current = ref.current + 1;
    alert('You clicked ' + ref.current + ' times!');
  }

  return (
    <button onClick={handleClick}>
      Click me!
    </button>
  );
}

Clicking on the button Click me! does not trigger any re-renders, while updating the information inside the ref.

reference: https://react.dev/learn/escape-hatches

Upvotes: 1

metalheadcoder
metalheadcoder

Reputation: 525

In this case, the state is only for header component. U can bring the state inside the Header component. U can read here for further explaination https://overreacted.io/before-you-memo/

Also here another good explanation How to prevent re-rendering of components that have not changed?

Upvotes: 1

Riya Patadiya
Riya Patadiya

Reputation: 255

To prevent re-rendering of reusable component while changing other states, We can use React.memo()

const MainArea = React.useMemo(() => {
return <div />;
});
const Footer = React.useMemo(() => {
   return <div />;
});
const App = () => {
   const [showMenu,setshowMenu]=useState(false)

   return(
      <>
      <Header showMenu={showMenu} setShowMenu={setShowMenu}/>
      <MainArea/>
      {showMenu ? <Menu/> : null}
      <Footer/>
      </>
  )
}

Upvotes: -3

Mila A
Mila A

Reputation: 569

You can use useMemo hook.

It prevents specific jsx contents from rerendering, even when the state that those jsx contents/components use get updated.


const App=()=>{
// you can only memoize parts that do not require use of the updated variable in this case. It means that Header cannot be memoized.

const mainArea = React.useMemo( () => <MainArea/>, [] );

const footer = React.useMemo( () => <Footer/>, [] );

   const [showMenu,setShowMenu]=useState(false)
   

 return(
     <>

     <Header showMenu={showMenu} setShowMenu={setShowMenu}/>

     {mainArea}

     {showMenu ? <Menu/> : null}

     {footer}

    </>
 )

}

EDIT:

Does the really need the state of the showMenu? Or we can only pass the setShowMenu to it? If so, then you can also memoize the Header component into memo chunk like:

const header = React.useMemo( () => , [] );

Upvotes: 22

fgkolf
fgkolf

Reputation: 1065

You can use React memo (or PureComponent if you use classes) on the components that you don't want to re-render (MainArea,Footer). This way when an update is forced by their parent they will first make a check if any of their props changed and if not (which is your case), re-render will be skipped.

However it's advisable to perform memoization on expensive components only instead of wrapping everything with React.memo, because memoization also introduces some overhead.

Upvotes: 3

Related Questions