threejs中group下绑定唯一key导致parten丢失的问题

技术架构

  • react
  • threejs
  • @react-three/drei
  • @react-three/fiber
  • @use-gesture/react

场景

一个分组下有一个Line,当使用gesture的useDrag触发事件以后:

import { Line } from '@react-three/drei'
import { ThreeEvent, useFrame } from '@react-three/fiber'
import { useDrag } from '@use-gesture/react'
import { useEffect, useState } from 'react'
import { DoubleSide, Vector3 } from 'three'

const lineWidth = 4
const LinePropsData = {
  color: 0x3b61fa,
  lineWidth: lineWidth,
  dashSize: lineWidth,
  gapSize: lineWidth,
  side: DoubleSide,
}

/**
 * 区域入参定义
 */
export interface ExampleProps {
  positions?: Vector3[]
}

const Example: React.FC<ExampleProps> = (props) => {
  const { positions = [] } = props
  const [linePositions, setLinePositions] = useState<Vector3[]>([...positions])
  useEffect(() => {
    if (!positions) {
      return
    }

    setLinePositions([...positions])
  }, [positions])

  const dragStateRef = useRef<GestureDragState>()
  const bind = useDrag((state) => {
    setDragState(state)
  })
  const bindObject = bind() as any

  // 每一帧更新 mesh 的位置
  useFrame(() => {
    const dragState = dragStateRef.current
    if (!dragState) {
      return
    }
    const event: ThreeEvent<MouseEvent> = dragState.event as any
    console.log('event.intersection.parent, event.intersections[0]?.object.parent)
  })

  return (
    <group {...bindObject}>
      {linePositions.length < 2 ? (
        // 两个以下的点构不成线
        <></>
      ) : (
        <Line key={Math.random()} points={linePositions} {...LinePropsData} />
      )}
    </group>
  )
}

export default Example

useFrame中获取相交对象的父级event.intersections[0]?.object.parent,发现父级为null,而Line明明在group下,父级应该为group才对。一时间百思不得其解,重新写了个Line发现父级能找到group,对比之下,发现旧的写法里绑定了个key={Math.random()}(暂时使用random代替源代码中的uuid生成),每次触发react重新渲染时都是渲染不同的元素,这导致了Line与group丢失了父子关系。

这是个有意思的问题,值得分享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值