mrtyvz61
mrtyvz61

Reputation: 87

How do I prevent component rerendering on browser resize?

In main layout component there is 2 different component which is MobileHeader and DesktopHeader when resize the browser it rerender these components every resize action. How to stop to render again and again when resize the browser ?

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;
}

const MainLayout = () => {
     const [w,h] = useWindowSize();
     return(
       <>
         {w > 992 ? <DesktopHeader/> : <MobileHeader/>}
       </>
     )
}

Upvotes: 4

Views: 4260

Answers (2)

Drew Reese
Drew Reese

Reputation: 202605

I would just debounce the updateSize function so the "resize" handler calls that instead and doesn't wail on your React component state updates.

Using a debouncing utility from a tried and tested library is probably best, i.e. debounce from lodash. I'm using a 200ms delay, but obviously you should test this and tune this delay value to suit your needs.

import { debounce } from 'lodash';

function useWindowSize() {
  const [size, setSize] = useState([0, 0]);

  useLayoutEffect(() => {
    function updateSize() {
      setSize([window.innerWidth, window.innerHeight]);
    }

    const debouncedUpdateSize = debounce(updateSize, 200);

    window.addEventListener('resize', debouncedUpdateSize);
    updateSize();
    return () => window.removeEventListener('resize', debouncedUpdateSize);
  }, []);

  return size;
}

If you don't want to add another dependency to your project you can roll your own simple debounce utility function.

const debounce = (fn, delay) => {
  let timerId;
  return (...args) => {
    clearTimeout(timerId);
    timerId = setTimeout(fn, delay, [...args]);
  };
};

Upvotes: 3

Dhruvi Makvana
Dhruvi Makvana

Reputation: 905

React will re-render your component when there is a change in state/props of the component. Your component is dependent on the window's dimension(width, height), so for every change on these dimensions, react will re-render the component.

You can use user make use of throttling/ debouncing based on your use case. Or simply you can integrate timeout.

Moreover, You can simply use the below javascript to identify the mobile devices and get rid of all these complex calculations.

if( /Android|webOS|iPhone|iPad|Mac|Macintosh|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
 // some code..
}

Upvotes: 1

Related Questions