Erratic Generator

Creative Coding and Design

About

Window Is Not Defined Error

An error while using gatsbyjs and p5js together

Photo by https://unsplash.com/photos/eQQI_HzT9RE
Photo by https://unsplash.com/photos/eQQI_HzT9RE

You may have encountered the error, window is not defined while working with gatsbyjs/reactjs and frontend libraries such as p5js that relies on window object to draw graphics. Here is how I was able to get around the issue without relying on another package.

A bit of background

I use react-p5-wrapper module when I work with p5js and React together. (I will maybe make another post on how to use this module.) I have not had this window issue so far, probably because React does clien-side rendering. But Gatsbyjs is a bit different.

Gatsbyjs is a static site generator, which means it does not require backend server to host your website, but when it builds the static site from your local machine (or from the cloud), it does use server-side rendering with Node.js, so when the server building your website is reading and executing your code and it finds you are using the window object, it will throw an error because the server is not a browser, and it does not have the window.

The workaround is to skip this bit of code running when building the website. By the time your website is executed on the client side by your users, they are using a browser so the window will be available and the code will run fine.

It worked when I was developing, though.

What was frustrating to me was that my project was working totally fine when I was developing with gatsby develop. The problem will only surface up when you gatsby build. It's usually when you are really tired late at night and just trying the wrap up the day by deploying the website right before you go to bed. Then the error message... Window is not defined!

There were many suggestions online, which I will link to below. One used loadable package, etc., but I did not want to add another dependency just to solve this problem. So I ended up using React.lazy method. I used Gatsby version 4.

How I solved it

I said earlier that I use react-p5-wrapper. Typically this is how I would import it:

import { ReactP5Wrapper } from 'react-p5-wrapper'

But because p5 relies on window and Gatsbyjs will try to import this with server at build time, it will throw an error, window is not defined.

So we will use React.lazy().

const ReactP5Wrapper = React.lazy(() => 
  import('react-p5-wrapper).then(module => ({
    default: module.ReactP5Wrapper
  }))
)

I have to admit this looks kinda crazy for just a simple import statement, but there is a reason. According to the React Documentation, the React.lazy function lets you render a dynamic import as a regular component. But the component has to be default export, and our react-p5-wrapper is not a default export. That's why we need then statement to get the proper module.

So, the import works now, then how do we use the component in our app? It's also well-documented in the React website. Just wrap the component around with <Suspense>.

import React from 'react'
import sketch from '../mysketch' // p5js sketch
const ReactP5Wrapper = React.lazy(() => 
  import('react-p5-wrapper).then(module => ({
    default: module.ReactP5Wrapper
  }))
)

//... in some component
function MyComponent() {
  return (
    <>
      <React.Suspense fallback={<div>Loading...</div>}>
        <ReactP5Wrapper sketch={sketch} />
      </React.Suspense>
    </>
  );
}

You should also check whether it's currently rendering server side or not by adding a condition:

function MyComponent() {
  const isSSR = typeof window === 'undefined'

  return (
    <>
      {!isSSR && (
        <React.Suspense fallback={<div>Loading...</div>}>
          <ReactP5Wrapper sketch={sketch} />
        </React.Suspense>
      )}
    </>
  );
}

Other possible solutions

Here are resources I found online. My solution is based on Gatsby's guides. Other solutions, unfortunately, were too complex for my liking or did not work for me, but I will leave theme here for future reference.

I publish the same articles on Medium, but they are behind the paywall. Your support will help me keep this website open to everyone. If you liked my contents, please consider supporting. Thank you!

Buy Me a Coffee at ko-fi.com
Copyright 2020-2021 • ErraticGenerator.com • Our Privacy Policy