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

React Three Fiber纹理加载报错:组件响应同步输入时挂起求助

解决React Three Fiber加载纹理时的Suspend错误

错误原因

React 18的并发模式下,当组件在响应同步输入操作(比如点击、表单输入)时触发异步加载(纹理加载属于异步操作),组件会进入suspend状态,此时React会抛出该错误,提示你需要明确处理这种可延迟的更新。

解决方案

1. 用React.Suspense包裹纹理组件

如果是组件初始化时就加载纹理,直接用Suspense包裹使用纹理的组件,指定加载时的 fallback 内容即可:

// 父组件/App.jsx
import { Suspense } from 'react';
import { Canvas } from '@react-three/fiber';
import TexturedPlane from './TexturedPlane';

export default function App() {
  return (
    <Canvas>
      {/* 用Suspense包裹,加载时显示灰色立方体作为占位 */}
      <Suspense fallback={<mesh><boxGeometry /><meshBasicMaterial color="#888" /></mesh>}>
        <TexturedPlane />
      </Suspense>
    </Canvas>
  );
}
// TexturedPlane.jsx
import { useTexture } from '@react-three/drei';

export default function TexturedPlane() {
  // 正常使用useTexture加载纹理
  const texture = useTexture('/textures/texture.png');
  
  return (
    <mesh position={[0,0,0]}>
      <planeGeometry args={[5,5]} />
      <meshBasicMaterial map={texture} />
    </mesh>
  );
}

2. 用startTransition包裹输入触发的加载逻辑

如果纹理加载是由用户输入(比如点击按钮)触发的,需要把加载操作包裹在startTransition中,告诉React这个更新可以延迟执行:

import { useState, startTransition } from 'react';
import { useTexture } from '@react-three/drei';

export default function TextureLoader() {
  const [texture, setTexture] = useState(null);

  const handleLoad = () => {
    // 把加载逻辑放在startTransition内
    startTransition(() => {
      const loadedTexture = useTexture('/textures/texture.png');
      setTexture(loadedTexture);
    });
  };

  return (
    <>
      <button onClick={handleLoad}>加载纹理</button>
      {texture && (
        <mesh>
          <planeGeometry args={[3,3]} />
          <meshBasicMaterial map={texture} />
        </mesh>
      )}
    </>
  );
}

3. 预加载纹理(可选)

如果希望纹理在应用启动时就加载完成,可以在应用初始化阶段预加载,避免后续操作触发suspend:

// 在App初始化时预加载
import { TextureLoader } from 'three';
import { useEffect, useState } from 'react';
import { Canvas } from '@react-three/fiber';

export default function App() {
  const [preloadedTexture, setPreloadedTexture] = useState(null);

  useEffect(() => {
    const loader = new TextureLoader();
    loader.load('/textures/texture.png', (texture) => {
      setPreloadedTexture(texture);
    });
  }, []);

  if (!preloadedTexture) return <div>加载中...</div>;

  return (
    <Canvas>
      <mesh>
        <planeGeometry />
        <meshBasicMaterial map={preloadedTexture} />
      </mesh>
    </Canvas>
  );
}

内容的提问来源于stack exchange,提问作者Sisandy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:17:35