Keep Component from Rerendering with Custom Hooks

665 Views Asked by At

I have a custom hook useWindowSize that listens to changes of the window size. Once the window size is below a certain threshold, some text should disappear in the Menu. This is implemented in another custom hook useSmallWindowWidth that takes the returned value of useWindowSize and checks whether it is smaller than the threshold.

However, even though only the nested state changes, my component rerenders constantly when the window size changes. Rerendering the menu takes about 50ms on average which adds up if I want to make other components responsive as well.

So how could I keep the component from rerendering? I tried React.memo by passing return prev.smallWindow === next.smallWindow; inside a function, but it didnt work.

My attempt so far:

//this hook is taken from: https://stackoverflow.com/questions/19014250/rerender-view-on-browser-resize-with-react

function useWindowSize() {     
    const [size, setSize] = useState([0, 0]);
    useLayoutEffect(() => {
      function updateSize() {
        setSize([window.innerWidth, window.innerHeight]);
      }
      window.addEventListener('resize', updateSize);
      updateSize();
      return () => window.removeEventListener('resize', updateSize);
    }, []);
    return size;
  }

function useSmallWindowWidth() {
  const [width] = useWindowSize();
  const smallWindowBreakpoint = 1024;
  return width < smallWindowBreakpoint;
}

function Menu() {
  const smallWindow = useSmallWindowWidth();
  return (
    <div>
      <MenuItem>
        <InformationIcon/>
        {smallWindow && <span>Information</span>}
      </MenuItem>
      <MenuItem>
        <MenuIcon/>
        {smallWindow && <span>Menu</span>}
      </MenuItem>
    </div>
  );
}
1

There are 1 best solutions below

2
On BEST ANSWER

You can try wrapping all your JSX inside a useMemo

function App() {
  return useMemo(() => {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
      </div>
    );
  }, []);
}

Put in the array in the second argument of the useMemo what variable should make your jsx rerender. If an empty array is set (like in the exemple), the jsx never rerenders.