@@ -218,7 +218,7 @@ describe('ReactOffscreen', () => {
218
218
219
219
// @gate experimental
220
220
// @gate enableSuspenseLayoutEffectSemantics
221
- it ( 'mounts/unmounts layout effects when visibility changes' , async ( ) => {
221
+ it ( 'mounts/unmounts layout effects when visibility changes (starting visible) ' , async ( ) => {
222
222
function Child ( { text} ) {
223
223
useLayoutEffect ( ( ) => {
224
224
Scheduler . unstable_yieldValue ( 'Mount layout' ) ;
@@ -265,4 +265,58 @@ describe('ReactOffscreen', () => {
265
265
expect ( Scheduler ) . toHaveYielded ( [ 'Child' , 'Mount layout' ] ) ;
266
266
expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
267
267
} ) ;
268
+
269
+ // @gate experimental
270
+ // @gate enableSuspenseLayoutEffectSemantics
271
+ it ( 'mounts/unmounts layout effects when visibility changes (starting hidden)' , async ( ) => {
272
+ function Child ( { text} ) {
273
+ useLayoutEffect ( ( ) => {
274
+ Scheduler . unstable_yieldValue ( 'Mount layout' ) ;
275
+ return ( ) => {
276
+ Scheduler . unstable_yieldValue ( 'Unmount layout' ) ;
277
+ } ;
278
+ } , [ ] ) ;
279
+ return < Text text = "Child" /> ;
280
+ }
281
+
282
+ const root = ReactNoop . createRoot ( ) ;
283
+ await ReactNoop . act ( async ( ) => {
284
+ // Start the tree hidden. The layout effect is not mounted.
285
+ root . render (
286
+ < Offscreen mode = "hidden" >
287
+ < Child />
288
+ </ Offscreen > ,
289
+ ) ;
290
+ } ) ;
291
+ expect ( Scheduler ) . toHaveYielded ( [ 'Child' ] ) ;
292
+ // TODO: Offscreen does not yet hide/unhide children correctly. Until we do,
293
+ // it should only be used inside a host component wrapper whose visibility
294
+ // is toggled simultaneously.
295
+ expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
296
+
297
+ // Show the tree. The layout effect is mounted.
298
+ await ReactNoop . act ( async ( ) => {
299
+ root . render (
300
+ < Offscreen mode = "visible" >
301
+ < Child />
302
+ </ Offscreen > ,
303
+ ) ;
304
+ } ) ;
305
+ expect ( Scheduler ) . toHaveYielded ( [ 'Child' , 'Mount layout' ] ) ;
306
+ expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
307
+
308
+ // Hide the tree again. The layout effect is un-mounted.
309
+ await ReactNoop . act ( async ( ) => {
310
+ root . render (
311
+ < Offscreen mode = "hidden" >
312
+ < Child />
313
+ </ Offscreen > ,
314
+ ) ;
315
+ } ) ;
316
+ expect ( Scheduler ) . toHaveYielded ( [ 'Unmount layout' , 'Child' ] ) ;
317
+ // TODO: Offscreen does not yet hide/unhide children correctly. Until we do,
318
+ // it should only be used inside a host component wrapper whose visibility
319
+ // is toggled simultaneously.
320
+ expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
321
+ } ) ;
268
322
} ) ;
0 commit comments