Adam Maras
Adam Maras

Reputation: 1

Accurate loading screen React spline

I am rendering a spline model using next.js but "onLoad" does not accurately represent the loading time

import Spline from '@splinetool/react-spline';
import { useState } from 'react';


const Computer = () => {

    const [isPhoneLoading, setIsPhoneLoading] = useState(true);

    const handlePhoneLoad = () => {
        setIsPhoneLoading(false);
      };
    return (
    <>
        {isPhoneLoading && <p className='text-5xl'>Loading...</p>}
        <div className='flex h-96 w-full mt-20 mr-20 md:hidden'>
            <div className='w-full'>
                <Spline scene="https://prod.spline.design/jEOSwsR2XIbxiR7J/scene.splinecode" **onLoad={handlePhoneLoad}**/>
            </div>
        </div>
    
    </>
     );
}
 
export default Computer;
    "@splinetool/react-spline": "^2.2.6",
    "@splinetool/runtime": "^0.9.330",
    "spline": "^0.0.0",
    "@types/react": "18.2.6",
    "@types/react-dom": "18.2.4",
    "next": "13.4.1",

I have looked at the doc but nothing on there

Also tried this

const handlePhoneLoad = (e: { disposed: boolean; }) => {
    /* setIsPhoneLoading(false); */
    if (e.disposed)  {
        setIsPhoneLoading(false);
    }
  };

Upvotes: 0

Views: 1269

Answers (3)

Chester Corpuz
Chester Corpuz

Reputation: 1

You can use assign the spline to a ref and check for ref.current._scene.

import Spline from "@splinetool/react-spline";
import { useRef, useState } from "react";

export default function SplineScene () {

    const spline = useRef();
    const [loading, setLoading] = useState(true);

    const onLoad = (splineApp) => {
        spline.current = splineApp;
        if (spline.current._scene) {
           setLoading(false);
        }
    };

    return (
        <div>
        <Spline
         scene="https://...."
         onLoad={onLoad}
        />
        {loading && (<p>Loading...</p>)}
        </div>
    );
};

Upvotes: 0

virelox
virelox

Reputation: 41

My code

import { lazy, Suspense, useEffect, useState } from 'react';
const Spline = lazy(() => import('@splinetool/react-spline'));

export const Robot = () => {
const [splineLoading, setSplineLoading] = useState<boolean>(true);
return (
    <div className="flex w-screen h-screen absolute bg-opacity-100 z-[1]">
            <Suspense fallback={<div>Loading...</div>}>
                <Spline onLoad={() => setSplineLoading(false)} scene="#" />
                {splineLoading && (
                    //Loading icon or something
                )}
            </Suspense>
    </div>
);
};

Upvotes: 1

In next js 13 the lazy loading looks like this:

import dynamic from "next/dynamic";

const Spline = dynamic(() => import("@splinetool/react-spline"), {
  loading: () => <p>Loading...</p>,
});

Alternatively might help to use loading.tsx in the app.

export default function Loading() {
  return <div>Loading...</div>;
}

Or use the react way, but I'm not sure it won't mess up next13.

import { lazy, Suspense } from "react";
const Spline = lazy(() => import("@splinetool/react-spline"));

export default function Scene() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <Spline scene="https://..." />
      </Suspense>
    </div>
  );
}

PS: And don't forget to "use client";

Upvotes: 1

Related Questions