420
// The initial value suspended, so we attempt the final value, which
421
// also suspends.
422
'Suspend! [Final]',
423
- // pre-warming
424
- 'Suspend! [Loading...]',
425
- 'Suspend! [Final]',
423
+ ...(gate('enableParallelTransitions')
424
+ ? []
425
+ : [
426
+ // Existing bug: Unnecessary pre-warm.
427
+ 'Suspend! [Loading...]',
428
+ 'Suspend! [Final]',
429
+ ]),
430
]);
431
expect(root).toMatchRenderedOutput(null);
432
443
},
444
);
445
446
+ it(
447
+ 'if a suspended render spawns a deferred task that suspends on a sibling, ' +
448
+ 'we can finish the original task if the original sibling loads first',
449
+ async () => {
450
+ function App() {
451
+ const deferredText = useDeferredValue(`Final`, `Loading...`);
452
+ return (
453
+ <>
454
+ <AsyncText text={deferredText} />{' '}
455
+ <AsyncText text={`Sibling: ${deferredText}`} />
456
+ </>
457
+ );
458
+ }
459
+
460
+ const root = ReactNoop.createRoot();
461
+ await act(() => root.render(<App text="a" />));
462
+ assertLog([
463
+ 'Suspend! [Loading...]',
464
+ // The initial value suspended, so we attempt the final value, which
465
+ // also suspends.
466
+ 'Suspend! [Final]',
467
+ 'Suspend! [Sibling: Final]',
468
+ ...(gate('enableParallelTransitions')
469
+ ? [
470
+ // With parallel transitions,
471
+ // we do not continue pre-warming.
472
+ ]
473
+ : [
474
+ 'Suspend! [Loading...]',
475
+ 'Suspend! [Sibling: Loading...]',
476
+ 'Suspend! [Final]',
477
+ 'Suspend! [Sibling: Final]',
478
+ ]),
479
+ ]);
480
+ expect(root).toMatchRenderedOutput(null);
481
+
482
+ // The final value loads, so we can skip the initial value entirely.
483
+ await act(() => {
484
+ resolveText('Final');
485
+ });
486
+ assertLog(['Final', 'Suspend! [Sibling: Final]']);
487
+ expect(root).toMatchRenderedOutput(null);
488
+
489
+ // The initial value resolves first, so we render that.
490
+ await act(() => resolveText('Loading...'));
491
+ assertLog([
492
+ 'Loading...',
493
+ 'Suspend! [Sibling: Loading...]',
494
+ 'Final',
495
+ 'Suspend! [Sibling: Final]',
496
+ ...(gate('enableParallelTransitions')
497
+ ? [
498
+ // With parallel transitions,
499
+ // we do not continue pre-warming.
500
+ ]
501
+ : [
502
+ 'Loading...',
503
+ 'Suspend! [Sibling: Loading...]',
504
+ 'Final',
505
+ 'Suspend! [Sibling: Final]',
506
+ ]),
507
+ ]);
508
+ expect(root).toMatchRenderedOutput(null);
509
+
510
+ // The Final sibling loads, we're unblocked and commit.
511
+ await act(() => {
512
+ resolveText('Sibling: Final');
513
+ });
514
+ assertLog(['Final', 'Sibling: Final']);
515
+ expect(root).toMatchRenderedOutput('Final Sibling: Final');
516
+
517
+ // We already rendered the Final value, so nothing happens
518
+ await act(() => {
519
+ resolveText('Sibling: Loading...');
520
+ });
521
+ assertLog([]);
522
+ expect(root).toMatchRenderedOutput('Final Sibling: Final');
523
+ },
524
+ );
525
+
526
+ it(
527
+ 'if a suspended render spawns a deferred task that suspends on a sibling,' +
528
+ ' we can switch to the deferred task without finishing the original one',
529
+ async () => {
530
+ function App() {
531
+ const deferredText = useDeferredValue(`Final`, `Loading...`);
532
+ return (
533
+ <>
534
+ <AsyncText text={deferredText} />{' '}
535
+ <AsyncText text={`Sibling: ${deferredText}`} />
536
+ </>
537
+ );
538
+ }
539
+
540
+ const root = ReactNoop.createRoot();
541
+ await act(() => root.render(<App text="a" />));
542
+ assertLog([
543
+ 'Suspend! [Loading...]',
544
+ // The initial value suspended, so we attempt the final value, which
545
+ // also suspends.
546
+ 'Suspend! [Final]',
547
+ 'Suspend! [Sibling: Final]',
548
+ ...(gate('enableParallelTransitions')
549
+ ? [
550
+ // With parallel transitions,
551
+ // we do not continue pre-warming.
552
+ ]
553
+ : [
554
+ 'Suspend! [Loading...]',
555
+ 'Suspend! [Sibling: Loading...]',
556
+ 'Suspend! [Final]',
557
+ 'Suspend! [Sibling: Final]',
558
+ ]),
559
+ ]);
560
+ expect(root).toMatchRenderedOutput(null);
561
+
562
+ // The final value loads, so we can skip the initial value entirely.
563
+ await act(() => {
564
+ resolveText('Final');
565
+ });
566
+ assertLog(['Final', 'Suspend! [Sibling: Final]']);
567
+ expect(root).toMatchRenderedOutput(null);
568
+
569
+ // The initial value resolves first, so we render that.
570
+ await act(() => resolveText('Loading...'));
571
+ assertLog([
572
+ 'Loading...',
573
+ 'Suspend! [Sibling: Loading...]',
574
+ 'Final',
575
+ 'Suspend! [Sibling: Final]',
576
+ ...(gate('enableParallelTransitions')
577
+ ? [
578
+ // With parallel transitions,
579
+ // we do not continue pre-warming.
580
+ ]
581
+ : [
582
+ 'Loading...',
583
+ 'Suspend! [Sibling: Loading...]',
584
+ 'Final',
585
+ 'Suspend! [Sibling: Final]',
586
+ ]),
587
+ ]);
588
+ expect(root).toMatchRenderedOutput(null);
589
+
590
+ // The initial sibling loads, we're unblocked and commit.
591
+ await act(() => {
592
+ resolveText('Sibling: Loading...');
593
+ });
594
+ assertLog([
595
+ 'Loading...',
596
+ 'Sibling: Loading...',
597
+ 'Final',
598
+ 'Suspend! [Sibling: Final]',
599
+ ]);
600
+ expect(root).toMatchRenderedOutput('Loading... Sibling: Loading...');
601
+
602
+ // Now unblock the final sibling.
603
+ await act(() => {
604
+ resolveText('Sibling: Final');
605
+ });
606
+ assertLog(['Final', 'Sibling: Final']);
607
+ expect(root).toMatchRenderedOutput('Final Sibling: Final');
608
+ },
609
+ );
610
+
611
it(
612
'if a suspended render spawns a deferred task, we can switch to the ' +
613
'deferred task without finishing the original one (no Suspense boundary, ' +
631
// The initial value suspended, so we attempt the final value, which
632
// also suspends.
633
'Suspend! [Final]',
465
- // pre-warming
466
- 'Suspend! [Loading...]',
467
- 'Suspend! [Final]',
634
+ ...(gate('enableParallelTransitions')
635
+ ? [
636
+ // With parallel transitions,
637
+ // we do not continue pre-warming.
638
+ ]
639
+ : ['Suspend! [Loading...]', 'Suspend! [Final]']),
640
]);
641
expect(root).toMatchRenderedOutput(null);
642
711
// The initial value suspended, so we attempt the final value, which
712
// also suspends.
713
'Suspend! [Final]',
542
- // pre-warming
543
- 'Suspend! [Loading...]',
544
- 'Suspend! [Final]',
714
+ ...(gate('enableParallelTransitions')
715
+ ? [
716
+ // With parallel transitions,
717
+ // we do not continue pre-warming.
718
+ ]
719
+ : ['Suspend! [Loading...]', 'Suspend! [Final]']),
720
]);
721
expect(root).toMatchRenderedOutput(null);
722