diff --git a/packages/fiber/src/core/utils.ts b/packages/fiber/src/core/utils.tsx similarity index 95% rename from packages/fiber/src/core/utils.ts rename to packages/fiber/src/core/utils.tsx index 069d8852d4..aed863a471 100644 --- a/packages/fiber/src/core/utils.ts +++ b/packages/fiber/src/core/utils.tsx @@ -1,5 +1,6 @@ import * as THREE from 'three' import * as React from 'react' +import { useFiber, traverseFiber, useContextBridge } from 'its-fine' import type { Fiber } from 'react-reconciler' import type { EventHandlers } from './events' import type { Dpr, RootState, RootStore, Size } from './store' @@ -55,6 +56,31 @@ export function useMutableCallback(fn: T): React.MutableRefObject { return ref } +export type Bridge = React.FC<{ children?: React.ReactNode }> + +/** + * Bridges renderer Context and StrictMode from a primary renderer. + */ +export function useBridge(): Bridge { + const fiber = useFiber() + const ContextBridge = useContextBridge() + + return React.useMemo( + () => + ({ children }) => { + const strict = !!traverseFiber(fiber, true, (node) => node.type === React.StrictMode) + const Root = strict ? React.StrictMode : React.Fragment + + return ( + + {children} + + ) + }, + [fiber, ContextBridge], + ) +} + export type SetBlock = false | Promise | null export type UnblockProps = { set: React.Dispatch>; children: React.ReactNode } @@ -93,7 +119,7 @@ export function calculateDpr(dpr: Dpr): number { /** * Returns instance root state */ -export const getRootState = (obj: T): RootState | undefined => +export const getRootState = (obj: T): RootState | undefined => (obj as Instance['object']).__r3f?.root.getState() export interface EquConfig { diff --git a/packages/fiber/src/native/Canvas.tsx b/packages/fiber/src/native/Canvas.tsx index a58f3fd9bf..b0cc4b77c3 100644 --- a/packages/fiber/src/native/Canvas.tsx +++ b/packages/fiber/src/native/Canvas.tsx @@ -2,8 +2,8 @@ import * as React from 'react' import * as THREE from 'three' import { View, ViewProps, ViewStyle, LayoutChangeEvent, StyleSheet, PixelRatio } from 'react-native' import { ExpoWebGLRenderingContext, GLView } from 'expo-gl' -import { useContextBridge, FiberProvider } from 'its-fine' -import { SetBlock, Block, ErrorBoundary, useMutableCallback } from '../core/utils' +import { FiberProvider } from 'its-fine' +import { SetBlock, Block, ErrorBoundary, useMutableCallback, useBridge } from '../core/utils' import { extend, createRoot, unmountComponentAtNode, RenderProps, ReconcilerRoot } from '../core' import { createTouchEvents } from './events' import { RootState, Size } from '../core/store' @@ -42,7 +42,7 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef( // their own elements by using the createRoot API instead React.useMemo(() => extend(THREE as any), []) - const Bridge = useContextBridge() + const Bridge = useBridge() const [{ width, height, top, left }, setSize] = React.useState({ width: 0, height: 0, top: 0, left: 0 }) const [canvas, setCanvas] = React.useState(null) diff --git a/packages/fiber/src/web/Canvas.tsx b/packages/fiber/src/web/Canvas.tsx index 14539ddb84..ce64a3b374 100644 --- a/packages/fiber/src/web/Canvas.tsx +++ b/packages/fiber/src/web/Canvas.tsx @@ -2,8 +2,16 @@ import * as React from 'react' import * as THREE from 'three' import useMeasure from 'react-use-measure' import type { Options as ResizeOptions } from 'react-use-measure' -import { useContextBridge, FiberProvider } from 'its-fine' -import { isRef, SetBlock, Block, ErrorBoundary, useMutableCallback, useIsomorphicLayoutEffect } from '../core/utils' +import { FiberProvider } from 'its-fine' +import { + isRef, + SetBlock, + Block, + ErrorBoundary, + useMutableCallback, + useIsomorphicLayoutEffect, + useBridge, +} from '../core/utils' import { ReconcilerRoot, extend, createRoot, unmountComponentAtNode, RenderProps } from '../core' import { createPointerEvents } from './events' import { DomEvent } from '../core/events' @@ -57,7 +65,7 @@ const CanvasImpl = /*#__PURE__*/ React.forwardRef extend(THREE as any), []) - const Bridge = useContextBridge() + const Bridge = useBridge() const [containerRef, containerRect] = useMeasure({ scroll: true, debounce: { scroll: 50, resize: 0 }, ...resize }) const canvasRef = React.useRef(null!)