R3F中GLTF导入网格上下文导致订阅渲染时TypeScript错误
解决React Three Fiber中实例化网格的TypeScript类型错误
问题背景
使用React Three Fiber(R3F)渲染实例化网格时,代码可正常运行,但在DigiviceMesh组件中渲染从Context获取的网格实例时,出现TypeScript类型错误:
'instances.DigiviceBodyLights' cannot be used as a JSX component. Its type 'Mesh<BufferGeometry, Material | Material[], Object3DEventMap>' is not a valid JSX element type.
问题根源是直接将Three.js原生Mesh类型作为JSX组件使用,TypeScript无法识别其为R3F可渲染的JSX元素类型。
解决方案
方案1:使用R3F的Object3DNode类型修正上下文接口
R3F提供了Object3DNode类型,用于将Three.js原生对象映射为可识别的JSX组件类型。修改上下文接口定义:
import type { Object3DNode } from '@react-three/fiber' import type { Mesh, BufferGeometry, Material, Object3DEventMap } from 'three' // 修正上下文类型,使用R3F的Object3DNode包裹原生Mesh类型 interface IInstanceContext { [key: string]: Object3DNode<Mesh<BufferGeometry, Material | Material[]>, typeof Mesh> } const context = createContext<IInstanceContext>({} as IInstanceContext)
方案2:自动推导上下文类型(更简洁)
直接从useMemo生成的instances对象推导类型,无需手动维护接口:
export function Instances({ children, ...props }) { const { nodes } = useGLTF('/models/digivice.glb') as GLTFResult const instances = useMemo( () => ({ DigiviceBodyLights: nodes.Digivice_Body_Lights_0, DigiviceBodyBody: nodes.Digivice_Body_Body_0, DigiviceBodyScreen: nodes.Digivice_Body_Screen_0, DigiviceBodyScreenCorner: nodes.Digivice_Body_Screen_Corner_0, ButtonsButtons: nodes.Buttons_Buttons_0, AntennaAntenna: nodes.Antenna_Antenna_0, }), [nodes] ) // 自动推导实例类型 type InstanceContextType = typeof instances const context = createContext<InstanceContextType>({} as InstanceContextType) return ( <Merged meshes={instances} {...props}> {(instances) => <context.Provider value={instances} children={children} />} </Merged> ) }
说明
两种方案都能让TypeScript正确识别从Context获取的网格实例为R3F可渲染的JSX组件,同时保留实例化网格的性能优势,避免改用<mesh>标签导致GPU负载翻倍的问题。
内容的提问来源于stack exchange,提问作者Ocean Evers-Peete
相关产品推荐
相关产品推荐

