This is the same code (not exactly!) as prisoner849's answer modified to run in react-three-fiber, I use this now in my project and it is working. I think my forwardRef is not necessary, its just that I have useImperativeHandle in there for a reason.
This is a non-answer to the question as its a copy of his code just translated.
import React, {useLayoutEffect, useRef} from 'react'
import * as THREE from 'three'
import { useThree } from 'react-three-fiber'
const { forwardRef, useImperativeHandle } = React;
export const LineMapping = (forwardRef(({}, ref) => {
const {
camera,
gl: { domElement }
} = useThree()
const ref3 = useRef()
const ref2 = useRef()
const meshRef = useRef()
const randomFloat = (a: number, b: number): number => {
return (Math.random() * (b-a)) + a
}
let width = [randomFloat(0.3, 2.0), randomFloat(0.3, 0.6)] // start, end
let basePoints = [
// start, end points
new THREE.Vector3(-2, 0.9 + randomFloat(0.0, 3.0)),
new THREE.Vector3(2, 0.9 + randomFloat(0.0, 3.0))
]
let pathPoints = [
basePoints[0],
// @ts-ignore
new THREE.Vector2().addVectors(basePoints[0], basePoints[1]).multiplyScalar(0.5).setY(basePoints[0].y),
// @ts-ignore
new THREE.Vector2().addVectors(basePoints[0], basePoints[1]).multiplyScalar(0.5).setY(basePoints[1].y),
basePoints[1]
]
// @ts-ignore
let curve = new THREE.CubicBezierCurve(pathPoints[0], pathPoints[1], pathPoints[2], pathPoints[3])
let resultPoints = curve.getSpacedPoints(50)
const lineGeometry = new THREE.BufferGeometry().setFromPoints(resultPoints)
useLayoutEffect(() => {
if (ref3.current !== undefined && ref2.current !== undefined) {
// @ts-ignore
let pos = ref2.current!.attributes.position
for (let i = 0; i <= 50; i++) {
let iMod = i
let lrp = THREE.MathUtils.lerp(width[0], width[1], i / 50)
pos.setXYZ(i, resultPoints[iMod].x, resultPoints[iMod].y + lrp * 0.5 * Math.sign(pos.getY(i)), 0)
pos.setXYZ(iMod + 51, resultPoints[iMod].x, resultPoints[iMod].y + lrp * 0.5 * Math.sign(pos.getY(i + 51)), 0)
}
}
});
// @ts-ignore
useImperativeHandle(ref, () => ({
testMe: () => {
}
}));
return <>
<group position={[2.2, 0, -5.5]}>
<group position={[0, 0, 0]} visible={false}>
<line ref={ref3} geometry={lineGeometry}>
<lineDashedMaterial attach="material" color={'#ffffff'} linewidth={1} />
</line>
</group>
<mesh ref={meshRef} receiveShadow>
<planeBufferGeometry ref={ref2} attach="geometry" args={[7, 7, 50, 1]} />
<meshBasicMaterial attach="material" color="#2892D7" wireframe={false} />
</mesh>
</group>
</>
}))