@@ -1302,20 +1302,25 @@ describe('ReactLazy', () => {
1302
1302
Scheduler . unstable_yieldValue ( 'Init A2' ) ;
1303
1303
return fakeImport ( ChildA ) ;
1304
1304
} ) ;
1305
+ let resolveB2 ;
1305
1306
const LazyChildB2 = lazy ( ( ) => {
1306
1307
Scheduler . unstable_yieldValue ( 'Init B2' ) ;
1307
- return fakeImport ( ChildB ) ;
1308
+ return new Promise ( r => {
1309
+ resolveB2 = r ;
1310
+ } ) ;
1308
1311
} ) ;
1309
1312
1310
1313
function Parent ( { swap} ) {
1311
1314
return (
1312
- < Suspense fallback = { < Text text = "Loading..." /> } >
1313
- { swap
1314
- ? [
1315
- < LazyChildB2 key = "B" lowerCase = { true } /> ,
1316
- < LazyChildA2 key = "A" lowerCase = { true } /> ,
1317
- ]
1318
- : [ < LazyChildA key = "A" /> , < LazyChildB key = "B" /> ] }
1315
+ < Suspense fallback = { < Text text = "Outer..." /> } >
1316
+ < Suspense fallback = { < Text text = "Loading..." /> } >
1317
+ { swap
1318
+ ? [
1319
+ < LazyChildB2 key = "B" lowerCase = { true } /> ,
1320
+ < LazyChildA2 key = "A" lowerCase = { true } /> ,
1321
+ ]
1322
+ : [ < LazyChildA key = "A" /> , < LazyChildB key = "B" /> ] }
1323
+ </ Suspense >
1319
1324
</ Suspense >
1320
1325
) ;
1321
1326
}
@@ -1338,12 +1343,107 @@ describe('ReactLazy', () => {
1338
1343
] ) ;
1339
1344
expect ( root ) . toMatchRenderedOutput ( 'AB' ) ;
1340
1345
1346
+ // Swap the position of A and B
1347
+ ReactTestRenderer . act ( ( ) => {
1348
+ root . update ( < Parent swap = { true } /> ) ;
1349
+ expect ( Scheduler ) . toFlushAndYield ( [ 'Init B2' , 'Loading...' ] ) ;
1350
+ } ) ;
1351
+
1352
+ // The suspense boundary should've triggered now.
1353
+ expect ( root ) . toMatchRenderedOutput ( 'Loading...' ) ;
1354
+ await resolveB2 ( { default : ChildB } ) ;
1355
+
1356
+ // We need to flush to trigger the second one to load.
1357
+ expect ( Scheduler ) . toFlushAndYield ( [ 'Init A2' ] ) ;
1358
+ await LazyChildA2 ;
1359
+
1360
+ expect ( Scheduler ) . toFlushAndYield ( [
1361
+ 'b' ,
1362
+ 'a' ,
1363
+ 'Did update: b' ,
1364
+ 'Did update: a' ,
1365
+ ] ) ;
1366
+ expect ( root ) . toMatchRenderedOutput ( 'ba' ) ;
1367
+ } ) ;
1368
+
1369
+ // @gate enableLazyElements
1370
+ it ( 'mount and reorder lazy types (legacy mode)' , async ( ) => {
1371
+ class Child extends React . Component {
1372
+ componentDidMount ( ) {
1373
+ Scheduler . unstable_yieldValue ( 'Did mount: ' + this . props . label ) ;
1374
+ }
1375
+ componentDidUpdate ( ) {
1376
+ Scheduler . unstable_yieldValue ( 'Did update: ' + this . props . label ) ;
1377
+ }
1378
+ render ( ) {
1379
+ return < Text text = { this . props . label } /> ;
1380
+ }
1381
+ }
1382
+
1383
+ function ChildA ( { lowerCase} ) {
1384
+ return < Child label = { lowerCase ? 'a' : 'A' } /> ;
1385
+ }
1386
+
1387
+ function ChildB ( { lowerCase} ) {
1388
+ return < Child label = { lowerCase ? 'b' : 'B' } /> ;
1389
+ }
1390
+
1391
+ const LazyChildA = lazy ( ( ) => {
1392
+ Scheduler . unstable_yieldValue ( 'Init A' ) ;
1393
+ return fakeImport ( ChildA ) ;
1394
+ } ) ;
1395
+ const LazyChildB = lazy ( ( ) => {
1396
+ Scheduler . unstable_yieldValue ( 'Init B' ) ;
1397
+ return fakeImport ( ChildB ) ;
1398
+ } ) ;
1399
+ const LazyChildA2 = lazy ( ( ) => {
1400
+ Scheduler . unstable_yieldValue ( 'Init A2' ) ;
1401
+ return fakeImport ( ChildA ) ;
1402
+ } ) ;
1403
+ const LazyChildB2 = lazy ( ( ) => {
1404
+ Scheduler . unstable_yieldValue ( 'Init B2' ) ;
1405
+ return fakeImport ( ChildB ) ;
1406
+ } ) ;
1407
+
1408
+ function Parent ( { swap} ) {
1409
+ return (
1410
+ < Suspense fallback = { < Text text = "Outer..." /> } >
1411
+ < Suspense fallback = { < Text text = "Loading..." /> } >
1412
+ { swap
1413
+ ? [
1414
+ < LazyChildB2 key = "B" lowerCase = { true } /> ,
1415
+ < LazyChildA2 key = "A" lowerCase = { true } /> ,
1416
+ ]
1417
+ : [ < LazyChildA key = "A" /> , < LazyChildB key = "B" /> ] }
1418
+ </ Suspense >
1419
+ </ Suspense >
1420
+ ) ;
1421
+ }
1422
+
1423
+ const root = ReactTestRenderer . create ( < Parent swap = { false } /> , {
1424
+ unstable_isConcurrent : false ,
1425
+ } ) ;
1426
+
1427
+ expect ( Scheduler ) . toHaveYielded ( [ 'Init A' , 'Init B' , 'Loading...' ] ) ;
1428
+ expect ( root ) . not . toMatchRenderedOutput ( 'AB' ) ;
1429
+
1430
+ await LazyChildA ;
1431
+ await LazyChildB ;
1432
+
1433
+ expect ( Scheduler ) . toFlushAndYield ( [
1434
+ 'A' ,
1435
+ 'B' ,
1436
+ 'Did mount: A' ,
1437
+ 'Did mount: B' ,
1438
+ ] ) ;
1439
+ expect ( root ) . toMatchRenderedOutput ( 'AB' ) ;
1440
+
1341
1441
// Swap the position of A and B
1342
1442
root . update ( < Parent swap = { true } /> ) ;
1343
- expect ( Scheduler ) . toFlushAndYield ( [ 'Init B2' , 'Loading...' ] ) ;
1443
+ expect ( Scheduler ) . toHaveYielded ( [ 'Init B2' , 'Loading...' ] ) ;
1344
1444
await LazyChildB2 ;
1345
1445
// We need to flush to trigger the second one to load.
1346
- expect ( Scheduler ) . toFlushAndYield ( [ 'Init A2' , 'Loading...' ] ) ;
1446
+ expect ( Scheduler ) . toFlushAndYield ( [ 'Init A2' ] ) ;
1347
1447
await LazyChildA2 ;
1348
1448
1349
1449
expect ( Scheduler ) . toFlushAndYield ( [
@@ -1430,4 +1530,80 @@ describe('ReactLazy', () => {
1430
1530
] ) ;
1431
1531
expect ( root ) . toMatchRenderedOutput ( 'ba' ) ;
1432
1532
} ) ;
1533
+
1534
+ // @gate enableLazyElements
1535
+ it ( 'mount and reorder lazy elements (legacy mode)' , async ( ) => {
1536
+ class Child extends React . Component {
1537
+ componentDidMount ( ) {
1538
+ Scheduler . unstable_yieldValue ( 'Did mount: ' + this . props . label ) ;
1539
+ }
1540
+ componentDidUpdate ( ) {
1541
+ Scheduler . unstable_yieldValue ( 'Did update: ' + this . props . label ) ;
1542
+ }
1543
+ render ( ) {
1544
+ return < Text text = { this . props . label } /> ;
1545
+ }
1546
+ }
1547
+
1548
+ const lazyChildA = lazy ( ( ) => {
1549
+ Scheduler . unstable_yieldValue ( 'Init A' ) ;
1550
+ return fakeImport ( < Child key = "A" label = "A" /> ) ;
1551
+ } ) ;
1552
+ const lazyChildB = lazy ( ( ) => {
1553
+ Scheduler . unstable_yieldValue ( 'Init B' ) ;
1554
+ return fakeImport ( < Child key = "B" label = "B" /> ) ;
1555
+ } ) ;
1556
+ const lazyChildA2 = lazy ( ( ) => {
1557
+ Scheduler . unstable_yieldValue ( 'Init A2' ) ;
1558
+ return fakeImport ( < Child key = "A" label = "a" /> ) ;
1559
+ } ) ;
1560
+ const lazyChildB2 = lazy ( ( ) => {
1561
+ Scheduler . unstable_yieldValue ( 'Init B2' ) ;
1562
+ return fakeImport ( < Child key = "B" label = "b" /> ) ;
1563
+ } ) ;
1564
+
1565
+ function Parent ( { swap} ) {
1566
+ return (
1567
+ < Suspense fallback = { < Text text = "Loading..." /> } >
1568
+ { swap ? [ lazyChildB2 , lazyChildA2 ] : [ lazyChildA , lazyChildB ] }
1569
+ </ Suspense >
1570
+ ) ;
1571
+ }
1572
+
1573
+ const root = ReactTestRenderer . create ( < Parent swap = { false } /> , {
1574
+ unstable_isConcurrent : false ,
1575
+ } ) ;
1576
+
1577
+ expect ( Scheduler ) . toHaveYielded ( [ 'Init A' , 'Loading...' ] ) ;
1578
+ expect ( root ) . not . toMatchRenderedOutput ( 'AB' ) ;
1579
+
1580
+ await lazyChildA ;
1581
+ // We need to flush to trigger the B to load.
1582
+ expect ( Scheduler ) . toFlushAndYield ( [ 'Init B' ] ) ;
1583
+ await lazyChildB ;
1584
+
1585
+ expect ( Scheduler ) . toFlushAndYield ( [
1586
+ 'A' ,
1587
+ 'B' ,
1588
+ 'Did mount: A' ,
1589
+ 'Did mount: B' ,
1590
+ ] ) ;
1591
+ expect ( root ) . toMatchRenderedOutput ( 'AB' ) ;
1592
+
1593
+ // Swap the position of A and B
1594
+ root . update ( < Parent swap = { true } /> ) ;
1595
+ expect ( Scheduler ) . toHaveYielded ( [ 'Init B2' , 'Loading...' ] ) ;
1596
+ await lazyChildB2 ;
1597
+ // We need to flush to trigger the second one to load.
1598
+ expect ( Scheduler ) . toFlushAndYield ( [ 'Init A2' ] ) ;
1599
+ await lazyChildA2 ;
1600
+
1601
+ expect ( Scheduler ) . toFlushAndYield ( [
1602
+ 'b' ,
1603
+ 'a' ,
1604
+ 'Did update: b' ,
1605
+ 'Did update: a' ,
1606
+ ] ) ;
1607
+ expect ( root ) . toMatchRenderedOutput ( 'ba' ) ;
1608
+ } ) ;
1433
1609
} ) ;
0 commit comments