React Three Fiber异步获取API后加载GLTF模型列表报错求助
我想实现通过异步API获取GLTF模型路径列表,遍历加载每个模型的功能,写了三个组件:
AllModels.tsx
export const AllModels = ({ ...props }: any) => { const { rotation, position } = props; const initialRef: any = null; const [modelPaths, setModelPaths] = useState(initialRef); const getMyData = async () => { const response = await fetch( "http://listOfPaths.com/list.json" // ["http://...", "http://...",..] ); const data = await response.json(); setModelPaths(data); }; useEffect(() => { getMyData(); }, []); return ( <> {modelPaths && modelPaths.map((value: any, index: any) => ( <Model key={`${index}-${value}`} path={value}></Model> ))} </> ); };
Model.tsx
import { useGLTF } from "@react-three/drei"; export const Model = async ({ ...props }: any) => { const { scale, rotation, position, path } = props; const model = useGLTF(path); const scene = model.scene; return ( <primitive castShadow receiveShadow scale={scale} rotation={rotation} position={position} object={scene} /> ); };
Main.tsx
<Canvas> <ambientLight /> <AllModels position={[0, 0, 0]} /> </Canvas>
运行时出现三个TypeScript错误:
错误1
Type 'Promise' is missing the following properties from type
'ReactElement<any, any>': type, props, key in AllModels.tsx:
<Model key={${index}-${value}} path={value}/>
错误2
Property 'scene' does not exist on type '(GLTF & ObjectMap) | (GLTF &
ObjectMap)[]'. Property 'scene' does not exist on type '(GLTF &
ObjectMap)[]'.
8 const scene = model.scene;
错误3
'Model' cannot be used as a JSX component. Its return type
'Promise' is not a valid JSX element.
Type 'Promise' is missing the following properties from type 'ReactElement<any, any>': type, props, key 27 <Model
key={${index}-${value}} path={value}/>
1. 移除Model组件的async关键字
React组件不能是异步函数,async会让组件返回Promise而非ReactElement,这是错误1和错误3的直接原因。修改Model.tsx:
import { useGLTF } from "@react-three/drei"; // 去掉async关键字 export const Model = ({ ...props }: any) => { const { scale, rotation, position, path } = props; const model = useGLTF(path); const scene = model.scene; return ( <primitive castShadow receiveShadow scale={scale} rotation={rotation} position={position} object={scene} /> ); };
2. 处理useGLTF的类型歧义
useGLTF的返回值可能是单个GLTF对象或数组,TypeScript无法自动推断。可以通过两种方式解决:
方式一:类型断言
直接断言返回值为单个GLTF对象:
import { GLTF } from "@react-three/drei"; // 断言model为单个GLTF实例 const model = useGLTF(path) as GLTF & ObjectMap; const scene = model.scene;
方式二:指定single选项(推荐)
如果你的路径指向单个模型,添加single: true选项确保返回单个对象,同时消除类型歧义:
const model = useGLTF(path, { single: true }); const scene = model.scene;
3. 完善类型定义(可选但推荐)
避免使用any类型,为组件添加明确的TypeScript类型,提升代码健壮性:
AllModels.tsx类型优化
import { useState, useEffect } from "react"; import { Model } from "./Model"; // 定义组件props类型 type AllModelsProps = { rotation?: [number, number, number]; position?: [number, number, number]; }; export const AllModels = ({ rotation, position }: AllModelsProps) => { const [modelPaths, setModelPaths] = useState<string[] | null>(null); const getMyData = async () => { const response = await fetch("http://listOfPaths.com/list.json"); const data = await response.json(); // 断言数据为字符串数组,或添加类型检查逻辑 setModelPaths(data as string[]); }; useEffect(() => { getMyData(); }, []); return ( <> {modelPaths?.map((value, index) => ( <Model key={`${index}-${value}`} path={value} rotation={rotation} position={position} /> ))} </> ); };
Model.tsx类型优化
import { useGLTF, GLTF } from "@react-three/drei"; import { Object3D } from "three"; // 定义组件props类型 type ModelProps = { scale?: [number, number, number]; rotation?: [number, number, number]; position?: [number, number, number]; path: string; }; export const Model = ({ scale = [1,1,1], rotation = [0,0,0], position = [0,0,0], path }: ModelProps) => { const model = useGLTF(path, { single: true }); const scene = model.scene as Object3D; return ( <primitive castShadow receiveShadow scale={scale} rotation={rotation} position={position} object={scene} /> ); }; // 可选:预加载模型提升性能 useGLTF.preload("http://listOfPaths.com/your-model-path.gltf");
内容的提问来源于stack exchange,提问作者Suisse

