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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 12:40:35