React Three Fiber报错:Hooks仅能在Canvas组件内使用问题排查
问题:React ThreeJS中使用useFrame报错“Hooks can only be used within the Canvas component!”
我正在用React结合ThreeJS制作带动画“hello”文字的立方体,但遇到报错:Hooks can only be used within the Canvas component!,明明已经加了Canvas组件,哪里错了?(React和ThreeJS新手)
原代码:
import React, { useRef } from "react"; import { PerspectiveCamera, RenderTexture, Text } from "@react-three/drei"; import { Canvas, useFrame } from "@react-three/fiber"; import styled from "styled-components"; const Container = styled.div` height: 100vh; width: 100%; scroll-snap-align: center; ` const Test = () => { const textRef = useRef(); useFrame( (state) => (textRef.current.position.x = Math.sin(state.clock.elapsedTime) * 2) ); return ( <Container> <Canvas> <mesh> <boxGeometry /> <meshStandardMaterial> <RenderTexture attach="map"> <PerspectiveCamera makeDefault position={[0, 0, 5]} /> <color attach="background" args={["#dc9dcd"]} /> <Text ref={textRef} fontSize={3} color="#555"> hello </Text> </RenderTexture> </meshStandardMaterial> </mesh> </Canvas> </Container> ); }; export default Test;
错误原因
你把useFrame和useRef放在了Test组件里,而Test是Canvas的父组件,不是Canvas内部的子组件。React Three Fiber的专属钩子(比如useFrame、useThree)必须在Canvas组件的直接/间接子组件中使用——这些钩子依赖Canvas提供的ThreeJS上下文,外部组件根本访问不到这个环境。
你的Text组件确实在Canvas内部,但控制它的动画钩子却在外部,这就触发了报错。
修正后的代码
把动画逻辑封装成独立组件,放到Canvas的上下文范围内:
import React, { useRef } from "react"; import { PerspectiveCamera, RenderTexture, Text } from "@react-three/drei"; import { Canvas, useFrame } from "@react-three/fiber"; import styled from "styled-components"; const Container = styled.div` height: 100vh; width: 100%; scroll-snap-align: center; ` // 封装带动画的文字组件,确保在Canvas上下文内使用钩子 const AnimatedText = () => { const textRef = useRef(); useFrame((state) => { textRef.current.position.x = Math.sin(state.clock.elapsedTime) * 2; }); return <Text ref={textRef} fontSize={3} color="#555">hello</Text>; }; const Test = () => { return ( <Container> <Canvas> <mesh> <boxGeometry /> <meshStandardMaterial> <RenderTexture attach="map"> <PerspectiveCamera makeDefault position={[0, 0, 5]} /> <color attach="background" args={["#dc9dcd"]} /> {/* 在Canvas内部使用动画文字组件 */} <AnimatedText /> </RenderTexture> </meshStandardMaterial> </mesh> </Canvas> </Container> ); }; export default Test;
内容的提问来源于stack exchange,提问作者Siddharth Juyal
相关产品推荐
相关产品推荐

