@react-three/fiber 9.7.0 → 9.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/declarations/react-reconciler/index.d.ts +30 -13
- package/dist/declarations/src/core/index.d.ts +1 -0
- package/dist/declarations/src/core/promise.d.ts +15 -0
- package/dist/declarations/src/core/reconciler.d.ts +4 -0
- package/dist/declarations/src/core/renderer.d.ts +4 -2
- package/dist/declarations/src/core/utils.d.ts +3 -0
- package/dist/declarations/src/native/Canvas.d.ts +1 -1
- package/dist/declarations/src/web/Canvas.d.ts +2 -2
- package/dist/{events-156d8d12.esm.js → events-803f4abc.esm.js} +7745 -6524
- package/dist/{events-4c71f21f.cjs.prod.js → events-a79ef12b.cjs.prod.js} +3330 -2690
- package/dist/{events-b1bdeb1a.cjs.dev.js → events-ce5e34e8.cjs.dev.js} +7745 -6523
- package/dist/react-three-fiber.cjs.dev.js +58 -40
- package/dist/react-three-fiber.cjs.prod.js +58 -40
- package/dist/react-three-fiber.esm.js +60 -42
- package/native/dist/react-three-fiber-native.cjs.dev.js +46 -40
- package/native/dist/react-three-fiber-native.cjs.prod.js +46 -40
- package/native/dist/react-three-fiber-native.esm.js +47 -41
- package/package.json +6 -6
- package/react-reconciler/index.d.ts +30 -13
- package/react-reconciler/index.js +79 -77
- package/readme.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @react-three/fiber
|
|
2
2
|
|
|
3
|
+
## 9.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4ae2f816543f21e72b38d3e1328a21fc312428c1: Support React 19.3. Transitions that touch a `<ViewTransition>` subtree inside the canvas now commit synchronously, mirroring react-dom in browsers without view transitions, instead of leaving the reconciler stuck mid-commit.
|
|
8
|
+
- bc240cc56dbb0162737b2df0e99077c889d7cf2e: feat: configure and render roots synchronously; suspend on async renderers.
|
|
9
|
+
|
|
10
|
+
`root.configure()` now runs synchronously unless `gl` is an async factory (WebGPU), and the first `root.render()` mounts synchronously once the root is configured; later renders are batched as before. The returned promises carry a `status` field that React's `use` reads, and every root exposes `ready`, which is pending only while an async renderer is being created.
|
|
11
|
+
|
|
12
|
+
`<Canvas>` uses this to commit its scene inside its own layout effect, so `onCreated` runs while the wrapper is mounted and the events are connected before the browser paints. With an async renderer the canvas suspends on `root.ready` internally, without showing a parent fallback, and mounts once it resolves. Unmounting meanwhile never renders the scene. A renderer factory that fails now reaches the nearest error boundary instead of an unhandled rejection.
|
|
13
|
+
|
|
14
|
+
Configure calls made while another is in flight are applied after it, in order. The `flushSync` caveats apply to that first `root.render()` when it is called from inside another root's commit.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- f0f1cdf4336519a988faadae7f8607bc0cd8d7e2: fix: unmount roots deterministically instead of after a 500ms timer.
|
|
19
|
+
|
|
20
|
+
`unmountComponentAtNode` deferred disposal by 500ms. A `<StrictMode>` remount lands inside that window and reuses the same root, store, scene and GL context, so the deferred callback destroyed a live root. `forceContextLoss()` is permanent, which left the canvas blank for the rest of the session.
|
|
21
|
+
|
|
22
|
+
Unmounting now claims the root and runs the teardown through React once the unmounted tree's effect cleanups have flushed. Using the root again through `configure` or `render` before then cancels it. A root that is unmounted, remounted and unmounted again is torn down exactly once.
|
|
23
|
+
|
|
24
|
+
- bc240cc56dbb0162737b2df0e99077c889d7cf2e: fix: don't resurrect a `<Canvas>` root that unmounts before its render settles.
|
|
25
|
+
|
|
26
|
+
`<Canvas>` configured its root asynchronously. When the canvas was unmounted between that effect and the microtasks it queued, for example by a spring reparenting it through a synchronous state update from a layout effect, the stale continuation still rendered into the torn-down root. Its Provider then mounted again and called `events.connect` with the unmounted wrapper `div`, throwing `Cannot read properties of null (reading 'addEventListener')`, and the resurrected root leaked a live WebGL context.
|
|
27
|
+
|
|
28
|
+
The scene now commits inside the canvas' own commit, a deferred render bails once the root is claimed for teardown, and `unmountComponentAtNode` waits for a configure still in flight so the renderer it creates is disposed rather than orphaned.
|
|
29
|
+
|
|
3
30
|
## 9.7.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
|
@@ -610,7 +610,8 @@ declare namespace ReactReconciler {
|
|
|
610
610
|
type LanePriority = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17;
|
|
611
611
|
|
|
612
612
|
type Lanes = number;
|
|
613
|
-
|
|
613
|
+
|
|
614
|
+
type Lane = number & { __LaneBrand: any };
|
|
614
615
|
|
|
615
616
|
type Flags = number;
|
|
616
617
|
|
|
@@ -941,7 +942,6 @@ declare namespace ReactReconciler {
|
|
|
941
942
|
onCaughtError: (error: Error, info: BaseErrorInfo) => void,
|
|
942
943
|
onRecoverableError: (error: Error, info: BaseErrorInfo) => void,
|
|
943
944
|
onDefaultTransitionIndicator: () => void,
|
|
944
|
-
transitionCallbacks: null | TransitionTracingCallbacks,
|
|
945
945
|
): OpaqueRoot;
|
|
946
946
|
|
|
947
947
|
createPortal(
|
|
@@ -951,8 +951,6 @@ declare namespace ReactReconciler {
|
|
|
951
951
|
key?: string | null,
|
|
952
952
|
): ReactPortal;
|
|
953
953
|
|
|
954
|
-
registerMutableSourceForHydration(root: FiberRoot, mutableSource: MutableSource): void;
|
|
955
|
-
|
|
956
954
|
createComponentSelector(component: React$AbstractComponent<never, unknown>): ComponentSelector;
|
|
957
955
|
|
|
958
956
|
createHasPseudoClassSelector(selectors: Selector[]): HasPseudoClassSelector;
|
|
@@ -987,8 +985,12 @@ declare namespace ReactReconciler {
|
|
|
987
985
|
isStrictMode: boolean,
|
|
988
986
|
concurrentUpdatesByDefaultOverride: null | boolean,
|
|
989
987
|
identifierPrefix: string,
|
|
990
|
-
|
|
988
|
+
onUncaughtError: (error: Error, info: BaseErrorInfo & { errorBoundary?: Component }) => void,
|
|
989
|
+
onCaughtError: (error: Error, info: BaseErrorInfo) => void,
|
|
990
|
+
onRecoverableError: (error: Error, info: BaseErrorInfo) => void,
|
|
991
|
+
onDefaultTransitionIndicator: () => void,
|
|
991
992
|
transitionCallbacks: null | TransitionTracingCallbacks,
|
|
993
|
+
formState: unknown,
|
|
992
994
|
): OpaqueRoot;
|
|
993
995
|
|
|
994
996
|
updateContainer(
|
|
@@ -998,17 +1000,27 @@ declare namespace ReactReconciler {
|
|
|
998
1000
|
callback?: (() => void) | null,
|
|
999
1001
|
): Lane;
|
|
1000
1002
|
|
|
1003
|
+
updateContainerSync(
|
|
1004
|
+
element: ReactNode,
|
|
1005
|
+
container: OpaqueRoot,
|
|
1006
|
+
parentComponent?: Component<any, any> | null,
|
|
1007
|
+
callback?: (() => void) | null,
|
|
1008
|
+
): Lane;
|
|
1009
|
+
|
|
1001
1010
|
batchedUpdates<A, R>(fn: (a: A) => R, a: A): R;
|
|
1002
1011
|
|
|
1003
1012
|
deferredUpdates<A>(fn: () => A): A;
|
|
1004
1013
|
|
|
1005
1014
|
discreteUpdates<A, B, C, D, R>(fn: (arg0: A, arg1: B, arg2: C, arg3: D) => R, a: A, b: B, c: C, d: D): R;
|
|
1006
1015
|
|
|
1007
|
-
flushControlled(fn: () => any): void;
|
|
1008
|
-
|
|
1009
1016
|
flushSync(): void;
|
|
1010
1017
|
flushSync<R>(fn: () => R): R;
|
|
1011
1018
|
|
|
1019
|
+
flushSyncFromReconciler(): void;
|
|
1020
|
+
flushSyncFromReconciler<R>(fn: () => R): R;
|
|
1021
|
+
|
|
1022
|
+
flushSyncWork(): boolean;
|
|
1023
|
+
|
|
1012
1024
|
isAlreadyRendering(): boolean;
|
|
1013
1025
|
|
|
1014
1026
|
flushPassiveEffects(): boolean;
|
|
@@ -1017,16 +1029,10 @@ declare namespace ReactReconciler {
|
|
|
1017
1029
|
|
|
1018
1030
|
attemptSynchronousHydration(fiber: Fiber): void;
|
|
1019
1031
|
|
|
1020
|
-
attemptDiscreteHydration(fiber: Fiber): void;
|
|
1021
|
-
|
|
1022
1032
|
attemptContinuousHydration(fiber: Fiber): void;
|
|
1023
1033
|
|
|
1024
1034
|
attemptHydrationAtCurrentPriority(fiber: Fiber): void;
|
|
1025
1035
|
|
|
1026
|
-
getCurrentUpdatePriority(): LanePriority;
|
|
1027
|
-
|
|
1028
|
-
runWithPriority<T>(priority: LanePriority, fn: () => T): T;
|
|
1029
|
-
|
|
1030
1036
|
findHostInstance(component: any): PublicInstance | null;
|
|
1031
1037
|
|
|
1032
1038
|
findHostInstanceWithWarning(component: any, methodName: string): PublicInstance | null;
|
|
@@ -1039,6 +1045,17 @@ declare namespace ReactReconciler {
|
|
|
1039
1045
|
|
|
1040
1046
|
injectIntoDevTools(devToolsConfig: DevToolsConfig<Instance, TextInstance, any>): boolean;
|
|
1041
1047
|
}
|
|
1048
|
+
|
|
1049
|
+
function defaultOnUncaughtError(error: Error): void;
|
|
1050
|
+
function defaultOnCaughtError(error: Error): void;
|
|
1051
|
+
function defaultOnRecoverableError(error: Error): void;
|
|
1052
|
+
|
|
1053
|
+
function startHostTransition(
|
|
1054
|
+
formFiber: Fiber,
|
|
1055
|
+
pendingState: unknown,
|
|
1056
|
+
action: ((formData: FormData) => void) | null,
|
|
1057
|
+
formData: FormData,
|
|
1058
|
+
): void;
|
|
1042
1059
|
}
|
|
1043
1060
|
|
|
1044
1061
|
export = ReactReconciler;
|
|
@@ -11,3 +11,4 @@ export type { Subscription, Dpr, Size, Viewport, RenderCallback, Frameloop, Perf
|
|
|
11
11
|
export { context } from "./store.js";
|
|
12
12
|
export type { ObjectMap, Camera, Disposable, Act } from "./utils.js";
|
|
13
13
|
export { applyProps, getRootState, dispose, act, buildGraph } from "./utils.js";
|
|
14
|
+
export type { TrackedPromise } from "./promise.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const isPromiseLike: (value: unknown) => value is PromiseLike<unknown>;
|
|
2
|
+
/** A promise tagged with its state, the protocol React's `use` reads */
|
|
3
|
+
export type TrackedPromise<T> = Promise<T> & ({
|
|
4
|
+
status: 'pending';
|
|
5
|
+
} | {
|
|
6
|
+
status: 'fulfilled';
|
|
7
|
+
value: T;
|
|
8
|
+
} | {
|
|
9
|
+
status: 'rejected';
|
|
10
|
+
reason: unknown;
|
|
11
|
+
});
|
|
12
|
+
export declare const fulfilled: <T>(value: T) => TrackedPromise<T>;
|
|
13
|
+
export declare const rejected: <T>(reason: unknown) => TrackedPromise<T>;
|
|
14
|
+
/** Tags `promise` in place once it settles. */
|
|
15
|
+
export declare const tracked: <T>(promise: PromiseLike<T>) => TrackedPromise<T>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import Reconciler from '../../react-reconciler/index.js';
|
|
4
|
+
import type { TrackedPromise } from "./promise.js";
|
|
4
5
|
import { IsAllOptional } from "./utils.js";
|
|
5
6
|
import type { RootStore } from "./store.js";
|
|
6
7
|
import { type EventHandlers } from "./events.js";
|
|
@@ -8,6 +9,9 @@ import type { ThreeElement } from "../three-types.js";
|
|
|
8
9
|
export interface Root {
|
|
9
10
|
fiber: Reconciler.FiberRoot;
|
|
10
11
|
store: RootStore;
|
|
12
|
+
unmountClaim: symbol | null;
|
|
13
|
+
/** Pending only while an async renderer is being created */
|
|
14
|
+
ready: TrackedPromise<unknown>;
|
|
11
15
|
}
|
|
12
16
|
export type AttachFnType<O = any> = (parent: any, self: O) => () => void;
|
|
13
17
|
export type AttachType<O = any> = string | AttachFnType<O>;
|
|
@@ -5,6 +5,7 @@ import { ComputeFunction, EventManager } from "./events.js";
|
|
|
5
5
|
import { Root } from "./reconciler.js";
|
|
6
6
|
import { Dpr, Frameloop, Performance, Renderer, RootState, RootStore, Size } from "./store.js";
|
|
7
7
|
import { type Properties, Camera } from "./utils.js";
|
|
8
|
+
import { TrackedPromise } from "./promise.js";
|
|
8
9
|
interface OffscreenCanvas extends EventTarget {
|
|
9
10
|
}
|
|
10
11
|
export declare const _roots: Map<HTMLCanvasElement | OffscreenCanvas, Root>;
|
|
@@ -29,7 +30,7 @@ export interface RenderProps<TCanvas extends HTMLCanvasElement | OffscreenCanvas
|
|
|
29
30
|
shadows?: boolean | 'basic' | 'percentage' | 'soft' | 'variance' | Partial<THREE.WebGLShadowMap>;
|
|
30
31
|
/**
|
|
31
32
|
* Disables three r139 color management.
|
|
32
|
-
* @see https://threejs.org/
|
|
33
|
+
* @see https://threejs.org/manual/#en/color-management
|
|
33
34
|
*/
|
|
34
35
|
legacy?: boolean;
|
|
35
36
|
/** Switch off automatic sRGB encoding and gamma correction */
|
|
@@ -64,7 +65,8 @@ export interface RenderProps<TCanvas extends HTMLCanvasElement | OffscreenCanvas
|
|
|
64
65
|
onPointerMissed?: (event: MouseEvent) => void;
|
|
65
66
|
}
|
|
66
67
|
export interface ReconcilerRoot<TCanvas extends HTMLCanvasElement | OffscreenCanvas> {
|
|
67
|
-
|
|
68
|
+
ready: TrackedPromise<unknown>;
|
|
69
|
+
configure: (config?: RenderProps<TCanvas>) => TrackedPromise<ReconcilerRoot<TCanvas>>;
|
|
68
70
|
render: (element: React.ReactNode) => RootStore;
|
|
69
71
|
unmount: () => void;
|
|
70
72
|
}
|
|
@@ -39,6 +39,9 @@ export declare const isColorRepresentation: (value: unknown) => value is THREE.C
|
|
|
39
39
|
*/
|
|
40
40
|
export declare const useIsomorphicLayoutEffect: typeof React.useLayoutEffect;
|
|
41
41
|
export declare function useMutableCallback<T>(fn: T): React.RefObject<T>;
|
|
42
|
+
export declare const noop: () => void;
|
|
43
|
+
/** Waits for a promise in a null subtree, re-rendering the caller once it settles either way. */
|
|
44
|
+
export declare function useGate(): [gate: React.ReactNode, waitFor: (promise: PromiseLike<unknown>) => void];
|
|
42
45
|
export type Bridge = React.FC<{
|
|
43
46
|
children?: React.ReactNode;
|
|
44
47
|
}>;
|
|
@@ -10,4 +10,4 @@ export interface CanvasProps extends Omit<RenderProps<HTMLCanvasElement>, 'size'
|
|
|
10
10
|
* A native canvas which accepts threejs elements as children.
|
|
11
11
|
* @see https://docs.pmnd.rs/react-three-fiber/api/canvas
|
|
12
12
|
*/
|
|
13
|
-
export declare function Canvas(props: CanvasProps):
|
|
13
|
+
export declare function Canvas(props: CanvasProps): React.JSX.Element;
|
|
@@ -12,7 +12,7 @@ export interface CanvasProps extends Omit<RenderProps<HTMLCanvasElement>, 'size'
|
|
|
12
12
|
*/
|
|
13
13
|
resize?: ResizeOptions;
|
|
14
14
|
/** The target where events are being subscribed to, default: the div that wraps canvas */
|
|
15
|
-
eventSource?: HTMLElement | React.RefObject<HTMLElement>;
|
|
15
|
+
eventSource?: HTMLElement | React.RefObject<HTMLElement | null>;
|
|
16
16
|
/** The event prefix that is cast into canvas pointer x/y events, default: "offset" */
|
|
17
17
|
eventPrefix?: 'offset' | 'client' | 'page' | 'layer' | 'screen';
|
|
18
18
|
}
|
|
@@ -20,4 +20,4 @@ export interface CanvasProps extends Omit<RenderProps<HTMLCanvasElement>, 'size'
|
|
|
20
20
|
* A DOM canvas which accepts threejs elements as children.
|
|
21
21
|
* @see https://docs.pmnd.rs/react-three-fiber/api/canvas
|
|
22
22
|
*/
|
|
23
|
-
export declare function Canvas(props: CanvasProps):
|
|
23
|
+
export declare function Canvas(props: CanvasProps): React.JSX.Element;
|