Search code examples
reactjsreact-three-fiber

React Three Fiber / How Can access child position inside the useFrame Hook?


I made a simple Earth sphere rotating around 0 axis. Then I have added a child (the moon) but I can't figure if it is possible to also modify its position inside the useFrame hook of the Earth.


    const Earth = (props) => {
    
        const ref = useRef()
        const texture = useLoader(THREE.TextureLoader, "/03earth.jpg")
        const coef = 0.1
        const delta = 6
        useFrame(state => {
            ref.current.rotation.y += 0.01
            ref.current.position.x = Math.cos(state.clock.elapsedTime * coef) * delta
            ref.current.position.z = Math.sin(state.clock.elapsedTime * coef) * delta
    
        })
    
        return (
            <mesh ref={ref} {...props} castShadow receiveShadow>
                <sphereGeometry />
                <meshPhysicalMaterial map={texture} />
                <Moon/> )

Solution

  • you can access sub components by specifying their index in children:

    import "./styles.css";
    import React, { useRef } from "react";
    import { Canvas, useFrame } from "@react-three/fiber";
    import { OrbitControls } from "@react-three/drei";
    import * as THREE from "three";
    
    export default function App() {
      return (
        <div className="App" style={{ width: "100vw", height: "100vh" }}>
          <Canvas>
            <OrbitControls />
            <Earth />
          </Canvas>
        </div>
      );
    }
    
    const Earth: React.FC = () => {
      const ref = useRef(null);
      useFrame((state) => {
        ref.current.rotation.y = state.clock.getElapsedTime();
        // Here 
        ref.current.children[0].position.y = Math.sin(state.clock.getElapsedTime());
      });
      return (
        <mesh ref={ref}>
          <sphereGeometry args={[1, 32, 32]} />
          <meshNormalMaterial />
          <mesh position={[1, 1, 1]}>
            <sphereGeometry args={[0.2, 32, 32]} />
            <meshNormalMaterial />
          </mesh>
        </mesh>
      );
    };
    

    sandbox https://codesandbox.io/s/inspiring-rgb-ry2f1h?file=/src/App.tsx