How to detect window size in Next.js SSR using react hook?
Solution 1
You can avoid calling your detection function in ssr by adding this code:
// make sure your function is being called in client side only
if (typeof window !== 'undefined') {
// detect window screen width function
}
full example from your link:
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(() => {
// only execute all the code below in client side
if (typeof window !== 'undefined') {
// 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;
}
Solution 2
While Darryl RN has provided an absolutely correct answer. I'd like to make a small remark: You don't really need to check for the existence of the window
object inside useEffect
because useEffect
only runs client-side and never server-side, and the window
object is always available on the client-side.
Comments
-
GoonGamja almost 2 years
I am building an app using Next.js and react-dates.
I have two component DateRangePicker component and DayPickerRangeController component.
I want to render DateRangePicker when the window's width is bigger than size 1180px, if the size is smaller than this I want to render DayPickerRangeController instead.
Here is the code:
windowSize > 1180 ? <DateRangePicker startDatePlaceholderText="Start" startDate={startDate} startDateId="startDate" onDatesChange={handleOnDateChange} endDate={endDate} endDateId="endDate" focusedInput={focus} transitionDuration={0} onFocusChange={(focusedInput) => { if (!focusedInput) { setFocus("startDate") } else { setFocus(focusedInput) } }} /> : <DayPickerRangeController isOutsideRange={day => isInclusivelyBeforeDay(day, moment().add(-1, 'days'))} startDate={startDate} onDatesChange={handleOnDateChange} endDate={endDate} focusedInput={focus} onFocusChange={(focusedInput) => { if (!focusedInput) { setFocus("startDate") } else { setFocus(focusedInput) } }} /> }
I normally use react hook with window object to detect window screen width like this
But I found that this way is not available when ssr because ssr rendering does not have window object.
Is there an alternative way I can get window size safely regardless of ssr?