I am trying to trigger a transition/movement for a React Three drei component on initial page load by accessing its ref in a useEffect
function. Within the useEffect
on initial load the useRef
is still null.
import React, { useRef useEffect, Suspense } from 'react';
import { Canvas } from '@react-three/fiber';
import { Cylinder, OrbitControls } from '@react-three/drei';
import gsap from 'gsap';
function Section() {
const cylinderRef = useRef(null);
useEffect(()=>{
if(!!cylinderRef.current){ //At this check cylinderRef.current is still null
// The movement is executed here with gsap.timeline
// which needs to access the cylinderRef.current
const timeLine = gsap.timeline({paused:true});
timeLine.to(cylinderRef.current.position, {
y: .7,
duration: 3,
ease: "power2.out",
});
timeLine.play();
};
}, [cylinderRef.current]); // Adding this parameter to useEffect did not help
return(
<Canvas>
<Suspense fallback={<></>}>
<mesh position={[0,2,0]} ref={cylinderRef}>
<Cylinder scale={[0.9, 0.5, 0.9]}>
<meshStandardMaterial color={"#545755"} roughness={0.7}/>
</Cylinder>
</mesh>
<OrbitControls enableZoom={false} autoRotate={false}/>
<ambientLight intensity={1}/>
<directionalLight position={[3,2,1]}/>
</Suspense>
</Canvas>
)
}
I have seen some talk about using a useCallback
in a similar situation, but I am not exactly sure that is the right solution for this use case and for function based components.
The issue still happens with or without the Suspense component, which will eventually be used to display a loading icon.
Work-around for me was using the onStart callback to set the mouseButtons. For you, this would be the onChange callback.
export default function App() {
const handleStart = (ev) => {
ev.target.mouseButtons.left = ACTION.TRUCK;
};
return (
<div className="App">
<Canvas>
<orthographicCamera />
<CameraControls onStart={handleStart} />
</Canvas>
</div>
);
}