@@ -218,7 +218,7 @@ describe('ReactOffscreen', () => {
218218
219219 // @gate experimental
220220 // @gate enableSuspenseLayoutEffectSemantics
221- it ( 'mounts/unmounts layout effects when visibility changes' , async ( ) => {
221+ it ( 'mounts/unmounts layout effects when visibility changes (starting visible) ' , async ( ) => {
222222 function Child ( { text} ) {
223223 useLayoutEffect ( ( ) => {
224224 Scheduler . unstable_yieldValue ( 'Mount layout' ) ;
@@ -265,4 +265,58 @@ describe('ReactOffscreen', () => {
265265 expect ( Scheduler ) . toHaveYielded ( [ 'Child' , 'Mount layout' ] ) ;
266266 expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
267267 } ) ;
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+ } ) ;
268322} ) ;
0 commit comments