@@ -102,7 +102,12 @@ import {
102
102
enterDisallowedContextReadInDEV ,
103
103
exitDisallowedContextReadInDEV ,
104
104
} from './ReactFiberNewContext.new' ;
105
- import { Callback , ShouldCapture , DidCapture } from './ReactFiberFlags' ;
105
+ import {
106
+ Callback ,
107
+ Visibility ,
108
+ ShouldCapture ,
109
+ DidCapture ,
110
+ } from './ReactFiberFlags' ;
106
111
107
112
import { debugRenderPhaseSideEffectsForStrictMode } from 'shared/ReactFeatureFlags' ;
108
113
@@ -136,14 +141,15 @@ export type Update<State> = {|
136
141
export type SharedQueue < State > = { |
137
142
pending : Update < State > | null ,
138
143
lanes : Lanes ,
144
+ hiddenCallbacks : Array < ( ) => mixed > | null ,
139
145
| } ;
140
146
141
147
export type UpdateQueue < State > = { |
142
148
baseState : State ,
143
149
firstBaseUpdate : Update < State > | null ,
144
150
lastBaseUpdate : Update < State > | null ,
145
151
shared : SharedQueue < State > ,
146
- effects : Array < Update < State > > | null ,
152
+ callbacks : Array < ( ) => mixed > | null ,
147
153
| } ;
148
154
149
155
export const UpdateState = 0 ;
@@ -175,8 +181,9 @@ export function initializeUpdateQueue<State>(fiber: Fiber): void {
175
181
shared : {
176
182
pending : null ,
177
183
lanes : NoLanes ,
184
+ hiddenCallbacks : null ,
178
185
} ,
179
- effects : null ,
186
+ callbacks : null ,
180
187
} ;
181
188
fiber . updateQueue = queue ;
182
189
}
@@ -194,7 +201,7 @@ export function cloneUpdateQueue<State>(
194
201
firstBaseUpdate : currentQueue . firstBaseUpdate ,
195
202
lastBaseUpdate : currentQueue . lastBaseUpdate ,
196
203
shared : currentQueue . shared ,
197
- effects : currentQueue . effects ,
204
+ callbacks : null ,
198
205
} ;
199
206
workInProgress . updateQueue = clone ;
200
207
}
@@ -326,7 +333,9 @@ export function enqueueCapturedUpdate<State>(
326
333
327
334
tag : update . tag ,
328
335
payload : update . payload ,
329
- callback : update . callback ,
336
+ // When this update is rebased, we should not fire its
337
+ // callback again.
338
+ callback : null ,
330
339
331
340
next : null ,
332
341
} ;
@@ -355,7 +364,7 @@ export function enqueueCapturedUpdate<State>(
355
364
firstBaseUpdate : newFirst ,
356
365
lastBaseUpdate : newLast ,
357
366
shared : currentQueue . shared ,
358
- effects : currentQueue . effects ,
367
+ callbacks : currentQueue . callbacks ,
359
368
} ;
360
369
workInProgress.updateQueue = queue;
361
370
return;
@@ -577,7 +586,10 @@ export function processUpdateQueue<State>(
577
586
578
587
tag : update . tag ,
579
588
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 ,
581
593
582
594
next : null ,
583
595
} ;
@@ -594,18 +606,16 @@ export function processUpdateQueue<State>(
594
606
instance ,
595
607
) ;
596
608
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 ) {
603
610
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 ] ;
607
617
} else {
608
- effects . push ( update ) ;
618
+ callbacks . push ( callback ) ;
609
619
}
610
620
}
611
621
}
@@ -679,22 +689,51 @@ export function checkHasForceUpdateAfterProcessing(): boolean {
679
689
return hasForceUpdate ;
680
690
}
681
691
682
- export function commitUpdateQueue< State > (
683
- finishedWork: Fiber,
684
- finishedQueue: UpdateQueue< State > ,
685
- instance: any,
692
+ export function deferHiddenCallbacks< State > (
693
+ updateQueue: UpdateQueue< State > ,
686
694
): 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 ) ;
698
737
}
699
738
}
700
739
}
0 commit comments