mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
[Fizz] Delay detachment of completed boundaries until reveal (#33511)
This commit is contained in:
parent
888ea60d8e
commit
a00ca6f6b5
|
|
@ -4,6 +4,7 @@ import React, {
|
||||||
useEffect,
|
useEffect,
|
||||||
useState,
|
useState,
|
||||||
unstable_addTransitionType as addTransitionType,
|
unstable_addTransitionType as addTransitionType,
|
||||||
|
use,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
import Chrome from './Chrome';
|
import Chrome from './Chrome';
|
||||||
|
|
|
||||||
36
fixtures/view-transition/src/components/NestedReveal.js
Normal file
36
fixtures/view-transition/src/components/NestedReveal.js
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import React, {Suspense, use} from 'react';
|
||||||
|
|
||||||
|
async function sleep(ms) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
function Use({useable}) {
|
||||||
|
use(useable);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let delay1;
|
||||||
|
let delay2;
|
||||||
|
|
||||||
|
export default function NestedReveal({}) {
|
||||||
|
if (!delay1) {
|
||||||
|
delay1 = sleep(100);
|
||||||
|
// Needs to happen before the throttled reveal of delay 1
|
||||||
|
delay2 = sleep(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="swipe-recognizer">
|
||||||
|
Shell
|
||||||
|
<Suspense fallback="Loading level 1">
|
||||||
|
<div>Level 1</div>
|
||||||
|
<Use useable={delay1} />
|
||||||
|
|
||||||
|
<Suspense fallback="Loading level 2">
|
||||||
|
<div>Level 2</div>
|
||||||
|
<Use useable={delay2} />
|
||||||
|
</Suspense>
|
||||||
|
</Suspense>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ import SwipeRecognizer from './SwipeRecognizer';
|
||||||
import './Page.css';
|
import './Page.css';
|
||||||
|
|
||||||
import transitions from './Transitions.module.css';
|
import transitions from './Transitions.module.css';
|
||||||
|
import NestedReveal from './NestedReveal';
|
||||||
|
|
||||||
async function sleep(ms) {
|
async function sleep(ms) {
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
|
@ -241,6 +242,7 @@ export default function Page({url, navigate}) {
|
||||||
</div>
|
</div>
|
||||||
</ViewTransition>
|
</ViewTransition>
|
||||||
</SwipeRecognizer>
|
</SwipeRecognizer>
|
||||||
|
<NestedReveal />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export const markShellTime =
|
||||||
export const clientRenderBoundary =
|
export const clientRenderBoundary =
|
||||||
'$RX=function(b,c,d,e,f){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data="$!",a=a.dataset,c&&(a.dgst=c),d&&(a.msg=d),e&&(a.stck=e),f&&(a.cstck=f),b._reactRetry&&b._reactRetry())};';
|
'$RX=function(b,c,d,e,f){var a=document.getElementById(b);a&&(b=a.previousSibling,b.data="$!",a=a.dataset,c&&(a.dgst=c),d&&(a.msg=d),e&&(a.stck=e),f&&(a.cstck=f),b._reactRetry&&b._reactRetry())};';
|
||||||
export const completeBoundary =
|
export const completeBoundary =
|
||||||
'$RB=[];$RV=function(b){$RT=performance.now();for(var a=0;a<b.length;a+=2){var c=b[a],h=b[a+1],e=c.parentNode;if(e){var f=c.previousSibling,g=0;do{if(c&&8===c.nodeType){var d=c.data;if("/$"===d||"/&"===d)if(0===g)break;else g--;else"$"!==d&&"$?"!==d&&"$~"!==d&&"$!"!==d&&"&"!==d||g++}d=c.nextSibling;e.removeChild(c);c=d}while(c);for(;h.firstChild;)e.insertBefore(h.firstChild,c);f.data="$";f._reactRetry&&f._reactRetry()}}b.length=0};$RC=function(b,a){if(a=document.getElementById(a))if(a.parentNode.removeChild(a),b=document.getElementById(b))b.previousSibling.data="$~",$RB.push(b,a),2===$RB.length&&(b="number"!==typeof $RT?0:$RT,a=performance.now(),setTimeout($RV.bind(null,$RB),2300>a&&2E3<a?2300-a:b+300-a))};';
|
'$RB=[];$RV=function(b){$RT=performance.now();for(var a=0;a<b.length;a+=2){var c=b[a],e=b[a+1];e.parentNode.removeChild(e);var f=c.parentNode;if(f){var g=c.previousSibling,h=0;do{if(c&&8===c.nodeType){var d=c.data;if("/$"===d||"/&"===d)if(0===h)break;else h--;else"$"!==d&&"$?"!==d&&"$~"!==d&&"$!"!==d&&"&"!==d||h++}d=c.nextSibling;f.removeChild(c);c=d}while(c);for(;e.firstChild;)f.insertBefore(e.firstChild,c);g.data="$";g._reactRetry&&g._reactRetry()}}b.length=0};$RC=function(b,a){if(a=document.getElementById(a))(b=document.getElementById(b))?(b.previousSibling.data="$~",$RB.push(b,a),2===$RB.length&&(b="number"!==typeof $RT?0:$RT,a=performance.now(),setTimeout($RV.bind(null,$RB),2300>a&&2E3<a?2300-a:b+300-a))):a.parentNode.removeChild(a)};';
|
||||||
export const completeBoundaryUpgradeToViewTransitions =
|
export const completeBoundaryUpgradeToViewTransitions =
|
||||||
'$RV=function(A,g){function k(a,b){var e=a.getAttribute(b);e&&(b=a.style,l.push(a,b.viewTransitionName,b.viewTransitionClass),"auto"!==e&&(b.viewTransitionClass=e),(a=a.getAttribute("vt-name"))||(a="_T_"+K++ +"_"),b.viewTransitionName=a,B=!0)}var B=!1,K=0,l=[];try{var f=document.__reactViewTransition;if(f){f.finished.finally($RV.bind(null,g));return}var m=new Map;for(f=1;f<g.length;f+=2)for(var h=g[f].querySelectorAll("[vt-share]"),d=0;d<h.length;d++){var c=h[d];m.set(c.getAttribute("vt-name"),c)}var u=[];for(h=0;h<g.length;h+=2){var C=g[h],x=C.parentNode;if(x){var v=x.getBoundingClientRect();if(v.left||v.top||v.width||v.height){c=C;for(f=0;c;){if(8===c.nodeType){var r=c.data;if("/$"===r)if(0===f)break;else f--;else"$"!==r&&"$?"!==r&&"$~"!==r&&"$!"!==r||f++}else if(1===c.nodeType){d=c;var D=d.getAttribute("vt-name"),y=m.get(D);k(d,y?"vt-share":"vt-exit");y&&(k(y,"vt-share"),m.set(D,null));var E=d.querySelectorAll("[vt-share]");for(d=0;d<E.length;d++){var F=E[d],G=F.getAttribute("vt-name"),\nH=m.get(G);H&&(k(F,"vt-share"),k(H,"vt-share"),m.set(G,null))}}c=c.nextSibling}for(var I=g[h+1],t=I.firstElementChild;t;)null!==m.get(t.getAttribute("vt-name"))&&k(t,"vt-enter"),t=t.nextElementSibling;c=x;do for(var n=c.firstElementChild;n;){var J=n.getAttribute("vt-update");J&&"none"!==J&&!l.includes(n)&&k(n,"vt-update");n=n.nextElementSibling}while((c=c.parentNode)&&1===c.nodeType&&"none"!==c.getAttribute("vt-update"));u.push.apply(u,I.querySelectorAll(\'img[src]:not([loading="lazy"])\'))}}}if(B){var z=\ndocument.__reactViewTransition=document.startViewTransition({update:function(){A(g);for(var a=[document.documentElement.clientHeight,document.fonts.ready],b={},e=0;e<u.length;b={g:b.g},e++)if(b.g=u[e],!b.g.complete){var p=b.g.getBoundingClientRect();0<p.bottom&&0<p.right&&p.top<window.innerHeight&&p.left<window.innerWidth&&(p=new Promise(function(w){return function(q){w.g.addEventListener("load",q);w.g.addEventListener("error",q)}}(b)),a.push(p))}return Promise.race([Promise.all(a),new Promise(function(w){var q=\nperformance.now();setTimeout(w,2300>q&&2E3<q?2300-q:500)})])},types:[]});z.ready.finally(function(){for(var a=l.length-3;0<=a;a-=3){var b=l[a],e=b.style;e.viewTransitionName=l[a+1];e.viewTransitionClass=l[a+1];""===b.getAttribute("style")&&b.removeAttribute("style")}});z.finished.finally(function(){document.__reactViewTransition===z&&(document.__reactViewTransition=null)});$RB=[];return}}catch(a){}A(g)}.bind(null,$RV);';
|
'$RV=function(A,g){function k(a,b){var e=a.getAttribute(b);e&&(b=a.style,l.push(a,b.viewTransitionName,b.viewTransitionClass),"auto"!==e&&(b.viewTransitionClass=e),(a=a.getAttribute("vt-name"))||(a="_T_"+K++ +"_"),b.viewTransitionName=a,B=!0)}var B=!1,K=0,l=[];try{var f=document.__reactViewTransition;if(f){f.finished.finally($RV.bind(null,g));return}var m=new Map;for(f=1;f<g.length;f+=2)for(var h=g[f].querySelectorAll("[vt-share]"),d=0;d<h.length;d++){var c=h[d];m.set(c.getAttribute("vt-name"),c)}var u=[];for(h=0;h<g.length;h+=2){var C=g[h],x=C.parentNode;if(x){var v=x.getBoundingClientRect();if(v.left||v.top||v.width||v.height){c=C;for(f=0;c;){if(8===c.nodeType){var r=c.data;if("/$"===r)if(0===f)break;else f--;else"$"!==r&&"$?"!==r&&"$~"!==r&&"$!"!==r||f++}else if(1===c.nodeType){d=c;var D=d.getAttribute("vt-name"),y=m.get(D);k(d,y?"vt-share":"vt-exit");y&&(k(y,"vt-share"),m.set(D,null));var E=d.querySelectorAll("[vt-share]");for(d=0;d<E.length;d++){var F=E[d],G=F.getAttribute("vt-name"),\nH=m.get(G);H&&(k(F,"vt-share"),k(H,"vt-share"),m.set(G,null))}}c=c.nextSibling}for(var I=g[h+1],t=I.firstElementChild;t;)null!==m.get(t.getAttribute("vt-name"))&&k(t,"vt-enter"),t=t.nextElementSibling;c=x;do for(var n=c.firstElementChild;n;){var J=n.getAttribute("vt-update");J&&"none"!==J&&!l.includes(n)&&k(n,"vt-update");n=n.nextElementSibling}while((c=c.parentNode)&&1===c.nodeType&&"none"!==c.getAttribute("vt-update"));u.push.apply(u,I.querySelectorAll(\'img[src]:not([loading="lazy"])\'))}}}if(B){var z=\ndocument.__reactViewTransition=document.startViewTransition({update:function(){A(g);for(var a=[document.documentElement.clientHeight,document.fonts.ready],b={},e=0;e<u.length;b={g:b.g},e++)if(b.g=u[e],!b.g.complete){var p=b.g.getBoundingClientRect();0<p.bottom&&0<p.right&&p.top<window.innerHeight&&p.left<window.innerWidth&&(p=new Promise(function(w){return function(q){w.g.addEventListener("load",q);w.g.addEventListener("error",q)}}(b)),a.push(p))}return Promise.race([Promise.all(a),new Promise(function(w){var q=\nperformance.now();setTimeout(w,2300>q&&2E3<q?2300-q:500)})])},types:[]});z.ready.finally(function(){for(var a=l.length-3;0<=a;a-=3){var b=l[a],e=b.style;e.viewTransitionName=l[a+1];e.viewTransitionClass=l[a+1];""===b.getAttribute("style")&&b.removeAttribute("style")}});z.finished.finally(function(){document.__reactViewTransition===z&&(document.__reactViewTransition=null)});$RB=[];return}}catch(a){}A(g)}.bind(null,$RV);';
|
||||||
export const completeBoundaryWithStyles =
|
export const completeBoundaryWithStyles =
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,10 @@ export function revealCompletedBoundaries(batch) {
|
||||||
for (let i = 0; i < batch.length; i += 2) {
|
for (let i = 0; i < batch.length; i += 2) {
|
||||||
const suspenseIdNode = batch[i];
|
const suspenseIdNode = batch[i];
|
||||||
const contentNode = batch[i + 1];
|
const contentNode = batch[i + 1];
|
||||||
|
// We can detach the content now.
|
||||||
|
// Completions of boundaries within this contentNode will now find the boundary
|
||||||
|
// in its designated place.
|
||||||
|
contentNode.parentNode.removeChild(contentNode);
|
||||||
|
|
||||||
// Clear all the existing children. This is complicated because
|
// Clear all the existing children. This is complicated because
|
||||||
// there can be embedded Suspense boundaries in the fallback.
|
// there can be embedded Suspense boundaries in the fallback.
|
||||||
|
|
@ -385,13 +389,16 @@ export function completeBoundary(suspenseBoundaryID, contentID) {
|
||||||
// the segment. Regardless we can ignore this case.
|
// the segment. Regardless we can ignore this case.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We'll detach the content node so that regardless of what happens next we don't leave in the tree.
|
|
||||||
// This might also help by not causing recalcing each time we move a child from here to the target.
|
|
||||||
contentNodeOuter.parentNode.removeChild(contentNodeOuter);
|
|
||||||
|
|
||||||
// Find the fallback's first element.
|
// Find the fallback's first element.
|
||||||
const suspenseIdNodeOuter = document.getElementById(suspenseBoundaryID);
|
const suspenseIdNodeOuter = document.getElementById(suspenseBoundaryID);
|
||||||
if (!suspenseIdNodeOuter) {
|
if (!suspenseIdNodeOuter) {
|
||||||
|
// We'll never reveal this boundary so we can remove its content immediately.
|
||||||
|
// Otherwise we'll leave it in until we reveal it.
|
||||||
|
// This is important in case this specific boundary contains other boundaries
|
||||||
|
// that may get completed before we reveal this one.
|
||||||
|
contentNodeOuter.parentNode.removeChild(contentNodeOuter);
|
||||||
|
|
||||||
// The user must have already navigated away from this tree.
|
// The user must have already navigated away from this tree.
|
||||||
// E.g. because the parent was hydrated. That's fine there's nothing to do
|
// E.g. because the parent was hydrated. That's fine there's nothing to do
|
||||||
// but we have to make sure that we already deleted the container node.
|
// but we have to make sure that we already deleted the container node.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user