My website deploys fine on desktop, but only renders the background color on smaller devices. How do I fix it?

I created a portfolio website and deployed it on Netlify.

Here’s the GitHub repo: GitHub - AnukratiMehta/portfolio-website

Here’s the Netlify address: https://anukratimehta.netlify.app

The website renders perfectly fine on desktop but has been giving me trouble on smaller devices. I faced the same issue when deploying with GitHub pages as well, so I know the issue is with the website, not the hosting service.

After testing, I realized the issue is with my Kaleidoscope component. When I comment it out from the website completely and push the changes, the website opens as expected on mobile devices. I want to understand how I can fix the component to be able to render the website with it on smaller devices too.

import React, { useRef, useEffect, useState } from 'react';
import p5 from 'p5';

function Kaleidoscope() {
  let canvasRef = useRef(null);
  let sketchCreated = false;

  useEffect(() => {
    if (!sketchCreated) {
      new p5(sketch, canvasRef.current);
      sketchCreated = true;
    }
  }, []);

  const [p5Instance, setP5Instance] = useState(null);
  const [color, setColor] = useState("#57cbff");

  function handleReset() {
    if (p5Instance) {
      p5Instance.clear();
    }
  }


  function handlePink() {
    setColor("#f57dff");
    p5Instance.stroke("#f57dff");
  }

  function handleBlue() {
    setColor("#57cbff");
    p5Instance.stroke("#57cbff");
  }

  function handleYellow() {
    setColor("#e8ff64");
    p5Instance.stroke("#e8ff64");
  }

  function sketch(p) {
    let symmetry;
    let angle;

    p.setup = function () {
      if (!sketchCreated) {
        new p5(sketch, canvasRef.current);
        sketchCreated = true;
      }

      symmetry = 6;
      angle = 360 / symmetry;
      p.createCanvas(350, 350);
      p.angleMode(p.DEGREES);
      p.stroke(color);

      setP5Instance(p);
    };


    p.draw = function () {
      p.translate(p.width / 2, p.height / 2);

      if (p.mouseX > 0 && p.mouseX < p.width && p.mouseY > 0 && p.mouseY < p.height) {
        let mx = p.mouseX - p.width / 2;
        let my = p.mouseY - p.height / 2;
        let pmx = p.pmouseX - p.width / 2;
        let pmy = p.pmouseY - p.height / 2;

        if (p.mouseIsPressed) {
          for (let i = 0; i < symmetry; i++) {
            p.rotate(angle);
            p.line(mx, my, pmx, pmy);
            p.push();
            p.scale(1, -1);
            p.line(mx, my, pmx, pmy);
            p.pop();
          }
        }
      }
    };
  }

  return (
    <div className='flex flex-col'>
      <div className='my-5' style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
        <h1 className='text-2xl text-center text-lightest-slate ml-5'>Draw on Me ↓</h1>
        <button onClick={handleReset} onTouchStart={handleReset} className="text-green border border-green rounded-md text-lg px-5 py-2.5 hover:text-green hover:bg-lightest-navy transition-all ease-in-out duration-200 cursor-pointer text-center mx-8">Reset</button>
      </div>
      <div className="kaleidoscope-container" style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
        <div ref={canvasRef} style={{ border: '3px solid rgba(73, 86, 112, 0.102)', borderRadius: '5px', padding: '5px' }} />
      </div>
      <div className='m-5' style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
        <button
          onClick={handleBlue}
          onTouchStart={handleBlue}
          className={`text-green border border-green rounded-md text-lg px-5 py-2.5 hover:text-green hover:bg-lightest-navy transition-all ease-in-out duration-200 cursor-pointer text-center mx-3 ${color === "#57cbff" ? "selected" : ""
            }`}
        >
          Blue
        </button>

        <button
          onClick={handleYellow}
          onTouchStart={handleYellow}
          className={`text-green border border-green rounded-md text-lg px-5 py-2.5 hover:text-green hover:bg-lightest-navy transition-all ease-in-out duration-200 cursor-pointer text-center mx-3 ${color === "#e8ff64" ? "selected" : ""
            }`}
        >
          Yellow
        </button>
        <button
          onClick={handlePink}
          onTouchStart={handlePink}
          className={`text-green border border-green rounded-md text-lg px-5 py-2.5 hover:text-green hover:bg-lightest-navy transition-all ease-in-out duration-200 cursor-pointer text-center mx-3 ${color === "#f57dff" ? "selected" : ""
            }`}
        >
          Pink
        </button>
      </div>
    </div>
  );

}

export default Kaleidoscope;

So far, I’ve tried:

  • Making the canvas size responsive instead of 350*350
  • Adding onTouchStart along with onClick
  • Hiding the component on smaller devices

None of these worked. The website still worked fine on desktops and only rendered the background on mobiles and tablets. Can you offer any fixes? Please let me know if you need more details. TIA!

@anukratim The Netlify support forums aren’t a great place to seek general coding assistance, they’re for getting assistance with Netlify’s products & services.

That said, I can’t see anything when loading your site, (no matter the viewport size).

This is because of the error shown in the developer console:

image

When you run your build you will notice it says:

Compiled with warnings.

The warning is:

src/components/Kaleidoscope.jsx
  Line 11:23:  Assignments to the 'sketchCreated' variable from inside
  React Hook useEffect will be lost after each render. To preserve the
  value over time, store it in a useRef Hook and keep the mutable
  value in the '.current' property. Otherwise, you can move this
  variable directly inside useEffect react-hooks/exhaustive-deps

So one issue you have is that you’re using a boolean value to guard against repeated executions, but that variable is never actually being set due to the behaviour of the system you’ve chosen (react).

The true cause of the issue isn’t how it’s being guarded against though, but that you’re creating a p5 instance inside of the setup of the p5 instance…

  1. useEffect is creating a p5 instance, giving it sketch and p5 then executes p.setup
  2. the p.setup function creates a new p5 instance that is given sketch and calls p.setup
  3. the p.setup function creates a new p5 instance that is given sketch and calls p.setup
  4. the p.setup function creates a new p5 instance that is given sketch and calls p.setup
  5. … etc

So if you delete the instance creation from inside of p.setup it will execute only once.

Thanks a lot, @nathanmartin. This worked! My site works on all devices now.

Thanks so much for confirming that nathans solution got your site working. This is exciting and i’m grateful community members like @nathanmartin can be so helpful.