Reputation: 87
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
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
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