React Hook recipe from https://usehooks.com. Demo: https://codesandbox.io/s/jj61r2w6z5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useState, useEffect } from 'react'; | |
// Usage | |
function App() { | |
const size = useWindowSize(); | |
return ( | |
<div> | |
{size.width}px / {size.height}px | |
</div> | |
); | |
} | |
// Hook | |
function useWindowSize() { | |
// Initialize state with undefined width/height so server and client renders match | |
// Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/ | |
const [windowSize, setWindowSize] = useState({ | |
width: undefined, | |
height: undefined, | |
}); | |
useEffect(() => { | |
// Handler to call on window resize | |
function handleResize() { | |
// Set window width/height to state | |
setWindowSize({ | |
width: window.innerWidth, | |
height: window.innerHeight, | |
}); | |
} | |
// Add event listener | |
window.addEventListener("resize", handleResize); | |
// Call handler right away so state gets updated with initial window size | |
handleResize(); | |
// Remove event listener on cleanup | |
return () => window.removeEventListener("resize", handleResize); | |
}, []); // Empty array ensures that effect is only run on mount | |
return windowSize; | |
} |
change the useEffect
to useLayoutEffect
because you see a flicker before it's set in some cases. useLayoutEffect
is definitely the way to go here. Here an example where a div is centered based on the body, if you change it to a normal useEffect
you will see it flicker. https://codesandbox.io/s/still-wave-q0pk7
Long time has passed , why haven't this been updated with debounce or throttle ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello! 👋🏻
This code has an issue with server rendering. I ran in to a similar issue here: gatsbyjs/gatsby#14601
The underlying issue is in
getSize
The problem is that the server render value of
windowSize
and the first client render won't match. (eg,width
on the server will beundefined
, client will bewindow.innerWidth
). This confuses React and you will see incorrect values on first load, as described in the github issue above and demonstrated here on a large screen: http://mikelambert.me/gatsby-bug/To fix this, I modified the hook to always initialize the values to
undefined
(so the server render and first client render match) and to update the values after the first render on the client.