diff --git a/packages/fiber/src/web/Canvas.tsx b/packages/fiber/src/web/Canvas.tsx index c2ebdbdc17..9d5ab9ba7e 100644 --- a/packages/fiber/src/web/Canvas.tsx +++ b/packages/fiber/src/web/Canvas.tsx @@ -59,7 +59,6 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef(func const [containerRef, containerRect] = useMeasure({ scroll: true, debounce: { scroll: 50, resize: 0 }, ...resize }) const canvasRef = React.useRef(null!) const divRef = React.useRef(null!) - const [canvas, setCanvas] = React.useState(null) React.useImperativeHandle(forwardedRef, () => canvasRef.current) const handlePointerMissed = useMutableCallback(onPointerMissed) @@ -73,58 +72,60 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef(func const root = React.useRef>(null!) - if (containerRect.width > 0 && containerRect.height > 0 && canvas) { - if (!root.current) root.current = createRoot(canvas) - root.current.configure({ - gl, - events, - shadows, - linear, - flat, - legacy, - orthographic, - frameloop, - dpr, - performance, - raycaster, - camera, - size: containerRect, - // Pass mutable reference to onPointerMissed so it's free to update - onPointerMissed: (...args) => handlePointerMissed.current?.(...args), - onCreated: (state) => { - // Connect to event source - state.events.connect?.(eventSource ? (isRef(eventSource) ? eventSource.current : eventSource) : divRef.current) - // Set up compute function - if (eventPrefix) { - state.setEvents({ - compute: (event, state) => { - const x = event[(eventPrefix + 'X') as keyof DomEvent] as number - const y = event[(eventPrefix + 'Y') as keyof DomEvent] as number - state.pointer.set((x / state.size.width) * 2 - 1, -(y / state.size.height) * 2 + 1) - state.raycaster.setFromCamera(state.pointer, state.camera) - }, - }) - } - // Call onCreated callback - onCreated?.(state) - }, - }) - root.current.render( - - - }>{children} - - , - ) - } - useIsomorphicLayoutEffect(() => { - setCanvas(canvasRef.current) - }, []) + const canvas = canvasRef.current + if (containerRect.width > 0 && containerRect.height > 0 && canvas) { + if (!root.current) root.current = createRoot(canvas) + root.current.configure({ + gl, + events, + shadows, + linear, + flat, + legacy, + orthographic, + frameloop, + dpr, + performance, + raycaster, + camera, + size: containerRect, + // Pass mutable reference to onPointerMissed so it's free to update + onPointerMissed: (...args) => handlePointerMissed.current?.(...args), + onCreated: (state) => { + // Connect to event source + state.events.connect?.( + eventSource ? (isRef(eventSource) ? eventSource.current : eventSource) : divRef.current, + ) + // Set up compute function + if (eventPrefix) { + state.setEvents({ + compute: (event, state) => { + const x = event[(eventPrefix + 'X') as keyof DomEvent] as number + const y = event[(eventPrefix + 'Y') as keyof DomEvent] as number + state.pointer.set((x / state.size.width) * 2 - 1, -(y / state.size.height) * 2 + 1) + state.raycaster.setFromCamera(state.pointer, state.camera) + }, + }) + } + // Call onCreated callback + onCreated?.(state) + }, + }) + root.current.render( + + + }>{children} + + , + ) + } + }) React.useEffect(() => { - if (canvas) return () => unmountComponentAtNode(canvas!) - }, [canvas]) + const canvas = canvasRef.current + if (canvas) return () => unmountComponentAtNode(canvas) + }, []) // When the event source is not this div, we need to set pointer-events to none // Or else the canvas will block events from reaching the event source