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
Directly modifying props is a React no-no
In your App.js, you're doingcube.current.props.position[0] = debugObject.position.xto 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.Cube component's state logic is unnecessary and broken
You're storing thepositionprop in the component's state, but yourcomponentDidUpdatecheck is comparingprevProps.position[0]tothis.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.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
useStatein 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
positionprop changes and updates the underlying mesh automatically. - We've eliminated the broken
componentDidUpdatelogic and avoided modifying props directly, which keeps your code aligned with React best practices.
内容的提问来源于stack exchange,提问作者Ezequiel Gonzalez Macho

