@@ -102,7 +102,12 @@ import {
102102 enterDisallowedContextReadInDEV ,
103103 exitDisallowedContextReadInDEV ,
104104} from './ReactFiberNewContext.new' ;
105- import { Callback , ShouldCapture , DidCapture } from './ReactFiberFlags' ;
105+ import {
106+ Callback ,
107+ Visibility ,
108+ ShouldCapture ,
109+ DidCapture ,
110+ } from './ReactFiberFlags' ;
106111
107112import { debugRenderPhaseSideEffectsForStrictMode } from 'shared/ReactFeatureFlags' ;
108113
@@ -136,14 +141,15 @@ export type Update<State> = {|
136141export type SharedQueue < State > = { |
137142 pending : Update < State > | null ,
138143 lanes : Lanes ,
144+ hiddenCallbacks : Array < ( ) => mixed > | null ,
139145| } ;
140146
141147export type UpdateQueue < State > = { |
142148 baseState : State ,
143149 firstBaseUpdate : Update < State > | null ,
144150 lastBaseUpdate : Update < State > | null ,
145151 shared : SharedQueue < State > ,
146- effects : Array < Update < State > > | null ,
152+ callbacks : Array < ( ) => mixed > | null ,
147153| } ;
148154
149155export const UpdateState = 0 ;
@@ -175,8 +181,9 @@ export function initializeUpdateQueue<State>(fiber: Fiber): void {
175181 shared : {
176182 pending : null ,
177183 lanes : NoLanes ,
184+ hiddenCallbacks : null ,
178185 } ,
179- effects : null ,
186+ callbacks : null ,
180187 } ;
181188 fiber . updateQueue = queue ;
182189}
@@ -194,7 +201,7 @@ export function cloneUpdateQueue<State>(
194201 firstBaseUpdate : currentQueue . firstBaseUpdate ,
195202 lastBaseUpdate : currentQueue . lastBaseUpdate ,
196203 shared : currentQueue . shared ,
197- effects : currentQueue . effects ,
204+ callbacks : null ,
198205 } ;
199206 workInProgress . updateQueue = clone ;
200207 }
@@ -326,7 +333,9 @@ export function enqueueCapturedUpdate<State>(
326333
327334 tag : update . tag ,
328335 payload : update . payload ,
329- callback : update . callback ,
336+ // When this update is rebased, we should not fire its
337+ // callback again.
338+ callback : null ,
330339
331340 next : null ,
332341 } ;
@@ -355,7 +364,7 @@ export function enqueueCapturedUpdate<State>(
355364 firstBaseUpdate : newFirst ,
356365 lastBaseUpdate : newLast ,
357366 shared : currentQueue . shared ,
358- effects : currentQueue . effects ,
367+ callbacks : currentQueue . callbacks ,
359368 } ;
360369 workInProgress.updateQueue = queue;
361370 return;
@@ -577,7 +586,10 @@ export function processUpdateQueue<State>(
577586
578587 tag : update . tag ,
579588 payload : update . payload ,
580- callback : update . callback ,
589+
590+ // When this update is rebased, we should not fire its
591+ // callback again.
592+ callback : null ,
581593
582594 next : null ,
583595 } ;
@@ -594,18 +606,16 @@ export function processUpdateQueue<State>(
594606 instance ,
595607 ) ;
596608 const callback = update . callback ;
597- if (
598- callback !== null &&
599- // If the update was already committed, we should not queue its
600- // callback again.
601- update . lane !== NoLane
602- ) {
609+ if ( callback !== null ) {
603610 workInProgress . flags |= Callback ;
604- const effects = queue . effects ;
605- if ( effects === null ) {
606- queue . effects = [ update ] ;
611+ if ( isHiddenUpdate ) {
612+ workInProgress . flags |= Visibility ;
613+ }
614+ const callbacks = queue.callbacks;
615+ if (callbacks === null) {
616+ queue . callbacks = [ callback ] ;
607617 } else {
608- effects . push ( update ) ;
618+ callbacks . push ( callback ) ;
609619 }
610620 }
611621 }
@@ -679,22 +689,51 @@ export function checkHasForceUpdateAfterProcessing(): boolean {
679689 return hasForceUpdate ;
680690}
681691
682- export function commitUpdateQueue< State > (
683- finishedWork: Fiber,
684- finishedQueue: UpdateQueue< State > ,
685- instance: any,
692+ export function deferHiddenCallbacks< State > (
693+ updateQueue: UpdateQueue< State > ,
686694): void {
687- // Commit the effects
688- const effects = finishedQueue . effects ;
689- finishedQueue . effects = null ;
690- if ( effects !== null ) {
691- for ( let i = 0 ; i < effects . length ; i ++ ) {
692- const effect = effects [ i ] ;
693- const callback = effect . callback ;
694- if ( callback !== null ) {
695- effect . callback = null ;
696- callCallback ( callback , instance ) ;
697- }
695+ // When an update finishes on a hidden component, its callback should not
696+ // be fired until/unless the component is made visible again. Stash the
697+ // callback on the shared queue object so it can be fired later.
698+ const newHiddenCallbacks = updateQueue . callbacks ;
699+ if ( newHiddenCallbacks !== null ) {
700+ const existingHiddenCallbacks = updateQueue . shared . hiddenCallbacks ;
701+ if ( existingHiddenCallbacks === null ) {
702+ updateQueue . shared . hiddenCallbacks = newHiddenCallbacks ;
703+ } else {
704+ updateQueue. shared . hiddenCallbacks = existingHiddenCallbacks . concat (
705+ newHiddenCallbacks ,
706+ ) ;
707+ }
708+ }
709+ }
710+
711+ export function commitHiddenCallbacks < State > (
712+ updateQueue: UpdateQueue< State > ,
713+ context: any,
714+ ): void {
715+ // This component is switching from hidden -> visible. Commit any callbacks
716+ // that were previously deferred.
717+ const hiddenCallbacks = updateQueue . shared . hiddenCallbacks ;
718+ if ( hiddenCallbacks !== null ) {
719+ updateQueue . shared . hiddenCallbacks = null ;
720+ for ( let i = 0 ; i < hiddenCallbacks . length ; i ++ ) {
721+ const callback = hiddenCallbacks [ i ] ;
722+ callCallback ( callback , context ) ;
723+ }
724+ }
725+ }
726+
727+ export function commitCallbacks< State > (
728+ updateQueue: UpdateQueue< State > ,
729+ context: any,
730+ ): void {
731+ const callbacks = updateQueue . callbacks ;
732+ if ( callbacks !== null ) {
733+ updateQueue . callbacks = null ;
734+ for ( let i = 0 ; i < callbacks . length ; i ++ ) {
735+ const callback = callbacks [ i ] ;
736+ callCallback ( callback , context ) ;
698737 }
699738 }
700739}
0 commit comments