@@ -25,6 +25,7 @@ import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
25
25
import type { UpdateQueue } from './ReactFiberClassUpdateQueue.new' ;
26
26
import type { FunctionComponentUpdateQueue } from './ReactFiberHooks.new' ;
27
27
import type { Wakeable } from 'shared/ReactTypes' ;
28
+ import { isOffscreenManual } from './ReactFiberOffscreenComponent' ;
28
29
import type {
29
30
OffscreenState ,
30
31
OffscreenInstance ,
@@ -156,6 +157,7 @@ import {
156
157
clearSingleton ,
157
158
acquireSingletonInstance ,
158
159
releaseSingletonInstance ,
160
+ scheduleMicrotask ,
159
161
} from './ReactFiberHostConfig' ;
160
162
import {
161
163
captureCommitPhaseError ,
@@ -172,6 +174,7 @@ import {
172
174
setIsRunningInsertionEffect ,
173
175
getExecutionContext ,
174
176
CommitContext ,
177
+ RenderContext ,
175
178
NoContext ,
176
179
} from './ReactFiberWorkLoop.new' ;
177
180
import {
@@ -200,6 +203,7 @@ import {releaseCache, retainCache} from './ReactFiberCacheComponent.new';
200
203
import { clearTransitionsForLanes } from './ReactFiberLane.new' ;
201
204
import {
202
205
OffscreenVisible ,
206
+ OffscreenDetached ,
203
207
OffscreenPassiveEffectsConnected ,
204
208
} from './ReactFiberOffscreenComponent' ;
205
209
import {
@@ -2416,6 +2420,28 @@ function getRetryCache(finishedWork) {
2416
2420
}
2417
2421
}
2418
2422
2423
+ export function detachOffscreenInstance ( instance : OffscreenInstance ) : void {
2424
+ const currentOffscreenFiber = instance . _current ;
2425
+ if ( currentOffscreenFiber === null ) {
2426
+ throw new Error (
2427
+ 'Calling Offscreen.detach before instance handle has been set.' ,
2428
+ ) ;
2429
+ }
2430
+
2431
+ const executionContext = getExecutionContext ( ) ;
2432
+ if ( ( executionContext & ( RenderContext | CommitContext ) ) !== NoContext ) {
2433
+ scheduleMicrotask ( ( ) => {
2434
+ instance . _visibility |= OffscreenDetached ;
2435
+ disappearLayoutEffects ( currentOffscreenFiber ) ;
2436
+ disconnectPassiveEffect ( currentOffscreenFiber ) ;
2437
+ } ) ;
2438
+ } else {
2439
+ instance . _visibility |= OffscreenDetached ;
2440
+ disappearLayoutEffects ( currentOffscreenFiber ) ;
2441
+ disconnectPassiveEffect ( currentOffscreenFiber ) ;
2442
+ }
2443
+ }
2444
+
2419
2445
function attachSuspenseRetryListeners (
2420
2446
finishedWork : Fiber ,
2421
2447
wakeables : Set < Wakeable > ,
@@ -2845,6 +2871,8 @@ function commitMutationEffectsOnFiber(
2845
2871
}
2846
2872
2847
2873
commitReconciliationEffects ( finishedWork ) ;
2874
+ // TODO: Add explicit effect flag to set _current.
2875
+ finishedWork. stateNode . _current = finishedWork ;
2848
2876
2849
2877
if ( flags & Visibility ) {
2850
2878
const offscreenInstance : OffscreenInstance = finishedWork . stateNode ;
@@ -2871,7 +2899,8 @@ function commitMutationEffectsOnFiber(
2871
2899
}
2872
2900
}
2873
2901
2874
- if ( supportsMutation ) {
2902
+ // Offscreen with manual mode manages visibility manually.
2903
+ if ( supportsMutation && ! isOffscreenManual ( finishedWork ) ) {
2875
2904
// TODO: This needs to run whenever there's an insertion or update
2876
2905
// inside a hidden Offscreen tree.
2877
2906
hideOrUnhideAllChildren ( offscreenBoundary , isHidden ) ;
0 commit comments