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

在Gatsby+React Three Fiber中使用Context实例化网格报错

解决Gatsby + R3F实例化网格的Context与instances未定义问题

核心问题定位

  • 全局包裹Context Provider会导致R3F钩子在Canvas外部执行,触发Hooks can only be used within the Canvas component错误
  • instances未定义是因为Context数据没有正确传递到Canvas内的组件树中

分步解决方案

1. 正确创建Context并限定使用范围

先创建Context,同时封装自定义钩子确保只能在Provider内部使用:

// src/context/InstanceContext.js
import { createContext, useContext } from 'react';

const InstanceContext = createContext(null);

export const useInstanceContext = () => {
  const context = useContext(InstanceContext);
  if (!context) throw new Error('useInstanceContext必须在InstanceContext.Provider内部使用');
  return context;
};

export default InstanceContext;

2. 在Canvas内部挂载Context Provider

将Provider放在Canvas组件内部,确保所有依赖R3F钩子的组件都处于Canvas上下文内:

// src/pages/your-page.js
import { Canvas } from '@react-three/fiber';
import InstanceContext from '../context/InstanceContext';
import Planks from '../components/Planks';

export default function YourPage() {
  // 定义实例化数据:每个实例的位置、旋转、缩放参数
  const instances = [
    { position: [0, 0, 0], rotation: [0, 0, 0] },
    { position: [2, 0, 0], rotation: [0, Math.PI/4, 0] },
    { position: [4, 0, 0], rotation: [0, Math.PI/2, 0] }
    // 按需添加更多实例
  ];

  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <Canvas>
        {/* 仅在Canvas内部提供Context */}
        <InstanceContext.Provider value={{ instances }}>
          <Planks />
          {/* 其他场景组件 */}
        </InstanceContext.Provider>
      </Canvas>
    </div>
  );
}

3. 在Planks组件中正确获取实例数据并使用Merged

确保组件在Canvas树内执行钩子,正确传递instances给Merged组件:

// src/components/Planks.js
import { useInstanceContext } from '../context/InstanceContext';
import { Merged, useGLTF } from '@react-three/drei';

export default function Planks() {
  const { instances } = useInstanceContext();
  // 加载目标模型(假设模型中包含名为Plank的网格节点)
  const { nodes, loaded } = useGLTF('/plank.gltf');

  // 等待模型加载完成再渲染实例
  if (!loaded) return null;

  return (
    <Merged instances={instances}>
      <mesh geometry={nodes.Plank.geometry} material={nodes.Plank.material} />
    </Merged>
  );
}

4. 额外避坑提示

  • 确保instances始终为有效数组,可在Provider中设置默认空数组防止初始未定义:value={{ instances: instances || [] }}
  • 如果模型加载存在异步延迟,务必通过loaded状态判断后再渲染Merged,避免因模型未加载导致的异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:22:08