Search code examples
javascriptreactjstypeerrorvantajs

React - TypeError: Cannot read properties of null (reading 'vanta')


I learning React and building a simple portfolio in the process. I have incorporated a vanta.js animated background for my home screen, but after implementing a Navigation Bar, I am getting the error: TypeError: Cannot read properties of null (reading 'vanta'). The error happens when switching to a page that is not my Home page, which is the only page where the animated background should be visible.

This is my App.js:

import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./components/Home";
import Navbar from "./components/Navbar";
import Projects from "./components/Projects";

export default function App() {
  return (
    <main className="flex flex-col m-0 w-screen h-screen bg-gray-50 body-font text-gray-600 font-display">
      <BrowserRouter>
        <Navbar />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/projects" element={<Projects />} />
        </Routes>
      </BrowserRouter>
      
    </main>
  );
}

This is my Home.js, where the vanta.js background is incorporated. I don't quite understand why the vanta.js implementation from this file is accessed whenever I switch to a new page:

import React, { useRef, useEffect } from "react";
import * as THREE from "three"; // Importing THREE.js
import TRUNK from "vanta/dist/vanta.trunk.min"; // Importing the vanta effect

export default function Home() {
    const myRef = useRef(null);

    useEffect(() => {
      TRUNK({
        THREE: THREE,
        el: myRef.current,
        mouseControls: true,
        touchControls: true,
        gyroControls: false,
        minHeight: 200.00,
        minWidth: 200.00,
        scale: 1.00,
        scaleMobile: 1.00,
        color: 0x3B82F6,
        backgroundColor: 0xF9FAFB
      });
  
      return () => {
        if (myRef.current.vanta) { // <-- ERROR HAPPENS HERE
          myRef.current.vanta.destroy();
        }
      };
    }, []);

    return (
      <section id="about" ref={myRef} className="flex-1">
        <div className="absolute container min-h-full min-w-full mx-auto my-auto bg-gray-50 z-10 lg:opacity-10 opacity-70"></div>
        <div className="container h-full w-full mx-auto my-auto flex px-10 py-20 md:flex-row flex-col items-center justify-center z-20">
          <div className="lg:flex-grow lg:w-1/2 lg:pr-24 flex flex-col lg:items-start lg:text-left mb-16 lg:mb-0 items-center justify-center text-center">
            <h1 className="title-font lg:text-5xl text-4xl mb-2 font-extrabold text-blue-500">
              NAME HERE
            </h1>
            <p className="mb-4 leading-relaxed lg:text-base text-sm font-normal">
              Developer
            </p>
            </div>
          </div>
        </div>
      </section>
    );
  }

The error must be in one of the above files, but if needed, here is my Navbar.js:

import React from "react";
import {  Link } from "react-router-dom";

export default function Navbar() {
  return (
    <header className="bg-gray-50 top-0 z-10">
      <div className="container mx-auto flex p-5 flex-col items-end">
        <nav className="md:mr-4 md:py-1 md:pl-4 flex flex-wrap items-center text-base justify-center">
          <Link to="/" className="mr-5 hover:border-blue-500 border-2 px-4 py-1 rounded-full  hover:bg-blue-500 hover:text-white ease-in-out hover:ease-in-out duration-150">
            <p>Home</p>
          </Link>
          <Link to="/projects" className="mr-5 hover:border-blue-500 border-2 px-4 py-1 rounded-full hover:bg-blue-500 hover:text-white ease-in-out hover:ease-in-out duration-150">
            <p>Projects</p>
          </Link>
        </nav>
      </div>
    </header>
  );
}

Any help is appreciated, thanks!


Solution

  • I managed to find a fix. There was an error in my implementation of vanta.js. This documentation of implementation with React helped me. Here is the updated code to make it work in my Home.js:

    export default function Home() {
        const [vantaEffect, setVantaEffect] = useState(0); // Added this + import useState
        const myRef = useRef(null);
    
        useEffect(() => {
          if(!vantaEffect) { // <-- Added this conditional
            TRUNK({
              THREE: THREE,
              el: myRef.current,
              mouseControls: true,
              touchControls: true,
              gyroControls: false,
              minHeight: 200.00,
              minWidth: 200.00,
              scale: 1.00,
              scaleMobile: 1.00,
              color: 0x3B82F6,
              backgroundColor: 0xF9FAFB
            });
          }
    
      
          return () => {
            if (vantaEffect) { // <-- Used vantaEffect here
              vantaEffect.destroy();
            }
          };
        }, []);
    
        return ( ... );
      }