WebpackError: window is not defined

Viewed 3614

I am experiencing the same issue here, Coverflow works fine for gatsby develop but for build it throws an error: WebpackError: window is not defined

WebpackError: window is not defined

     - react-coverflow.js:1 Object.<anonymous>
       ~/react-coverflow/dist/react-coverflow.js:1:330

     - main.js:1 Object.<anonymous>
       ~/react-coverflow/main.js:1:1

I think it is caused by the this library "Coverflow"

import Coverflow from 'react-coverflow';
import { StyleRoot } from 'radium'

class Team extends React.Component {

  render(){
    return(
      <StyleRoot>
      <Coverflow
        displayQuantityOfSide={2}
        navigation
        infiniteScroll
        enableHeading
        active={0}
        media={{
          '@media (max-width: 720px)': {
            width: '100%',
            height: '200px'
          },
          '@media (min-width: 720px)': {
            width: '100%',
            height: '400px',
          }
        }}
      >
        <img src={Sandiso} alt='Chairperson'/>
        <img src={Sihle} alt='Deputy Chairperson' />
        <img src={olwethu} alt='General Secretary' />
        <img src={Aphiwe} alt='Recording Secretary'/>
        <img src={cynoh} alt='Treasury'/>
        <img src={aso} alt='Marketing' />

      </Coverflow>
    </StyleRoot>
    )
  }
}

export default Team;
2 Answers

Haven't looked fully into the other suggested answer re: React.Lazy and Suspense, but ran up against a similar problem trying to instantiate Intersection Observer and found a simpler answer in Kyle Matthew's response to this issue:

https://github.com/gatsbyjs/gatsby/issues/309#issuecomment-223360361

That is—potentially, you can import your package or whatever is looking for window in the componentDidMount method (or a useEffect hook) of your component.

The package 'react-coverflow' is probably expecting itself to be run on browser, which is why gatsby yells at you when it tries to render the component on server side. If you're using Gatsby v2 which seems to ship with react^16.6, you could dynamically load the component with React's lazy and Suspense combo:

// src/components/coverflow.js
import React from 'react'
import Coverflow from 'react-coverflow'

export default () => (
  <Coverflow>
    {/* your coverflow setup */}
  </Coverflow>
)

Then you can lazy load the component on a page like this:

// src/pages/index.js

const LazyCoverflow = () => {
  if (typeof window === 'undefined') return <span>loading...</span>
  const Component = lazy(() => import('../components/coverflow'))
  return (
    <>
      <Suspense fallback={<span>loading...</span>}>
        <Component />
      </Suspense>
    </>
  )
}

export default () => (
  <Layout>
    {/* other components */}
    <LazyCoverflow />
  </Layout>
)

Check out the lazy & Suspense doc on reactjs.org.

Related