You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-three-fiber封装组件props变更时Mesh位置未更新问题求助

Hey there! Let's break down what's going wrong here and fix it step by step—you're pretty close, just missing some key React and react-three-fiber conventions.

First, Let's Identify the Issues

  1. Directly modifying props is a React no-no
    In your App.js, you're doing cube.current.props.position[0] = debugObject.position.x to update the position. React props are read-only, and since you're only changing an element inside the existing array (not creating a new array reference), React can't detect this change. That's why your Cube component never re-renders with the new position.

  2. Cube component's state logic is unnecessary and broken
    You're storing the position prop in the component's state, but your componentDidUpdate check is comparing prevProps.position[0] to this.state.position[0]—this creates a confusing loop, and there's no need to duplicate props in state here anyway. react-three-fiber handles mesh property updates automatically when props change.

  3. Misusing refs for class components
    The ref you're using on the Cube class component gives you the component instance, not direct access to modify props. This isn't the right way to trigger updates in React.

Let's Fix the Code

Step 1: Update App.js to use proper state management

We'll use React's useState to track the cube position, so dat.gui changes trigger proper React state updates:

import { OrbitControls } from "@react-three/drei";
import { Canvas } from '@react-three/fiber';
import * as dat from 'dat.gui';
import { useEffect, useState } from 'react';
import './App.css';
import Lights from './components/Lights';
import Cube from './components/Cube';

function App() {
  // Track cube position with React state
  const [cubePosition, setCubePosition] = useState([0, 0, 0]);

  useEffect(() => {
    const gui = new dat.GUI({ width: 400 });
    const debugObject = {
      position: {
        x: cubePosition[0],
        y: cubePosition[1],
        z: cubePosition[2],
      }
    };

    // Sync x control to state
    gui.add(debugObject.position, "x")
      .min(-10)
      .max(10)
      .step(0.1)
      .onChange((value) => {
        // Create a new array to trigger React's change detection
        setCubePosition(prev => [value, prev[1], prev[2]]);
    });

    // Add y and z controls too (optional but useful)
    gui.add(debugObject.position, "y")
      .min(-10)
      .max(10)
      .step(0.1)
      .onChange((value) => {
        setCubePosition(prev => [prev[0], value, prev[2]]);
    });

    gui.add(debugObject.position, "z")
      .min(-10)
      .max(10)
      .step(0.1)
      .onChange((value) => {
        setCubePosition(prev => [prev[0], prev[1], value]);
    });

    return () => gui.destroy();
  }, []); // Empty dependency array runs this once on mount

  return (
    <div className="App">
      <Canvas camera={{ fov: 75, aspect: 2, near: 0.1, far: 1000, position: [0,0,20] }} >
        <color attach="background" args={["#161c24"]}/>
        <Lights/>
        {/* Pass the state position to Cube as a prop */}
        <Cube position={cubePosition}/>
        <OrbitControls/>
      </Canvas>
    </div>
  );
}

export default App;

Step 2: Simplify the Cube Component

You don't need a class component or local state here—just pass the position prop directly to the mesh. react-three-fiber will handle updating the mesh's position automatically when the prop changes.

Option 1: Convert to a function component (recommended for react-three-fiber):

import React from "react";

function Cube({ position }) {
  return(
    <mesh position={position} onUpdate={() => console.log("Mesh position updated!")}>
      <boxGeometry attach="geometry" args={[0.5,0.5,0.5]}/>
      <meshStandardMaterial attach="material" color="#ff0000"/>
    </mesh>
  )
}

export default Cube;

Option 2: Fix the class component if you prefer:

import React from "react";

class Cube extends React.Component {
  render() {
    // Use props directly instead of local state
    return(
      <mesh position={this.props.position} onUpdate={() => console.log("Mesh position updated!")}>
        <boxGeometry attach="geometry" args={[0.5,0.5,0.5]}/>
        <meshStandardMaterial attach="material" color="#ff0000"/>
      </mesh>
    )
  }
}

export default Cube;

Why This Works

  • By using useState in App.js, we're following React's one-way data flow: when dat.gui changes the value, we update the state, which triggers a re-render and passes the new position prop to Cube.
  • The Cube component no longer needs to manage its own state—react-three-fiber detects when the position prop changes and updates the underlying mesh automatically.
  • We've eliminated the broken componentDidUpdate logic and avoided modifying props directly, which keeps your code aligned with React best practices.

内容的提问来源于stack exchange,提问作者Ezequiel Gonzalez Macho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:57:40