Search code examples
reactjsgatsby

Gatsby build fails because window is undefined in a React hook


I have a custom hook which checks the window width to conditionally render some UI elements. It works ok during development, but fails on Gatsby build.

Here is the code for my hook:

export const useViewport = () => {
  const [width, setWidth] = React.useState(window.innerWidth);

  React.useEffect(() => {
    const handleWindowResize = () => setWidth(window.innerWidth);
    window.addEventListener("resize", handleWindowResize);
    return () => window.removeEventListener("resize", handleWindowResize);
  }, []);

  // Return the width so we can use it in our components
  return { width };
}

Then in my component I use it like this:

const { width } = useViewport();
const breakpoint = 767

/** in JSX **/

{
  width > breakpoint ? <Menu {...props} /> : <Drawer {...props} />
}

According to Gatsby docs window is not available during the build process. I've tried to if (typeof window !== 'undefined') condition to the hook, but I get the following error:

Cannot destructure property 'width' of 'Object(...)(.  ..)' as it is undefined

I've also tried to wrap const { width } = useViewport() in React.useEffect hook, but then I get an error that width in my JSX is undefined.

How can I fix this problem?


Solution

  • See few solutions here

    Specially this one:

    You'd need to adjust the hook itself. Defining default values in the outside scope and using them as default state should do the trick: