Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b738ced

Browse files
author
Andrew Clark
authored
Remove render prop option from Suspense (facebook#13880)
This was the original, lower-level API before we landed on `fallback` instead. (We might add a different lower-level API in the future, likely alongside a new API for catching errors).
1 parent 55b8279 commit b738ced

File tree

2 files changed

+17
-71
lines changed

2 files changed

+17
-71
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.js

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -990,16 +990,6 @@ function updateSuspenseComponent(
990990
}
991991
}
992992

993-
// If the `children` prop is a function, treat it like a render prop.
994-
// TODO: Remove this, or put it behind a feature flag
995-
const children = nextProps.children;
996-
let nextChildren;
997-
if (typeof children === 'function') {
998-
nextChildren = children(nextDidTimeout);
999-
} else {
1000-
nextChildren = nextDidTimeout ? nextProps.fallback : children;
1001-
}
1002-
1003993
// This next part is a bit confusing. If the children timeout, we switch to
1004994
// showing the fallback children in place of the "primary" children.
1005995
// However, we don't want to delete the primary children because then their
@@ -1036,14 +1026,15 @@ function updateSuspenseComponent(
10361026
// no previous state that needs to be preserved.
10371027
if (nextDidTimeout) {
10381028
// Mount separate fragments for primary and fallback children.
1029+
const nextFallbackChildren = nextProps.fallback;
10391030
const primaryChildFragment = createFiberFromFragment(
10401031
null,
10411032
mode,
10421033
NoWork,
10431034
null,
10441035
);
10451036
const fallbackChildFragment = createFiberFromFragment(
1046-
nextChildren,
1037+
nextFallbackChildren,
10471038
mode,
10481039
renderExpirationTime,
10491040
null,
@@ -1056,10 +1047,11 @@ function updateSuspenseComponent(
10561047
child.return = next.return = workInProgress;
10571048
} else {
10581049
// Mount the primary children without an intermediate fragment fiber.
1050+
const nextPrimaryChildren = nextProps.children;
10591051
child = next = mountChildFibers(
10601052
workInProgress,
10611053
null,
1062-
nextChildren,
1054+
nextPrimaryChildren,
10631055
renderExpirationTime,
10641056
);
10651057
}
@@ -1076,6 +1068,7 @@ function updateSuspenseComponent(
10761068
if (nextDidTimeout) {
10771069
// Still timed out. Reuse the current primary children by cloning
10781070
// its fragment. We're going to skip over these entirely.
1071+
const nextFallbackChildren = nextProps.fallback;
10791072
const primaryChildFragment = createWorkInProgress(
10801073
currentFallbackChildFragment,
10811074
currentFallbackChildFragment.pendingProps,
@@ -1086,7 +1079,7 @@ function updateSuspenseComponent(
10861079
// working on.
10871080
const fallbackChildFragment = (primaryChildFragment.sibling = createWorkInProgress(
10881081
currentFallbackChildFragment,
1089-
nextChildren,
1082+
nextFallbackChildren,
10901083
currentFallbackChildFragment.expirationTime,
10911084
));
10921085
fallbackChildFragment.effectTag |= Placement;
@@ -1098,12 +1091,13 @@ function updateSuspenseComponent(
10981091
} else {
10991092
// No longer suspended. Switch back to showing the primary children,
11001093
// and remove the intermediate fragment fiber.
1094+
const nextPrimaryChildren = nextProps.children;
11011095
const currentPrimaryChild = currentPrimaryChildFragment.child;
11021096
const currentFallbackChild = currentFallbackChildFragment.child;
11031097
const primaryChild = reconcileChildFibers(
11041098
workInProgress,
11051099
currentPrimaryChild,
1106-
nextChildren,
1100+
nextPrimaryChildren,
11071101
renderExpirationTime,
11081102
);
11091103
// Delete the fallback children.
@@ -1123,6 +1117,7 @@ function updateSuspenseComponent(
11231117
if (nextDidTimeout) {
11241118
// Timed out. Wrap the children in a fragment fiber to keep them
11251119
// separate from the fallback children.
1120+
const nextFallbackChildren = nextProps.fallback;
11261121
const primaryChildFragment = createFiberFromFragment(
11271122
// It shouldn't matter what the pending props are because we aren't
11281123
// going to render this fragment.
@@ -1136,7 +1131,7 @@ function updateSuspenseComponent(
11361131
currentPrimaryChild.return = primaryChildFragment;
11371132
// Create a fragment from the fallback children, too.
11381133
const fallbackChildFragment = (primaryChildFragment.sibling = createFiberFromFragment(
1139-
nextChildren,
1134+
nextFallbackChildren,
11401135
mode,
11411136
renderExpirationTime,
11421137
null,
@@ -1150,10 +1145,11 @@ function updateSuspenseComponent(
11501145
} else {
11511146
// Still haven't timed out. Continue rendering the children, like we
11521147
// normally do.
1148+
const nextPrimaryChildren = nextProps.children;
11531149
next = child = reconcileChildFibers(
11541150
workInProgress,
11551151
currentPrimaryChild,
1156-
nextChildren,
1152+
nextPrimaryChildren,
11571153
renderExpirationTime,
11581154
);
11591155
}

packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -670,11 +670,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
670670

671671
it('throws a helpful error when an update is suspends without a placeholder', () => {
672672
expect(() => {
673-
ReactNoop.flushSync(() =>
674-
ReactNoop.render(
675-
<Suspense>{() => <AsyncText text="Async" />}</Suspense>,
676-
),
677-
);
673+
ReactNoop.flushSync(() => ReactNoop.render(<AsyncText text="Async" />));
678674
}).toThrow('An update was suspended, but no placeholder UI was provided.');
679675
});
680676

@@ -772,47 +768,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
772768
expect(ReactNoop.getChildren()).toEqual([span('C')]);
773769
});
774770

775-
it('can hide a tree to unblock its surroundings', async () => {
776-
function App() {
777-
return (
778-
<Suspense maxDuration={1000}>
779-
{didTimeout => (
780-
<Fragment>
781-
<div hidden={didTimeout}>
782-
<AsyncText text="Async" ms={3000} />
783-
</div>
784-
{didTimeout ? <Text text="Loading..." /> : null}
785-
</Fragment>
786-
)}
787-
</Suspense>
788-
);
789-
}
790-
791-
ReactNoop.render(<App />);
792-
expect(ReactNoop.flush()).toEqual(['Suspend! [Async]', 'Loading...']);
793-
expect(ReactNoop.getChildrenAsJSX()).toEqual(null);
794-
795-
ReactNoop.expire(2000);
796-
await advanceTimers(2000);
797-
expect(ReactNoop.flush()).toEqual([]);
798-
expect(ReactNoop.getChildrenAsJSX()).toEqual(
799-
<React.Fragment>
800-
<div hidden={true} />
801-
<span prop="Loading..." />
802-
</React.Fragment>,
803-
);
804-
805-
ReactNoop.expire(1000);
806-
await advanceTimers(1000);
807-
808-
expect(ReactNoop.flush()).toEqual(['Promise resolved [Async]', 'Async']);
809-
expect(ReactNoop.getChildrenAsJSX()).toEqual(
810-
<div>
811-
<span prop="Async" />
812-
</div>,
813-
);
814-
});
815-
816771
it('flushes all expired updates in a single batch', async () => {
817772
class Foo extends React.Component {
818773
componentDidUpdate() {
@@ -869,16 +824,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
869824
}
870825

871826
function Delay({ms}) {
827+
// Once ms has elapsed, render null. This allows the rest of the
828+
// tree to resume rendering.
872829
return (
873-
<Suspense maxDuration={ms}>
874-
{didTimeout => {
875-
if (didTimeout) {
876-
// Once ms has elapsed, render null. This allows the rest of the
877-
// tree to resume rendering.
878-
return null;
879-
}
880-
return <Never />;
881-
}}
830+
<Suspense fallback={null} maxDuration={ms}>
831+
<Never />
882832
</Suspense>
883833
);
884834
}

0 commit comments

Comments
 (0)