Skip to content
Advertisement

404 on page refresh in NextJS with p5.js

I’m using the react-p5 library for generating PerlinNoise wave animation in my about page. When I use the p5 on any page it returns a 404 page, but if click back to the home page and open about.js using the link it will work. After refresh, it won’t work.

Everything works if I remove the p5 component from the file. I think the problem is with the p5 or p5 import.

about.js

import React from 'react'
// Importing Sketch
import Sketch from 'react-p5'


export default function about() {

// Setup for creating canvas
    const setup = (p5, canvasParentRef) => {
        p5.createCanvas(p5.windowWidth, 100).parent(canvasParentRef)
    }
    let inc = 0.005;
    let start = 0;

// Function to draw the wave
    const draw = p5 => {
        p5.background('rgba(255,255,255)')
        p5.stroke('rgb(0,0,0)');
        p5.noFill();
        p5.beginShape();
        let xoff = start;
        for (let x = 0; x < p5.width; x++) {
            p5.stroke('#000');
            let y = p5.noise(xoff) * p5.height;
            p5.vertex(x, y);
            xoff += inc;
        }
        p5.endShape();
        start += inc;
    }

    return (
        <>
// Returning Sketch Component
            <Sketch setup={setup} draw={draw} />
        </>
    )
}

Project Structure :

Here

Advertisement

Answer

The problem is that Sketch component is wanting to access window property, but window is undefined since we serve server side rendered About page.

How to get around this?

Best solution would be to create a separated component, we can call it DrawSketch

DrawSketch component is almost identical to your About page with exception that it is a component.

import React from "react";
import Sketch from "react-p5";

export default function DrawSketch() {
  const setup = (p5, canvasParentRef) => {
    p5.createCanvas(p5.windowWidth, 100).parent(canvasParentRef);
  };
  let inc = 0.005;
  let start = 0;

  // Function to draw the wave
  const draw = (p5) => {
    p5.background("rgba(255,255,255)");
    p5.stroke("rgb(0,0,0)");
    p5.noFill();
    p5.beginShape();
    let xoff = start;
    for (let x = 0; x < p5.width; x++) {
      p5.stroke("#000");
      let y = p5.noise(xoff) * p5.height;
      p5.vertex(x, y);
      xoff += inc;
    }
    p5.endShape();
    start += inc;
  };

  return <Sketch setup={setup} draw={draw} />;
}

Next thing we want is to make sure that we will client side server our DrawSketch component, so it can has access to window property.

In next.js you can use dynamic imports

Next.js supports ES2020 dynamic import() for JavaScript. With it you can import JavaScript modules dynamically and work with them. They also work with SSR.

Next step would be importing DrawSketch component we created inside your About view and declare it as dynamic component which is not server side rendered.

import React from "react";
import dynamic from "next/dynamic";

const ClientSideSketch = dynamic(() => import("../components/DrawSketch"), {
  ssr: false
});

export default function AboutPage() {

  return (
    <>
      <ClientSideSketch />
    </>
  );
}

I have edited codesandbox, so you can see working live example.

10 People found this is helpful
Advertisement