How to detect window size in Next.js SSR using react hook?

25,708

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.

Share:
25,708
GoonGamja
Author by

GoonGamja

meow

Updated on July 09, 2022

Comments

  • GoonGamja
    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?