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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 10:27:41