MCPcopy Create free account
hub / github.com/reactjs/react-rails / updateSuspenseComponent

Function updateSuspenseComponent

lib/assets/react-source/development/react.js:21310–21567  ·  view source on GitHub ↗
(current, workInProgress, renderExpirationTime)

Source from the content-addressed store, hash-verified

21308 }
21309
21310 function updateSuspenseComponent(current, workInProgress, renderExpirationTime) {
21311 var mode = workInProgress.mode;
21312 var nextProps = workInProgress.pendingProps; // This is used by DevTools to force a boundary to suspend.
21313
21314 {
21315 if (shouldSuspend(workInProgress)) {
21316 workInProgress.effectTag |= DidCapture;
21317 }
21318 }
21319
21320 var suspenseContext = suspenseStackCursor.current;
21321 var nextDidTimeout = false;
21322 var didSuspend = (workInProgress.effectTag & DidCapture) !== NoEffect;
21323
21324 if (didSuspend || shouldRemainOnFallback(suspenseContext, current)) {
21325 // Something in this boundary's subtree already suspended. Switch to
21326 // rendering the fallback children.
21327 nextDidTimeout = true;
21328 workInProgress.effectTag &= ~DidCapture;
21329 } else {
21330 // Attempting the main content
21331 if (current === null || current.memoizedState !== null) {
21332 // This is a new mount or this boundary is already showing a fallback state.
21333 // Mark this subtree context as having at least one invisible parent that could
21334 // handle the fallback state.
21335 // Boundaries without fallbacks or should be avoided are not considered since
21336 // they cannot handle preferred fallback states.
21337 if (nextProps.fallback !== undefined && nextProps.unstable_avoidThisFallback !== true) {
21338 suspenseContext = addSubtreeSuspenseContext(suspenseContext, InvisibleParentSuspenseContext);
21339 }
21340 }
21341 }
21342
21343 suspenseContext = setDefaultShallowSuspenseContext(suspenseContext);
21344 pushSuspenseContext(workInProgress, suspenseContext); // This next part is a bit confusing. If the children timeout, we switch to
21345 // showing the fallback children in place of the "primary" children.
21346 // However, we don't want to delete the primary children because then their
21347 // state will be lost (both the React state and the host state, e.g.
21348 // uncontrolled form inputs). Instead we keep them mounted and hide them.
21349 // Both the fallback children AND the primary children are rendered at the
21350 // same time. Once the primary children are un-suspended, we can delete
21351 // the fallback children — don't need to preserve their state.
21352 //
21353 // The two sets of children are siblings in the host environment, but
21354 // semantically, for purposes of reconciliation, they are two separate sets.
21355 // So we store them using two fragment fibers.
21356 //
21357 // However, we want to avoid allocating extra fibers for every placeholder.
21358 // They're only necessary when the children time out, because that's the
21359 // only time when both sets are mounted.
21360 //
21361 // So, the extra fragment fibers are only used if the children time out.
21362 // Otherwise, we render the primary children directly. This requires some
21363 // custom reconciliation logic to preserve the state of the primary
21364 // children. It's essentially a very basic form of re-parenting.
21365
21366 if (current === null) {
21367 // If we're currently hydrating, try to hydrate this boundary.

Callers 1

beginWorkFunction · 0.85

Calls 9

shouldSuspendFunction · 0.85
shouldRemainOnFallbackFunction · 0.85
pushSuspenseContextFunction · 0.85
createFiberFromFragmentFunction · 0.85
createWorkInProgressFunction · 0.85
reconcileChildFibersFunction · 0.85

Tested by

no test coverage detected