@@ -25,6 +25,7 @@ import type {SuspenseState} from './ReactFiberSuspenseComponent.new';
2525import type { UpdateQueue } from './ReactFiberClassUpdateQueue.new' ;
2626import type { FunctionComponentUpdateQueue } from './ReactFiberHooks.new' ;
2727import type { Wakeable } from 'shared/ReactTypes' ;
28+ import { isOffscreenManual } from './ReactFiberOffscreenComponent' ;
2829import type {
2930 OffscreenState ,
3031 OffscreenInstance ,
@@ -156,6 +157,7 @@ import {
156157 clearSingleton ,
157158 acquireSingletonInstance ,
158159 releaseSingletonInstance ,
160+ scheduleMicrotask ,
159161} from './ReactFiberHostConfig' ;
160162import {
161163 captureCommitPhaseError ,
@@ -172,6 +174,7 @@ import {
172174 setIsRunningInsertionEffect ,
173175 getExecutionContext ,
174176 CommitContext ,
177+ RenderContext ,
175178 NoContext ,
176179} from './ReactFiberWorkLoop.new' ;
177180import {
@@ -200,6 +203,7 @@ import {releaseCache, retainCache} from './ReactFiberCacheComponent.new';
200203import { clearTransitionsForLanes } from './ReactFiberLane.new' ;
201204import {
202205 OffscreenVisible ,
206+ OffscreenDetached ,
203207 OffscreenPassiveEffectsConnected ,
204208} from './ReactFiberOffscreenComponent' ;
205209import {
@@ -2416,6 +2420,28 @@ function getRetryCache(finishedWork) {
24162420 }
24172421}
24182422
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+
24192445function attachSuspenseRetryListeners (
24202446 finishedWork : Fiber ,
24212447 wakeables : Set < Wakeable > ,
@@ -2845,6 +2871,8 @@ function commitMutationEffectsOnFiber(
28452871 }
28462872
28472873 commitReconciliationEffects ( finishedWork ) ;
2874+ // TODO: Add explicit effect flag to set _current.
2875+ finishedWork. stateNode . _current = finishedWork ;
28482876
28492877 if ( flags & Visibility ) {
28502878 const offscreenInstance : OffscreenInstance = finishedWork . stateNode ;
@@ -2871,7 +2899,8 @@ function commitMutationEffectsOnFiber(
28712899 }
28722900 }
28732901
2874- if ( supportsMutation ) {
2902+ // Offscreen with manual mode manages visibility manually.
2903+ if ( supportsMutation && ! isOffscreenManual ( finishedWork ) ) {
28752904 // TODO: This needs to run whenever there's an insertion or update
28762905 // inside a hidden Offscreen tree.
28772906 hideOrUnhideAllChildren ( offscreenBoundary , isHidden ) ;
0 commit comments