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

react-three-fiber中如何访问map遍历传入的数据设置组件属性

问题根因
  • Props取值层级错误:React函数组件的入参是所有传入属性的集合对象,你给组件传入pinInfo={e}时,组件入参的实际结构为{ pinInfo: 对应e的点位数据 }。你直接将入参命名为pinInfo后访问pinInfo.pin_position,相当于在props根对象上找不存在的字段,自然返回undefined。
  • demand渲染模式未触发重绘:Canvas设置frameloop="demand"后,react-three-fiber不会自动逐帧更新画面,仅在手动调用invalidate()方法时才会重渲染,状态变更后没有主动触发重绘的话,新的位置数据不会同步到画布上。
修复代码

修正Pin组件实现

import { useLoader, useThree } from '@react-three/fiber'
import { TextureLoader } from 'three'
import { useEffect } from 'react'

function Pin({ pinInfo }) {
  // 正确解构拿到传入的点位数据,可直接访问内部属性
  const pinTexture = useLoader(TextureLoader, setPinColor(pinInfo.pin_color));
  const { x_pos, y_pos } = pinInfo.pin_position;
  // 获取R3F提供的画布重绘方法
  const { invalidate } = useThree();

  // 点位数据变化时主动触发画布重绘
  useEffect(() => {
    invalidate();
  }, [pinInfo, invalidate]);

  return (
    <mesh position={[x_pos, y_pos, 0]}>
      <planeGeometry args={[5, 5]} />
      <meshBasicMaterial map={pinTexture} toneMapped={false} transparent={true} />
    </mesh>
  )
}

补充列表渲染唯一key

遍历渲染组件时必须加唯一key,避免React虚拟DOM diff异常:

<Canvas linear flat frameloop="demand" orthographic camera={{ position: [0, 0, 50], zoom: 20, up: [0, 0, 1], far: 10000 }}>
  <Suspense fallback={null}>
    {moduleData.floor1.pins.map(e =>
      // 替换成你数据里的唯一业务字段,不要用数组下标当key
      <Pin key={e.popup_title} pinInfo={e}/>
    )}
    <Scene mapImage={riverwalkMap}/>
  </Suspense>
  <MapControls enableRotate={false}/>
</Canvas>
补充说明
  • 如果后续有拖拽、实时动画这类高频更新需求,可以把Canvas的frameloop改回默认值always,就不需要手动调用invalidate()触发重绘,根据业务场景选择即可。
  • 只要你的点位state更新能触发Pin组件重渲染,上述逻辑就会自动同步位置到画布,不需要额外引入特殊hook。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 05:54:37