Enable Suspense + rename Placeholder (#13799)
* Enable Suspense * <unstable_Placeholder delayMs> => <unstable_Suspense maxDuration> * Update suspense fixture
Dan Abramov committed
Oct 10, 2018 at 17:02 UTC
8af6728c6f105d37f9c0006288a6d1ac3903dc71
30 files changed
+326
-362
fixtures/unstable-async/suspense/README.md
+2
-8
@@ -14,19 +14,13 @@ No. The APIs being tested here are unstable and some of them have still not been
14
15
Clone the React repository.
16
17
-First, open this file locally:
18
-
19
-* `packages/shared/ReactFeatureFlags.js` (make sure you didn't open a similarly named file!)
20
-
21
-Set [the `enableSuspense` flag](https://github.com/facebook/react/blob/d79238f1eeb6634ba7a3df23c3b2709b56cbb8b2/packages/shared/ReactFeatureFlags.js#L19) to `true` and save the file.
22
-
23
-**After you've done that,** follow these steps:
17
+Follow these steps:
18
19
```shell
20
# 1: Build react from source
21
cd /path/to/react
22
yarn
29
-yarn build dom-client,core,react-cache,schedule --type=NODE
23
+yarn build dom-client,core,react-cache,scheduler --type=NODE
24
25
# 2: Install fixture dependencies
26
cd fixtures/unstable-async/suspense/
fixtures/unstable-async/suspense/src/components/App.js
+5
-5
@@ -1,4 +1,4 @@
1
-import React, {Placeholder, PureComponent} from 'react';
1
+import React, {unstable_Suspense as Suspense, PureComponent} from 'react';
2
import {unstable_scheduleCallback} from 'scheduler';
3
import {
4
unstable_trace as trace,
@@ -76,21 +76,21 @@ export default class App extends PureComponent {
76
}}>
77
Return to list
78
</button>
79
- <Placeholder delayMs={2000} fallback={<Spinner size="large" />}>
79
+ <Suspense maxDuration={2000} fallback={<Spinner size="large" />}>
80
<UserPageLoader id={id} />
81
- </Placeholder>
81
+ </Suspense>
82
</div>
83
);
84
}
85
86
renderList(loadingId) {
87
return (
88
- <Placeholder delayMs={1500} fallback={<Spinner size="large" />}>
88
+ <Suspense maxDuration={1500} fallback={<Spinner size="large" />}>
89
<ContributorListPage
90
loadingId={loadingId}
91
onUserClick={this.handleUserClick}
92
/>
93
- </Placeholder>
93
+ </Suspense>
94
);
95
}
96
}
fixtures/unstable-async/suspense/src/components/UserPage.js
+5
-5
@@ -1,4 +1,4 @@
1
-import React, {Placeholder} from 'react';
1
+import React, {unstable_Suspense as Suspense} from 'react';
2
import {createResource} from 'react-cache';
3
import Spinner from './Spinner';
4
import {cache} from '../cache';
@@ -14,9 +14,9 @@ export default function UserPage({id}) {
14
alignItems: 'start',
15
}}>
16
<UserDetails id={id} />
17
- <Placeholder delayMs={1000} fallback={<Spinner size="medium" />}>
17
+ <Suspense maxDuration={1000} fallback={<Spinner size="medium" />}>
18
<Repositories id={id} />
19
- </Placeholder>
19
+ </Suspense>
20
</div>
21
);
22
}
@@ -118,7 +118,7 @@ function Img({src, alt, ...rest}) {
118
119
function UserPicture({source}) {
120
return (
121
- <Placeholder delayMs={1500} fallback={<img src={source} alt="poster" />}>
121
+ <Suspense maxDuration={1500} fallback={<img src={source} alt="poster" />}>
122
<Img
123
src={source}
124
alt="profile picture"
@@ -128,7 +128,7 @@ function UserPicture({source}) {
128
borderRadius: '0.5rem',
129
}}
130
/>
131
- </Placeholder>
131
+ </Suspense>
132
);
133
}
134
packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js
renamed
+3
-4
@@ -21,7 +21,6 @@ function initModules() {
21
jest.resetModuleRegistry();
22
23
ReactFeatureFlags = require('shared/ReactFeatureFlags');
24
- ReactFeatureFlags.enableSuspense = true;
24
ReactFeatureFlags.enableSuspenseServerRenderer = true;
25
26
React = require('react');
@@ -39,7 +38,7 @@ const {resetModules, serverRender} = ReactDOMServerIntegrationUtils(
38
initModules,
39
);
40
42
-describe('ReactDOMServerPlaceholders', () => {
41
+describe('ReactDOMServerSuspense', () => {
42
beforeEach(() => {
43
resetModules();
44
});
@@ -49,9 +48,9 @@ describe('ReactDOMServerPlaceholders', () => {
48
throw new Promise(() => {});
49
};
50
const e = await serverRender(
52
- <React.Placeholder fallback={<div />}>
51
+ <React.unstable_Suspense fallback={<div />}>
52
<Suspended />
54
- </React.Placeholder>,
53
+ </React.unstable_Suspense>,
54
);
55
56
expect(e.tagName).toBe('DIV');
packages/react-dom/src/server/ReactPartialRenderer.js
+2
-2
@@ -33,7 +33,7 @@ import {
33
REACT_FRAGMENT_TYPE,
34
REACT_STRICT_MODE_TYPE,
35
REACT_CONCURRENT_MODE_TYPE,
36
- REACT_PLACEHOLDER_TYPE,
36
+ REACT_SUSPENSE_TYPE,
37
REACT_PORTAL_TYPE,
38
REACT_PROFILER_TYPE,
39
REACT_PROVIDER_TYPE,
@@ -916,7 +916,7 @@ class ReactDOMServerRenderer {
916
this.stack.push(frame);
917
return '';
918
}
919
- case REACT_PLACEHOLDER_TYPE: {
919
+ case REACT_SUSPENSE_TYPE: {
920
if (enableSuspenseServerRenderer) {
921
const nextChildren = toArray(
922
// Always use the fallback when synchronously rendering to string.
packages/react-reconciler/src/ReactFiber.js
+4
-4
@@ -33,7 +33,7 @@ import {
33
ContextProvider,
34
ContextConsumer,
35
Profiler,
36
- PlaceholderComponent,
36
+ SuspenseComponent,
37
FunctionComponentLazy,
38
ClassComponentLazy,
39
ForwardRefLazy,
@@ -58,7 +58,7 @@ import {
58
REACT_PROVIDER_TYPE,
59
REACT_CONTEXT_TYPE,
60
REACT_CONCURRENT_MODE_TYPE,
61
- REACT_PLACEHOLDER_TYPE,
61
+ REACT_SUSPENSE_TYPE,
62
REACT_PURE_TYPE,
63
} from 'shared/ReactSymbols';
64
@@ -442,8 +442,8 @@ export function createFiberFromElement(
442
break;
443
case REACT_PROFILER_TYPE:
444
return createFiberFromProfiler(pendingProps, mode, expirationTime, key);
445
- case REACT_PLACEHOLDER_TYPE:
446
- fiberTag = PlaceholderComponent;
445
+ case REACT_SUSPENSE_TYPE:
446
+ fiberTag = SuspenseComponent;
447
break;
448
default: {
449
if (typeof type === 'object' && type !== null) {
packages/react-reconciler/src/ReactFiberBeginWork.js
+58
-64
@@ -30,7 +30,7 @@ import {
30
ContextProvider,
31
ContextConsumer,
32
Profiler,
33
- PlaceholderComponent,
33
+ SuspenseComponent,
34
PureComponent,
35
PureComponentLazy,
36
} from 'shared/ReactWorkTags';
@@ -45,7 +45,6 @@ import {
45
} from 'shared/ReactSideEffectTags';
46
import ReactSharedInternals from 'shared/ReactSharedInternals';
47
import {
48
- enableSuspense,
48
debugRenderPhaseSideEffects,
49
debugRenderPhaseSideEffectsForStrictMode,
50
enableProfilerTimer,
@@ -935,77 +934,72 @@ function mountIndeterminateComponent(
934
}
935
}
936
938
-function updatePlaceholderComponent(
937
+function updateSuspenseComponent(
938
current,
939
workInProgress,
940
renderExpirationTime,
941
) {
943
- if (enableSuspense) {
944
- const nextProps = workInProgress.pendingProps;
945
-
946
- // Check if we already attempted to render the normal state. If we did,
947
- // and we timed out, render the placeholder state.
948
- const alreadyCaptured =
949
- (workInProgress.effectTag & DidCapture) === NoEffect;
950
-
951
- let nextDidTimeout;
952
- if (current !== null && workInProgress.updateQueue !== null) {
953
- // We're outside strict mode. Something inside this Placeholder boundary
954
- // suspended during the last commit. Switch to the placholder.
955
- workInProgress.updateQueue = null;
956
- nextDidTimeout = true;
957
- } else {
958
- nextDidTimeout = !alreadyCaptured;
959
- }
942
+ const nextProps = workInProgress.pendingProps;
943
961
- if ((workInProgress.mode & StrictMode) !== NoEffect) {
962
- if (nextDidTimeout) {
963
- // If the timed-out view commits, schedule an update effect to record
964
- // the committed time.
965
- workInProgress.effectTag |= Update;
966
- } else {
967
- // The state node points to the time at which placeholder timed out.
968
- // We can clear it once we switch back to the normal children.
969
- workInProgress.stateNode = null;
970
- }
971
- }
944
+ // Check if we already attempted to render the normal state. If we did,
945
+ // and we timed out, render the placeholder state.
946
+ const alreadyCaptured = (workInProgress.effectTag & DidCapture) === NoEffect;
947
973
- // If the `children` prop is a function, treat it like a render prop.
974
- // TODO: This is temporary until we finalize a lower level API.
975
- const children = nextProps.children;
976
- let nextChildren;
977
- if (typeof children === 'function') {
978
- nextChildren = children(nextDidTimeout);
979
- } else {
980
- nextChildren = nextDidTimeout ? nextProps.fallback : children;
981
- }
948
+ let nextDidTimeout;
949
+ if (current !== null && workInProgress.updateQueue !== null) {
950
+ // We're outside strict mode. Something inside this Placeholder boundary
951
+ // suspended during the last commit. Switch to the placholder.
952
+ workInProgress.updateQueue = null;
953
+ nextDidTimeout = true;
954
+ } else {
955
+ nextDidTimeout = !alreadyCaptured;
956
+ }
957
983
- if (current !== null && nextDidTimeout !== workInProgress.memoizedState) {
984
- // We're about to switch from the placeholder children to the normal
985
- // children, or vice versa. These are two different conceptual sets that
986
- // happen to be stored in the same set. Call this special function to
987
- // force the new set not to match with the current set.
988
- // TODO: The proper way to model this is by storing each set separately.
989
- forceUnmountCurrentAndReconcile(
990
- current,
991
- workInProgress,
992
- nextChildren,
993
- renderExpirationTime,
994
- );
958
+ if ((workInProgress.mode & StrictMode) !== NoEffect) {
959
+ if (nextDidTimeout) {
960
+ // If the timed-out view commits, schedule an update effect to record
961
+ // the committed time.
962
+ workInProgress.effectTag |= Update;
963
} else {
996
- reconcileChildren(
997
- current,
998
- workInProgress,
999
- nextChildren,
1000
- renderExpirationTime,
1001
- );
964
+ // The state node points to the time at which placeholder timed out.
965
+ // We can clear it once we switch back to the normal children.
966
+ workInProgress.stateNode = null;
967
}
1003
- workInProgress.memoizedProps = nextProps;
1004
- workInProgress.memoizedState = nextDidTimeout;
1005
- return workInProgress.child;
968
+ }
969
+
970
+ // If the `children` prop is a function, treat it like a render prop.
971
+ // TODO: This is temporary until we finalize a lower level API.
972
+ const children = nextProps.children;
973
+ let nextChildren;
974
+ if (typeof children === 'function') {
975
+ nextChildren = children(nextDidTimeout);
976
} else {
1007
- return null;
977
+ nextChildren = nextDidTimeout ? nextProps.fallback : children;
978
+ }
979
+
980
+ if (current !== null && nextDidTimeout !== workInProgress.memoizedState) {
981
+ // We're about to switch from the placeholder children to the normal
982
+ // children, or vice versa. These are two different conceptual sets that
983
+ // happen to be stored in the same set. Call this special function to
984
+ // force the new set not to match with the current set.
985
+ // TODO: The proper way to model this is by storing each set separately.
986
+ forceUnmountCurrentAndReconcile(
987
+ current,
988
+ workInProgress,
989
+ nextChildren,
990
+ renderExpirationTime,
991
+ );
992
+ } else {
993
+ reconcileChildren(
994
+ current,
995
+ workInProgress,
996
+ nextChildren,
997
+ renderExpirationTime,
998
+ );
999
}
1000
+ workInProgress.memoizedProps = nextProps;
1001
+ workInProgress.memoizedState = nextDidTimeout;
1002
+ return workInProgress.child;
1003
}
1004
1005
function updatePortalComponent(
@@ -1342,8 +1336,8 @@ function beginWork(
1336
return updateHostComponent(current, workInProgress, renderExpirationTime);
1337
case HostText:
1338
return updateHostText(current, workInProgress);
1345
- case PlaceholderComponent:
1346
- return updatePlaceholderComponent(
1339
+ case SuspenseComponent:
1340
+ return updateSuspenseComponent(
1341
current,
1342
workInProgress,
1343
renderExpirationTime,
packages/react-reconciler/src/ReactFiberCommitWork.js
+16
-19
@@ -22,7 +22,6 @@ import type {CapturedValue, CapturedError} from './ReactCapturedValue';
22
import {
23
enableSchedulerTracing,
24
enableProfilerTimer,
25
- enableSuspense,
25
} from 'shared/ReactFeatureFlags';
26
import {
27
ClassComponent,
@@ -32,7 +31,7 @@ import {
31
HostText,
32
HostPortal,
33
Profiler,
35
- PlaceholderComponent,
34
+ SuspenseComponent,
35
} from 'shared/ReactWorkTags';
36
import {
37
invokeGuardedCallback,
@@ -352,22 +351,20 @@ function commitLifeCycles(
351
}
352
return;
353
}
355
- case PlaceholderComponent: {
356
- if (enableSuspense) {
357
- if ((finishedWork.mode & StrictMode) === NoEffect) {
358
- // In loose mode, a placeholder times out by scheduling a synchronous
359
- // update in the commit phase. Use `updateQueue` field to signal that
360
- // the Timeout needs to switch to the placeholder. We don't need an
361
- // entire queue. Any non-null value works.
362
- // $FlowFixMe - Intentionally using a value other than an UpdateQueue.
363
- finishedWork.updateQueue = emptyObject;
364
- scheduleWork(finishedWork, Sync);
365
- } else {
366
- // In strict mode, the Update effect is used to record the time at
367
- // which the placeholder timed out.
368
- const currentTime = requestCurrentTime();
369
- finishedWork.stateNode = {timedOutAt: currentTime};
370
- }
354
+ case SuspenseComponent: {
355
+ if ((finishedWork.mode & StrictMode) === NoEffect) {
356
+ // In loose mode, a placeholder times out by scheduling a synchronous
357
+ // update in the commit phase. Use `updateQueue` field to signal that
358
+ // the Timeout needs to switch to the placeholder. We don't need an
359
+ // entire queue. Any non-null value works.
360
+ // $FlowFixMe - Intentionally using a value other than an UpdateQueue.
361
+ finishedWork.updateQueue = emptyObject;
362
+ scheduleWork(finishedWork, Sync);
363
+ } else {
364
+ // In strict mode, the Update effect is used to record the time at
365
+ // which the placeholder timed out.
366
+ const currentTime = requestCurrentTime();
367
+ finishedWork.stateNode = {timedOutAt: currentTime};
368
}
369
return;
370
}
@@ -863,7 +860,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
860
case Profiler: {
861
return;
862
}
866
- case PlaceholderComponent: {
863
+ case SuspenseComponent: {
864
return;
865
}
866
default: {
packages/react-reconciler/src/ReactFiberCompleteWork.js
+2
-2
@@ -34,7 +34,7 @@ import {
34
Fragment,
35
Mode,
36
Profiler,
37
- PlaceholderComponent,
37
+ SuspenseComponent,
38
ForwardRefLazy,
39
PureComponent,
40
PureComponentLazy,
@@ -508,7 +508,7 @@ function completeWork(
508
case ForwardRef:
509
case ForwardRefLazy:
510
break;
511
- case PlaceholderComponent:
511
+ case SuspenseComponent:
512
break;
513
case Fragment:
514
break;
packages/react-reconciler/src/ReactFiberScheduler.js
+42
-47
@@ -49,7 +49,6 @@ import {
49
enableUserTimingAPI,
50
replayFailedUnitOfWorkWithInvokeGuardedCallback,
51
warnAboutDeprecatedLifecycles,
52
- enableSuspense,
52
} from 'shared/ReactFeatureFlags';
53
import getComponentName from 'shared/getComponentName';
54
import invariant from 'shared/invariant';
@@ -1374,7 +1373,7 @@ function renderRoot(
1373
}
1374
}
1375
1377
- if (enableSuspense && !isExpired && nextLatestAbsoluteTimeoutMs !== -1) {
1376
+ if (!isExpired && nextLatestAbsoluteTimeoutMs !== -1) {
1377
// The tree was suspended.
1378
const suspendedExpirationTime = expirationTime;
1379
markSuspendedPriorityLevel(root, suspendedExpirationTime);
@@ -1567,42 +1566,40 @@ function retrySuspendedRoot(
1566
fiber: Fiber,
1567
suspendedTime: ExpirationTime,
1568
) {
1570
- if (enableSuspense) {
1571
- let retryTime;
1569
+ let retryTime;
1570
1573
- if (isPriorityLevelSuspended(root, suspendedTime)) {
1574
- // Ping at the original level
1575
- retryTime = suspendedTime;
1571
+ if (isPriorityLevelSuspended(root, suspendedTime)) {
1572
+ // Ping at the original level
1573
+ retryTime = suspendedTime;
1574
1577
- markPingedPriorityLevel(root, retryTime);
1578
- } else {
1579
- // Placeholder already timed out. Compute a new expiration time
1580
- const currentTime = requestCurrentTime();
1581
- retryTime = computeExpirationForFiber(currentTime, fiber);
1582
- markPendingPriorityLevel(root, retryTime);
1583
- }
1584
-
1585
- // TODO: If the placeholder fiber has already rendered the primary children
1586
- // without suspending (that is, all of the promises have already resolved),
1587
- // we should not trigger another update here. One case this happens is when
1588
- // we are in sync mode and a single promise is thrown both on initial render
1589
- // and on update; we attach two .then(retrySuspendedRoot) callbacks and each
1590
- // one performs Sync work, rerendering the Placeholder.
1591
-
1592
- if ((fiber.mode & ConcurrentMode) !== NoContext) {
1593
- if (root === nextRoot && nextRenderExpirationTime === suspendedTime) {
1594
- // Received a ping at the same priority level at which we're currently
1595
- // rendering. Restart from the root.
1596
- nextRoot = null;
1597
- }
1598
- }
1575
+ markPingedPriorityLevel(root, retryTime);
1576
+ } else {
1577
+ // Suspense already timed out. Compute a new expiration time
1578
+ const currentTime = requestCurrentTime();
1579
+ retryTime = computeExpirationForFiber(currentTime, fiber);
1580
+ markPendingPriorityLevel(root, retryTime);
1581
+ }
1582
1600
- scheduleWorkToRoot(fiber, retryTime);
1601
- const rootExpirationTime = root.expirationTime;
1602
- if (rootExpirationTime !== NoWork) {
1603
- requestWork(root, rootExpirationTime);
1583
+ // TODO: If the placeholder fiber has already rendered the primary children
1584
+ // without suspending (that is, all of the promises have already resolved),
1585
+ // we should not trigger another update here. One case this happens is when
1586
+ // we are in sync mode and a single promise is thrown both on initial render
1587
+ // and on update; we attach two .then(retrySuspendedRoot) callbacks and each
1588
+ // one performs Sync work, rerendering the Suspense.
1589
+
1590
+ if ((fiber.mode & ConcurrentMode) !== NoContext) {
1591
+ if (root === nextRoot && nextRenderExpirationTime === suspendedTime) {
1592
+ // Received a ping at the same priority level at which we're currently
1593
+ // rendering. Restart from the root.
1594
+ nextRoot = null;
1595
}
1596
}
1597
+
1598
+ scheduleWorkToRoot(fiber, retryTime);
1599
+ const rootExpirationTime = root.expirationTime;
1600
+ if (rootExpirationTime !== NoWork) {
1601
+ requestWork(root, rootExpirationTime);
1602
+ }
1603
}
1604
1605
function scheduleWorkToRoot(fiber: Fiber, expirationTime): FiberRoot | null {
@@ -1877,7 +1874,7 @@ function onSuspend(
1874
msUntilTimeout: number,
1875
): void {
1876
root.expirationTime = rootExpirationTime;
1880
- if (enableSuspense && msUntilTimeout === 0 && !shouldYield()) {
1877
+ if (msUntilTimeout === 0 && !shouldYield()) {
1878
// Don't wait an additional tick. Commit the tree immediately.
1879
root.pendingCommitExpirationTime = suspendedExpirationTime;
1880
root.finishedWork = finishedWork;
@@ -1895,17 +1892,15 @@ function onYield(root) {
1892
}
1893
1894
function onTimeout(root, finishedWork, suspendedExpirationTime) {
1898
- if (enableSuspense) {
1899
- // The root timed out. Commit it.
1900
- root.pendingCommitExpirationTime = suspendedExpirationTime;
1901
- root.finishedWork = finishedWork;
1902
- // Read the current time before entering the commit phase. We can be
1903
- // certain this won't cause tearing related to batching of event updates
1904
- // because we're at the top of a timer event.
1905
- recomputeCurrentRendererTime();
1906
- currentSchedulerTime = currentRendererTime;
1907
- flushRoot(root, suspendedExpirationTime);
1908
- }
1895
+ // The root timed out. Commit it.
1896
+ root.pendingCommitExpirationTime = suspendedExpirationTime;
1897
+ root.finishedWork = finishedWork;
1898
+ // Read the current time before entering the commit phase. We can be
1899
+ // certain this won't cause tearing related to batching of event updates
1900
+ // because we're at the top of a timer event.
1901
+ recomputeCurrentRendererTime();
1902
+ currentSchedulerTime = currentRendererTime;
1903
+ flushRoot(root, suspendedExpirationTime);
1904
}
1905
1906
function onCommit(root, expirationTime) {
@@ -2247,7 +2242,7 @@ function performWorkOnRoot(
2242
// If this root previously suspended, clear its existing timeout, since
2243
// we're about to try rendering again.
2244
const timeoutHandle = root.timeoutHandle;
2250
- if (enableSuspense && timeoutHandle !== noTimeout) {
2245
+ if (timeoutHandle !== noTimeout) {
2246
root.timeoutHandle = noTimeout;
2247
// $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above
2248
cancelTimeout(timeoutHandle);
@@ -2271,7 +2266,7 @@ function performWorkOnRoot(
2266
// If this root previously suspended, clear its existing timeout, since
2267
// we're about to try rendering again.
2268
const timeoutHandle = root.timeoutHandle;
2274
- if (enableSuspense && timeoutHandle !== noTimeout) {
2269
+ if (timeoutHandle !== noTimeout) {
2270
root.timeoutHandle = noTimeout;
2271
// $FlowFixMe Complains noTimeout is not a TimeoutID, despite the check above
2272
cancelTimeout(timeoutHandle);
packages/react-reconciler/src/ReactFiberUnwindWork.js
+9
-10
@@ -26,7 +26,7 @@ import {
26
HostComponent,
27
HostPortal,
28
ContextProvider,
29
- PlaceholderComponent,
29
+ SuspenseComponent,
30
} from 'shared/ReactWorkTags';
31
import {
32
DidCapture,
@@ -36,7 +36,7 @@ import {
36
Update as UpdateEffect,
37
LifecycleEffectMask,
38
} from 'shared/ReactSideEffectTags';
39
-import {enableSuspense, enableSchedulerTracing} from 'shared/ReactFeatureFlags';
39
+import {enableSchedulerTracing} from 'shared/ReactFeatureFlags';
40
import {StrictMode, ConcurrentMode} from './ReactTypeOfMode';
41
42
import {createCapturedValue} from './ReactCapturedValue';
@@ -158,7 +158,6 @@ function throwException(
158
sourceFiber.firstEffect = sourceFiber.lastEffect = null;
159
160
if (
161
- enableSuspense &&
161
value !== null &&
162
typeof value === 'object' &&
163
typeof value.then === 'function'
@@ -175,7 +174,7 @@ function throwException(
174
let earliestTimeoutMs = -1;
175
let startTimeMs = -1;
176
do {
178
- if (workInProgress.tag === PlaceholderComponent) {
177
+ if (workInProgress.tag === SuspenseComponent) {
178
const current = workInProgress.alternate;
179
if (
180
current !== null &&
@@ -193,7 +192,7 @@ function throwException(
192
// Do not search any further.
193
break;
194
}
196
- let timeoutPropMs = workInProgress.pendingProps.delayMs;
195
+ let timeoutPropMs = workInProgress.pendingProps.maxDuration;
196
if (typeof timeoutPropMs === 'number') {
197
if (timeoutPropMs <= 0) {
198
earliestTimeoutMs = 0;
@@ -208,10 +207,10 @@ function throwException(
207
workInProgress = workInProgress.return;
208
} while (workInProgress !== null);
209
211
- // Schedule the nearest Placeholder to re-render the timed out view.
210
+ // Schedule the nearest Suspense to re-render the timed out view.
211
workInProgress = returnFiber;
212
do {
214
- if (workInProgress.tag === PlaceholderComponent) {
213
+ if (workInProgress.tag === SuspenseComponent) {
214
const didTimeout = workInProgress.memoizedState;
215
if (!didTimeout) {
216
// Found the nearest boundary.
@@ -238,10 +237,10 @@ function throwException(
237
// If the boundary is outside of strict mode, we should *not* suspend
238
// the commit. Pretend as if the suspended component rendered null and
239
// keep rendering. In the commit phase, we'll schedule a subsequent
241
- // synchronous update to re-render the Placeholder.
240
+ // synchronous update to re-render the Suspense.
241
//
242
// Note: It doesn't matter whether the component that suspended was
244
- // inside a strict mode tree. If the Placeholder is outside of it, we
243
+ // inside a strict mode tree. If the Suspense is outside of it, we
244
// should *not* suspend the commit.
245
if ((workInProgress.mode & StrictMode) === NoEffect) {
246
workInProgress.effectTag |= UpdateEffect;
@@ -434,7 +433,7 @@ function unwindWork(
433
popHostContext(workInProgress);
434
return null;
435
}
437
- case PlaceholderComponent: {
436
+ case SuspenseComponent: {
437
const effectTag = workInProgress.effectTag;
438
if (effectTag & ShouldCapture) {
439
workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture;
packages/react-reconciler/src/__tests__/ReactPure-test.internal.js
+17
-18
@@ -21,7 +21,6 @@ describe('pure', () => {
21
jest.resetModules();
22
ReactFeatureFlags = require('shared/ReactFeatureFlags');
23
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
24
- ReactFeatureFlags.enableSuspense = true;
24
React = require('react');
25
ReactNoop = require('react-noop-renderer');
26
});
@@ -50,7 +49,7 @@ describe('pure', () => {
49
function sharedTests(label, pure) {
50
describe(`${label}`, () => {
51
it('bails out on props equality', async () => {
53
- const {Placeholder} = React;
52
+ const {unstable_Suspense: Suspense} = React;
53
54
function Counter({count}) {
55
return <Text text={count} />;
@@ -58,9 +57,9 @@ describe('pure', () => {
57
Counter = pure(Counter);
58
59
ReactNoop.render(
61
- <Placeholder>
60
+ <Suspense>
61
<Counter count={0} />
63
- </Placeholder>,
62
+ </Suspense>,
63
);
64
expect(ReactNoop.flush()).toEqual([]);
65
await Promise.resolve();
@@ -69,18 +68,18 @@ describe('pure', () => {
68
69
// Should bail out because props have not changed
70
ReactNoop.render(
72
- <Placeholder>
71
+ <Suspense>
72
<Counter count={0} />
74
- </Placeholder>,
73
+ </Suspense>,
74
);
75
expect(ReactNoop.flush()).toEqual([]);
76
expect(ReactNoop.getChildren()).toEqual([span(0)]);
77
78
// Should update because count prop changed
79
ReactNoop.render(
81
- <Placeholder>
80
+ <Suspense>
81
<Counter count={1} />
83
- </Placeholder>,
82
+ </Suspense>,
83
);
84
expect(ReactNoop.flush()).toEqual([1]);
85
expect(ReactNoop.getChildren()).toEqual([span(1)]);
@@ -88,7 +87,7 @@ describe('pure', () => {
87
});
88
89
it("does not bail out if there's a context change", async () => {
91
- const {Placeholder} = React;
90
+ const {unstable_Suspense: Suspense} = React;
91
92
const CountContext = React.createContext(0);
93
@@ -102,11 +101,11 @@ describe('pure', () => {
101
state = {count: 0};
102
render() {
103
return (
105
- <Placeholder>
104
+ <Suspense>
105
<CountContext.Provider value={this.state.count}>
106
<Counter label="Count" />
107
</CountContext.Provider>
109
- </Placeholder>
108
+ </Suspense>
109
);
110
}
111
}
@@ -130,7 +129,7 @@ describe('pure', () => {
129
});
130
131
it('accepts custom comparison function', async () => {
133
- const {Placeholder} = React;
132
+ const {unstable_Suspense: Suspense} = React;
133
134
function Counter({count}) {
135
return <Text text={count} />;
@@ -143,9 +142,9 @@ describe('pure', () => {
142
});
143
144
ReactNoop.render(
146
- <Placeholder>
145
+ <Suspense>
146
<Counter count={0} />
148
- </Placeholder>,
147
+ </Suspense>,
148
);
149
expect(ReactNoop.flush()).toEqual([]);
150
await Promise.resolve();
@@ -154,18 +153,18 @@ describe('pure', () => {
153
154
// Should bail out because props have not changed
155
ReactNoop.render(
157
- <Placeholder>
156
+ <Suspense>
157
<Counter count={0} />
159
- </Placeholder>,
158
+ </Suspense>,
159
);
160
expect(ReactNoop.flush()).toEqual(['Old count: 0, New count: 0']);
161
expect(ReactNoop.getChildren()).toEqual([span(0)]);
162
163
// Should update because count prop changed
164
ReactNoop.render(
166
- <Placeholder>
165
+ <Suspense>
166
<Counter count={1} />
168
- </Placeholder>,
167
+ </Suspense>,
168
);
169
expect(ReactNoop.flush()).toEqual(['Old count: 0, New count: 1', 1]);
170
expect(ReactNoop.getChildren()).toEqual([span(1)]);
packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js
+14
-15
@@ -2,7 +2,7 @@ let React;
2
let ReactTestRenderer;
3
let ReactFeatureFlags;
4
let ReactCache;
5
-let Placeholder;
5
+let Suspense;
6
7
// let JestReact;
8
@@ -18,13 +18,12 @@ describe('ReactSuspense', () => {
18
ReactFeatureFlags = require('shared/ReactFeatureFlags');
19
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
20
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
21
- ReactFeatureFlags.enableSuspense = true;
21
React = require('react');
22
ReactTestRenderer = require('react-test-renderer');
23
// JestReact = require('jest-react');
24
ReactCache = require('react-cache');
25
27
- Placeholder = React.Placeholder;
26
+ Suspense = React.unstable_Suspense;
27
28
function invalidateCache() {
29
cache = ReactCache.createCache(invalidateCache);
@@ -107,12 +106,12 @@ describe('ReactSuspense', () => {
106
function Foo() {
107
ReactTestRenderer.unstable_yield('Foo');
108
return (
110
- <Placeholder>
109
+ <Suspense>
110
<Bar>
111
<AsyncText text="A" ms={100} />
112
<Text text="B" />
113
</Bar>
115
- </Placeholder>
114
+ </Suspense>
115
);
116
}
117
@@ -145,15 +144,15 @@ describe('ReactSuspense', () => {
144
});
145
146
it('suspends siblings and later recovers each independently', () => {
148
- // Render two sibling Placeholder components
147
+ // Render two sibling Suspense components
148
const root = ReactTestRenderer.create(
149
<React.Fragment>
151
- <Placeholder delayMs={1000} fallback={<Text text="Loading A..." />}>
150
+ <Suspense maxDuration={1000} fallback={<Text text="Loading A..." />}>
151
<AsyncText text="A" ms={5000} />
153
- </Placeholder>
154
- <Placeholder delayMs={3000} fallback={<Text text="Loading B..." />}>
152
+ </Suspense>
153
+ <Suspense maxDuration={3000} fallback={<Text text="Loading B..." />}>
154
<AsyncText text="B" ms={6000} />
156
- </Placeholder>
155
+ </Suspense>
156
</React.Fragment>,
157
{
158
unstable_isConcurrent: true,
@@ -173,8 +172,8 @@ describe('ReactSuspense', () => {
172
expect(root).toFlushWithoutYielding();
173
expect(root).toMatchRenderedOutput('Loading A...Loading B...');
174
176
- // Advance time by enough that the first Placeholder's promise resolves and
177
- // switches back to the normal view. The second Placeholder should still
175
+ // Advance time by enough that the first Suspense's promise resolves and
176
+ // switches back to the normal view. The second Suspense should still
177
// show the placeholder
178
jest.advanceTimersByTime(1000);
179
// TODO: Should we throw if you forget to call toHaveYielded?
@@ -182,7 +181,7 @@ describe('ReactSuspense', () => {
181
expect(root).toFlushAndYield(['A']);
182
expect(root).toMatchRenderedOutput('ALoading B...');
183
185
- // Advance time by enough that the second Placeholder's promise resolves
184
+ // Advance time by enough that the second Suspense's promise resolves
185
// and switches back to the normal view
186
jest.advanceTimersByTime(1000);
187
expect(ReactTestRenderer).toHaveYielded(['Promise resolved [B]']);
@@ -219,10 +218,10 @@ describe('ReactSuspense', () => {
218
}
219
220
const root = ReactTestRenderer.create(
222
- <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
221
+ <Suspense maxDuration={1000} fallback={<Text text="Loading..." />}>
222
<Async />
223
<Text text="Sibling" />
225
- </Placeholder>,
224
+ </Suspense>,
225
{
226
unstable_isConcurrent: true,
227
},
packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js
+106
-101
@@ -3,7 +3,7 @@ let ReactFeatureFlags;
3
let Fragment;
4
let ReactNoop;
5
let ReactCache;
6
-let Placeholder;
6
+let Suspense;
7
let StrictMode;
8
let ConcurrentMode;
9
let lazy;
@@ -21,12 +21,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
21
ReactFeatureFlags = require('shared/ReactFeatureFlags');
22
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
23
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
24
- ReactFeatureFlags.enableSuspense = true;
24
React = require('react');
25
Fragment = React.Fragment;
26
ReactNoop = require('react-noop-renderer');
27
ReactCache = require('react-cache');
29
- Placeholder = React.Placeholder;
28
+ Suspense = React.unstable_Suspense;
29
StrictMode = React.StrictMode;
30
ConcurrentMode = React.unstable_ConcurrentMode;
31
lazy = React.lazy;
@@ -103,12 +102,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
102
function Foo() {
103
ReactNoop.yield('Foo');
104
return (
106
- <Placeholder>
105
+ <Suspense>
106
<Bar>
107
<AsyncText text="A" ms={100} />
108
<Text text="B" />
109
</Bar>
111
- </Placeholder>
110
+ </Suspense>
111
);
112
}
113
@@ -143,15 +142,15 @@ describe('ReactSuspenseWithNoopRenderer', () => {
142
});
143
144
it('suspends siblings and later recovers each independently', async () => {
146
- // Render two sibling Placeholder components
145
+ // Render two sibling Suspense components
146
ReactNoop.render(
147
<Fragment>
149
- <Placeholder delayMs={1000} fallback={<Text text="Loading A..." />}>
148
+ <Suspense maxDuration={1000} fallback={<Text text="Loading A..." />}>
149
<AsyncText text="A" ms={5000} />
151
- </Placeholder>
152
- <Placeholder delayMs={3000} fallback={<Text text="Loading B..." />}>
150
+ </Suspense>
151
+ <Suspense maxDuration={3000} fallback={<Text text="Loading B..." />}>
152
<AsyncText text="B" ms={6000} />
154
- </Placeholder>
153
+ </Suspense>
154
</Fragment>,
155
);
156
expect(ReactNoop.flush()).toEqual([
@@ -172,8 +171,8 @@ describe('ReactSuspenseWithNoopRenderer', () => {
171
span('Loading B...'),
172
]);
173
175
- // Advance time by enough that the first Placeholder's promise resolves and
176
- // switches back to the normal view. The second Placeholder should still
174
+ // Advance time by enough that the first Suspense's promise resolves and
175
+ // switches back to the normal view. The second Suspense should still
176
// show the placeholder
177
ReactNoop.expire(1000);
178
await advanceTimers(1000);
@@ -181,7 +180,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
180
expect(ReactNoop.flush()).toEqual(['Promise resolved [A]', 'A']);
181
expect(ReactNoop.getChildren()).toEqual([span('A'), span('Loading B...')]);
182
184
- // Advance time by enough that the second Placeholder's promise resolves
183
+ // Advance time by enough that the second Suspense's promise resolves
184
// and switches back to the normal view
185
ReactNoop.expire(1000);
186
await advanceTimers(1000);
@@ -192,12 +191,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
191
192
it('continues rendering siblings after suspending', async () => {
193
ReactNoop.render(
195
- <Placeholder>
194
+ <Suspense>
195
<Text text="A" />
196
<AsyncText text="B" />
197
<Text text="C" />
198
<Text text="D" />
200
- </Placeholder>,
199
+ </Suspense>,
200
);
201
// B suspends. Continue rendering the remaining siblings.
202
expect(ReactNoop.flush()).toEqual(['A', 'Suspend! [B]', 'C', 'D']);
@@ -242,11 +241,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
241
const errorBoundary = React.createRef();
242
function App() {
243
return (
245
- <Placeholder>
244
+ <Suspense>
245
<ErrorBoundary ref={errorBoundary}>
246
<AsyncText text="Result" ms={1000} />
247
</ErrorBoundary>
249
- </Placeholder>
248
+ </Suspense>
249
);
250
}
251
@@ -304,11 +303,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
303
const errorBoundary = React.createRef();
304
function App() {
305
return (
307
- <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
306
+ <Suspense maxDuration={1000} fallback={<Text text="Loading..." />}>
307
<ErrorBoundary ref={errorBoundary}>
308
<AsyncText text="Result" ms={3000} />
309
</ErrorBoundary>
311
- </Placeholder>
310
+ </Suspense>
311
);
312
}
313
@@ -355,10 +354,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
354
it('can update at a higher priority while in a suspended state', async () => {
355
function App(props) {
356
return (
358
- <Placeholder>
357
+ <Suspense>
358
<Text text={props.highPri} />
359
<AsyncText text={props.lowPri} />
361
- </Placeholder>
360
+ </Suspense>
361
);
362
}
363
@@ -394,10 +393,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
393
it('keeps working on lower priority work after being pinged', async () => {
394
function App(props) {
395
return (
397
- <Placeholder>
396
+ <Suspense>
397
<AsyncText text="A" />
398
{props.showB && <Text text="B" />}
400
- </Placeholder>
399
+ </Suspense>
400
);
401
}
402
@@ -422,9 +421,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
421
return <Text text="(empty)" />;
422
}
423
return (
425
- <Placeholder>
424
+ <Suspense>
425
<AsyncText ms={2000} text="Async" />
427
- </Placeholder>
426
+ </Suspense>
427
);
428
}
429
@@ -449,9 +448,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
448
it('forces an expiration after an update times out', async () => {
449
ReactNoop.render(
450
<Fragment>
452
- <Placeholder fallback={<Text text="Loading..." />}>
451
+ <Suspense fallback={<Text text="Loading..." />}>
452
<AsyncText text="Async" ms={20000} />
454
- </Placeholder>
453
+ </Suspense>
454
<Text text="Sync" />
455
</Fragment>,
456
);
@@ -487,14 +486,16 @@ describe('ReactSuspenseWithNoopRenderer', () => {
486
ReactNoop.render(
487
<Fragment>
488
<Text text="Sync" />
490
- <Placeholder delayMs={1000} fallback={<Text text="Loading outer..." />}>
489
+ <Suspense
490
+ maxDuration={1000}
491
+ fallback={<Text text="Loading outer..." />}>
492
<AsyncText text="Outer content" ms={2000} />
492
- <Placeholder
493
- delayMs={2500}
493
+ <Suspense
494
+ maxDuration={2500}
495
fallback={<Text text="Loading inner..." />}>
496
<AsyncText text="Inner content" ms={5000} />
496
- </Placeholder>
497
- </Placeholder>
497
+ </Suspense>
498
+ </Suspense>
499
</Fragment>,
500
);
501
@@ -568,9 +569,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
569
ReactNoop.flushSync(() =>
570
ReactNoop.render(
571
<Fragment>
571
- <Placeholder fallback={<Text text="Loading..." />}>
572
+ <Suspense fallback={<Text text="Loading..." />}>
573
<AsyncText text="Async" />
573
- </Placeholder>
574
+ </Suspense>
575
<Text text="Sync" />
576
</Fragment>,
577
),
@@ -596,12 +597,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
597
ReactNoop.flushSync(() =>
598
ReactNoop.render(
599
<Fragment>
599
- <Placeholder fallback={<Text text="Loading (outer)..." />}>
600
- <Placeholder fallback={<AsyncText text="Loading (inner)..." />}>
600
+ <Suspense fallback={<Text text="Loading (outer)..." />}>
601
+ <Suspense fallback={<AsyncText text="Loading (inner)..." />}>
602
<AsyncText text="Async" />
602
- </Placeholder>
603
+ </Suspense>
604
<Text text="Sync" />
604
- </Placeholder>
605
+ </Suspense>
606
</Fragment>,
607
),
608
);
@@ -615,12 +616,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
616
expect(ReactNoop.getChildren()).toEqual([span('Loading (outer)...')]);
617
});
618
618
- it('expires early with a `delayMs` option', async () => {
619
+ it('expires early with a `maxDuration` option', async () => {
620
ReactNoop.render(
621
<Fragment>
621
- <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
622
+ <Suspense maxDuration={1000} fallback={<Text text="Loading..." />}>
623
<AsyncText text="Async" ms={3000} />
623
- </Placeholder>
624
+ </Suspense>
625
<Text text="Sync" />
626
</Fragment>,
627
);
@@ -651,9 +652,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
652
653
it('resolves successfully even if fallback render is pending', async () => {
654
ReactNoop.render(
654
- <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
655
+ <Suspense maxDuration={1000} fallback={<Text text="Loading..." />}>
656
<AsyncText text="Async" ms={3000} />
656
- </Placeholder>,
657
+ </Suspense>,
658
);
659
expect(ReactNoop.flushNextYield()).toEqual(['Suspend! [Async]']);
660
await advanceTimers(1500);
@@ -669,18 +670,18 @@ describe('ReactSuspenseWithNoopRenderer', () => {
670
expect(() => {
671
ReactNoop.flushSync(() =>
672
ReactNoop.render(
672
- <Placeholder>{() => <AsyncText text="Async" />}</Placeholder>,
673
+ <Suspense>{() => <AsyncText text="Async" />}</Suspense>,
674
),
675
);
676
}).toThrow('An update was suspended, but no placeholder UI was provided.');
677
});
678
678
- it('a Placeholder component correctly handles more than one suspended child', async () => {
679
+ it('a Suspense component correctly handles more than one suspended child', async () => {
680
ReactNoop.render(
680
- <Placeholder delayMs={0}>
681
+ <Suspense maxDuration={0}>
682
<AsyncText text="A" ms={100} />
683
<AsyncText text="B" ms={100} />
683
- </Placeholder>,
684
+ </Suspense>,
685
);
686
expect(ReactNoop.expire(10000)).toEqual(['Suspend! [A]', 'Suspend! [B]']);
687
expect(ReactNoop.getChildren()).toEqual([]);
@@ -698,9 +699,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
699
700
it('can resume rendering earlier than a timeout', async () => {
701
ReactNoop.render(
701
- <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
702
+ <Suspense maxDuration={1000} fallback={<Text text="Loading..." />}>
703
<AsyncText text="Async" ms={100} />
703
- </Placeholder>,
704
+ </Suspense>,
705
);
706
expect(ReactNoop.flush()).toEqual(['Suspend! [Async]', 'Loading...']);
707
expect(ReactNoop.getChildren()).toEqual([]);
@@ -723,13 +724,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
724
it('starts working on an update even if its priority falls between two suspended levels', async () => {
725
function App(props) {
726
return (
726
- <Placeholder delayMs={10000}>
727
+ <Suspense maxDuration={10000}>
728
{props.text === 'C' ? (
729
<Text text="C" />
730
) : (
731
<AsyncText text={props.text} ms={10000} />
732
)}
732
- </Placeholder>
733
+ </Suspense>
734
);
735
}
736
@@ -772,7 +773,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
773
it('can hide a tree to unblock its surroundings', async () => {
774
function App() {
775
return (
775
- <Placeholder delayMs={1000}>
776
+ <Suspense maxDuration={1000}>
777
{didTimeout => (
778
<Fragment>
779
<div hidden={didTimeout}>
@@ -781,7 +782,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
782
{didTimeout ? <Text text="Loading..." /> : null}
783
</Fragment>
784
)}
784
- </Placeholder>
785
+ </Suspense>
786
);
787
}
788
@@ -811,9 +812,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
812
}
813
render() {
814
return (
814
- <Placeholder fallback={<Text text="Loading..." />}>
815
+ <Suspense fallback={<Text text="Loading..." />}>
816
<AsyncText ms={20000} text={this.props.text} />
816
- </Placeholder>
817
+ </Suspense>
818
);
819
}
820
}
@@ -852,13 +853,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
853
function Never() {
854
// Throws a promise that resolves after some arbitrarily large
855
// number of seconds. The idea is that this component will never
855
- // resolve. It's always wrapped by a Placeholder.
856
+ // resolve. It's always wrapped by a Suspense.
857
throw new Promise(resolve => setTimeout(() => resolve(), 10000));
858
}
859
860
function Delay({ms}) {
861
return (
861
- <Placeholder delayMs={ms}>
862
+ <Suspense maxDuration={ms}>
863
{didTimeout => {
864
if (didTimeout) {
865
// Once ms has elapsed, render null. This allows the rest of the
@@ -867,7 +868,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
868
}
869
return <Never />;
870
}}
870
- </Placeholder>
871
+ </Suspense>
872
);
873
}
874
@@ -901,9 +902,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
902
it('times out immediately', async () => {
903
function App() {
904
return (
904
- <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
905
+ <Suspense maxDuration={1000} fallback={<Text text="Loading..." />}>
906
<AsyncText ms={100} text="Result" />
906
- </Placeholder>
907
+ </Suspense>
908
);
909
}
910
@@ -924,7 +925,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
925
expect(ReactNoop.getChildren()).toEqual([span('Result')]);
926
});
927
927
- it('times out immediately when Placeholder is in loose mode, even if the suspender is async', async () => {
928
+ it('times out immediately when Suspense is in loose mode, even if the suspender is async', async () => {
929
class UpdatingText extends React.Component {
930
state = {step: 1};
931
render() {
@@ -945,12 +946,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
946
const text = React.createRef(null);
947
function App() {
948
return (
948
- <Placeholder delayMs={1000} fallback={<Spinner />}>
949
+ <Suspense maxDuration={1000} fallback={<Spinner />}>
950
<ConcurrentMode>
951
<UpdatingText ref={text} />
952
<Text text="Sibling" />
953
</ConcurrentMode>
953
- </Placeholder>
954
+ </Suspense>
955
);
956
}
957
@@ -1022,7 +1023,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1023
function App() {
1024
return (
1025
<StrictMode>
1025
- <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
1026
+ <Suspense
1027
+ maxDuration={1000}
1028
+ fallback={<Text text="Loading..." />}>
1029
<ConcurrentMode>
1030
<UpdatingText ref={text1} initialText="Async: 1">
1031
{text => (
@@ -1034,7 +1037,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1037
)}
1038
</UpdatingText>
1039
</ConcurrentMode>
1037
- </Placeholder>
1040
+ </Suspense>
1041
<ConcurrentMode>
1042
<UpdatingText ref={text2} initialText="Sync: 1">
1043
{text => (
@@ -1154,7 +1157,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1157
function App() {
1158
return (
1159
<Fragment>
1157
- <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
1160
+ <Suspense
1161
+ maxDuration={1000}
1162
+ fallback={<Text text="Loading..." />}>
1163
<ConcurrentMode>
1164
<UpdatingText ref={text1} initialText="Async: 1">
1165
{text => (
@@ -1166,7 +1171,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1171
)}
1172
</UpdatingText>
1173
</ConcurrentMode>
1169
- </Placeholder>
1174
+ </Suspense>
1175
<ConcurrentMode>
1176
<UpdatingText ref={text2} initialText="Sync: 1">
1177
{text => (
@@ -1298,13 +1303,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1303
1304
function App() {
1305
return (
1301
- <Placeholder
1302
- delayMs={1000}
1306
+ <Suspense
1307
+ maxDuration={1000}
1308
fallback={<TextWithLifecycle text="Loading..." />}>
1309
<TextWithLifecycle text="A" />
1310
<AsyncTextWithLifecycle ms={100} text="B" />
1311
<TextWithLifecycle text="C" />
1307
- </Placeholder>
1312
+ </Suspense>
1313
);
1314
}
1315
@@ -1371,9 +1376,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1376
}
1377
1378
ReactNoop.renderLegacySyncRoot(
1374
- <Placeholder fallback={<Text text="Loading..." />}>
1379
+ <Suspense fallback={<Text text="Loading..." />}>
1380
<AsyncTextInConstructor ms={100} text="Hi" />
1376
- </Placeholder>,
1381
+ </Suspense>,
1382
);
1383
1384
expect(ReactNoop.getChildren()).toEqual([span('Loading...')]);
@@ -1397,9 +1402,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1402
class Demo extends React.Component {
1403
render() {
1404
return (
1400
- <Placeholder fallback={<Fallback />}>
1405
+ <Suspense fallback={<Fallback />}>
1406
<AsyncText text="Hi" ms={100} />
1402
- </Placeholder>
1407
+ </Suspense>
1408
);
1409
}
1410
}
@@ -1416,9 +1421,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1421
const LazyText = Promise.resolve(Text);
1422
1423
ReactNoop.render(
1419
- <Placeholder fallback={<Text text="Loading..." />}>
1424
+ <Suspense fallback={<Text text="Loading..." />}>
1425
<LazyText text="Hi" />
1421
- </Placeholder>,
1426
+ </Suspense>,
1427
);
1428
expect(ReactNoop.flush()).toEqual(['Loading...']);
1429
expect(ReactNoop.getChildren()).toEqual([]);
@@ -1430,9 +1435,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1435
1436
// Should not suspend on update
1437
ReactNoop.render(
1433
- <Placeholder fallback={<Text text="Loading..." />}>
1438
+ <Suspense fallback={<Text text="Loading..." />}>
1439
<LazyText text="Hi again" />
1435
- </Placeholder>,
1440
+ </Suspense>,
1441
);
1442
expect(ReactNoop.flush()).toEqual(['Hi again']);
1443
expect(ReactNoop.getChildren()).toEqual([span('Hi again')]);
@@ -1442,9 +1447,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1447
const LazyText = Promise.reject(new Error('Bad network'));
1448
1449
ReactNoop.render(
1445
- <Placeholder fallback={<Text text="Loading..." />}>
1450
+ <Suspense fallback={<Text text="Loading..." />}>
1451
<LazyText text="Hi" />
1447
- </Placeholder>,
1452
+ </Suspense>,
1453
);
1454
expect(ReactNoop.flush()).toEqual(['Loading...']);
1455
@@ -1471,7 +1476,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1476
1477
function Parent({swap}) {
1478
return (
1474
- <Placeholder fallback={<Text text="Loading..." />}>
1479
+ <Suspense fallback={<Text text="Loading..." />}>
1480
{swap
1481
? [
1482
<LazyChildB key="B" label="B" />,
@@ -1481,7 +1486,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1486
<LazyChildA key="A" label="A" />,
1487
<LazyChildB key="B" label="B" />,
1488
]}
1484
- </Placeholder>
1489
+ </Suspense>
1490
);
1491
}
1492
@@ -1515,9 +1520,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1520
const LazyText = Promise.resolve({default: Text});
1521
1522
ReactNoop.render(
1518
- <Placeholder fallback={<Text text="Loading..." />}>
1523
+ <Suspense fallback={<Text text="Loading..." />}>
1524
<LazyText text="Hi" />
1520
- </Placeholder>,
1525
+ </Suspense>,
1526
);
1527
expect(ReactNoop.flush()).toEqual(['Loading...']);
1528
expect(ReactNoop.getChildren()).toEqual([]);
@@ -1529,9 +1534,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1534
1535
// Should not suspend on update
1536
ReactNoop.render(
1532
- <Placeholder fallback={<Text text="Loading..." />}>
1537
+ <Suspense fallback={<Text text="Loading..." />}>
1538
<LazyText text="Hi again" />
1534
- </Placeholder>,
1539
+ </Suspense>,
1540
);
1541
expect(ReactNoop.flush()).toEqual(['Hi again']);
1542
expect(ReactNoop.getChildren()).toEqual([span('Hi again')]);
@@ -1545,9 +1550,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1550
const LazyText = Promise.resolve(T);
1551
1552
ReactNoop.render(
1548
- <Placeholder fallback={<Text text="Loading..." />}>
1553
+ <Suspense fallback={<Text text="Loading..." />}>
1554
<LazyText />
1550
- </Placeholder>,
1555
+ </Suspense>,
1556
);
1557
expect(ReactNoop.flush()).toEqual(['Loading...']);
1558
expect(ReactNoop.getChildren()).toEqual([]);
@@ -1560,9 +1565,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1565
T.defaultProps = {text: 'Hi again'};
1566
1567
ReactNoop.render(
1563
- <Placeholder fallback={<Text text="Loading..." />}>
1568
+ <Suspense fallback={<Text text="Loading..." />}>
1569
<LazyText text="Hi again" />
1565
- </Placeholder>,
1570
+ </Suspense>,
1571
);
1572
expect(ReactNoop.flush()).toEqual(['Hi again']);
1573
expect(ReactNoop.getChildren()).toEqual([span('Hi again')]);
@@ -1590,11 +1595,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1595
1596
const stateful = React.createRef(null);
1597
ReactNoop.render(
1593
- <Placeholder fallback={<Text text="Loading..." />}>
1598
+ <Suspense fallback={<Text text="Loading..." />}>
1599
<Lazy>
1600
<Stateful ref={stateful} />
1601
</Lazy>
1597
- </Placeholder>,
1602
+ </Suspense>,
1603
);
1604
expect(ReactNoop.flush()).toEqual(['Loading...']);
1605
expect(ReactNoop.getChildren()).toEqual([]);
@@ -1615,11 +1620,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1620
});
1621
1622
ReactNoop.render(
1618
- <Placeholder fallback={<Text text="Loading..." />}>
1623
+ <Suspense fallback={<Text text="Loading..." />}>
1624
<Text text="A" />
1625
<Text text="B" />
1626
<LazyText text="C" />
1622
- </Placeholder>,
1627
+ </Suspense>,
1628
);
1629
// Render first two siblings. The lazy component should not have
1630
// started loading yet.
@@ -1649,9 +1654,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1654
});
1655
1656
ReactNoop.render(
1652
- <Placeholder fallback={<Text text="Loading..." />}>
1657
+ <Suspense fallback={<Text text="Loading..." />}>
1658
<LazyFoo />
1654
- </Placeholder>,
1659
+ </Suspense>,
1660
);
1661
expect(ReactNoop.flush()).toEqual(['Started loading', 'Loading...']);
1662
expect(ReactNoop.getChildren()).toEqual([]);
@@ -1682,10 +1687,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1687
1688
const ref = React.createRef();
1689
ReactNoop.render(
1685
- <Placeholder fallback={<Text text="Loading..." />}>
1690
+ <Suspense fallback={<Text text="Loading..." />}>
1691
<LazyClass />
1692
<LazyForwardRef ref={ref} />
1688
- </Placeholder>,
1693
+ </Suspense>,
1694
);
1695
expect(ReactNoop.flush()).toEqual(['Loading...']);
1696
expect(ReactNoop.getChildren()).toEqual([]);
@@ -1745,13 +1750,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1750
1751
function App() {
1752
return (
1748
- <Placeholder
1749
- delayMs={1000}
1753
+ <Suspense
1754
+ maxDuration={1000}
1755
fallback={<TextWithLifecycle text="Loading..." />}>
1756
<TextWithLifecycle text="A" />
1757
<AsyncTextWithLifecycle ms={100} text="B" />
1758
<TextWithLifecycle text="C" />
1754
- </Placeholder>
1759
+ </Suspense>
1760
);
1761
}
1762
packages/react/src/React.js
+3
-7
@@ -11,9 +11,8 @@ import {
11
REACT_FRAGMENT_TYPE,
12
REACT_PROFILER_TYPE,
13
REACT_STRICT_MODE_TYPE,
14
- REACT_PLACEHOLDER_TYPE,
14
+ REACT_SUSPENSE_TYPE,
15
} from 'shared/ReactSymbols';
16
-import {enableSuspense} from 'shared/ReactFeatureFlags';
16
17
import {Component, PureComponent} from './ReactBaseClasses';
18
import {createRef} from './ReactCreateRef';
@@ -50,11 +49,13 @@ const React = {
49
50
createContext,
51
forwardRef,
52
+ lazy,
53
pure,
54
55
Fragment: REACT_FRAGMENT_TYPE,
56
StrictMode: REACT_STRICT_MODE_TYPE,
57
unstable_ConcurrentMode: REACT_CONCURRENT_MODE_TYPE,
58
+ unstable_Suspense: REACT_SUSPENSE_TYPE,
59
unstable_Profiler: REACT_PROFILER_TYPE,
60
61
createElement: __DEV__ ? createElementWithValidation : createElement,
@@ -67,9 +68,4 @@ const React = {
68
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals,
69
};
70
70
-if (enableSuspense) {
71
- React.Placeholder = REACT_PLACEHOLDER_TYPE;
72
- React.lazy = lazy;
73
-}
74
-
71
export default React;
packages/react/src/__tests__/ReactProfiler-test.internal.js
+26
-29
@@ -21,7 +21,6 @@ let AdvanceTime;
21
22
function loadModules({
23
enableProfilerTimer = true,
24
- enableSuspense = false,
24
enableSchedulerTracing = true,
25
replayFailedUnitOfWorkWithInvokeGuardedCallback = false,
26
useNoopRenderer = false,
@@ -37,7 +36,6 @@ function loadModules({
36
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
37
ReactFeatureFlags.enableProfilerTimer = enableProfilerTimer;
38
ReactFeatureFlags.enableSchedulerTracing = enableSchedulerTracing;
40
- ReactFeatureFlags.enableSuspense = enableSuspense;
39
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = replayFailedUnitOfWorkWithInvokeGuardedCallback;
40
41
React = require('react');
@@ -1234,7 +1232,6 @@ describe('Profiler', () => {
1232
jest.resetModules();
1233
1234
loadModules({
1237
- enableSuspense: true,
1235
enableSchedulerTracing: true,
1236
...params,
1237
});
@@ -2231,9 +2228,9 @@ describe('Profiler', () => {
2228
SchedulerTracing.unstable_trace(interaction.name, mockNow(), () => {
2229
ReactNoop.render(
2230
<React.unstable_Profiler id="test-profiler" onRender={onRender}>
2234
- <React.Placeholder fallback={<Text text="Loading..." />}>
2231
+ <React.unstable_Suspense fallback={<Text text="Loading..." />}>
2232
<AsyncText text="Async" ms={20000} />
2236
- </React.Placeholder>
2233
+ </React.unstable_Suspense>
2234
<Text text="Sync" />
2235
<Monkey ref={monkey} />
2236
</React.unstable_Profiler>,
@@ -2325,11 +2322,11 @@ describe('Profiler', () => {
2322
() => {
2323
ReactTestRenderer.create(
2324
<React.unstable_Profiler id="app" onRender={onRender}>
2328
- <React.Placeholder
2329
- delayMs={1000}
2325
+ <React.unstable_Suspense
2326
+ maxDuration={1000}
2327
fallback={<Text text="loading" />}>
2328
<AsyncText text="loaded" ms={2000} />
2332
- </React.Placeholder>
2329
+ </React.unstable_Suspense>
2330
</React.unstable_Profiler>,
2331
);
2332
},
@@ -2379,11 +2376,11 @@ describe('Profiler', () => {
2376
() => {
2377
ReactTestRenderer.create(
2378
<React.unstable_Profiler id="app" onRender={onRender}>
2382
- <React.Placeholder
2383
- delayMs={1000}
2379
+ <React.unstable_Suspense
2380
+ maxDuration={1000}
2381
fallback={<Text text="loading" />}>
2382
<AsyncComponentWithCascadingWork text="loaded" ms={2000} />
2386
- </React.Placeholder>
2383
+ </React.unstable_Suspense>
2384
</React.unstable_Profiler>,
2385
);
2386
},
@@ -2419,11 +2416,11 @@ describe('Profiler', () => {
2416
() => {
2417
renderer = ReactTestRenderer.create(
2418
<React.unstable_Profiler id="app" onRender={onRender}>
2422
- <React.Placeholder
2423
- delayMs={1000}
2419
+ <React.unstable_Suspense
2420
+ maxDuration={1000}
2421
fallback={<Text text="loading" />}>
2422
<AsyncText text="loaded" ms={2000} />
2426
- </React.Placeholder>
2423
+ </React.unstable_Suspense>
2424
</React.unstable_Profiler>,
2425
{
2426
unstable_isConcurrent: true,
@@ -2467,11 +2464,11 @@ describe('Profiler', () => {
2464
() => {
2465
renderer = ReactTestRenderer.create(
2466
<React.unstable_Profiler id="app" onRender={onRender}>
2470
- <React.Placeholder
2471
- delayMs={2000}
2467
+ <React.unstable_Suspense
2468
+ maxDuration={2000}
2469
fallback={<Text text="loading" />}>
2470
<AsyncText text="loaded" ms={1000} />
2474
- </React.Placeholder>
2471
+ </React.unstable_Suspense>
2472
</React.unstable_Profiler>,
2473
{unstable_isConcurrent: true},
2474
);
@@ -2506,11 +2503,11 @@ describe('Profiler', () => {
2503
() => {
2504
renderer = ReactTestRenderer.create(
2505
<React.unstable_Profiler id="app" onRender={onRender}>
2509
- <React.Placeholder
2510
- delayMs={2000}
2506
+ <React.unstable_Suspense
2507
+ maxDuration={2000}
2508
fallback={<Text text="loading" />}>
2509
<AsyncText text="loaded" ms={1000} />
2513
- </React.Placeholder>
2510
+ </React.unstable_Suspense>
2511
<Text text="initial" />
2512
</React.unstable_Profiler>,
2513
);
@@ -2540,11 +2537,11 @@ describe('Profiler', () => {
2537
() => {
2538
renderer.update(
2539
<React.unstable_Profiler id="app" onRender={onRender}>
2543
- <React.Placeholder
2544
- delayMs={2000}
2540
+ <React.unstable_Suspense
2541
+ maxDuration={2000}
2542
fallback={<Text text="loading" />}>
2543
<AsyncText text="loaded" ms={1000} />
2547
- </React.Placeholder>
2544
+ </React.unstable_Suspense>
2545
<Text text="updated" />
2546
</React.unstable_Profiler>,
2547
);
@@ -2602,11 +2599,11 @@ describe('Profiler', () => {
2599
() => {
2600
renderer = ReactTestRenderer.create(
2601
<React.unstable_Profiler id="app" onRender={onRender}>
2605
- <React.Placeholder
2606
- delayMs={2000}
2602
+ <React.unstable_Suspense
2603
+ maxDuration={2000}
2604
fallback={<Text text="loading" />}>
2605
<AsyncText text="loaded" ms={1000} />
2609
- </React.Placeholder>
2606
+ </React.unstable_Suspense>
2607
<Text text="initial" />
2608
</React.unstable_Profiler>,
2609
{unstable_isConcurrent: true},
@@ -2640,11 +2637,11 @@ describe('Profiler', () => {
2637
() => {
2638
renderer.update(
2639
<React.unstable_Profiler id="app" onRender={onRender}>
2643
- <React.Placeholder
2644
- delayMs={2000}
2640
+ <React.unstable_Suspense
2641
+ maxDuration={2000}
2642
fallback={<Text text="loading" />}>
2643
<AsyncText text="loaded" ms={1000} />
2647
- </React.Placeholder>
2644
+ </React.unstable_Suspense>
2645
<Text text="updated" />
2646
</React.unstable_Profiler>,
2647
);
packages/react/src/__tests__/ReactProfilerDOM-test.internal.js
+4
-3
@@ -50,7 +50,6 @@ function loadModules() {
50
ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
51
ReactFeatureFlags.enableProfilerTimer = true;
52
ReactFeatureFlags.enableSchedulerTracing = true;
53
- ReactFeatureFlags.enableSuspense = true;
53
54
React = require('react');
55
SchedulerTracing = require('scheduler/tracing');
@@ -120,9 +119,11 @@ describe('ProfilerDOM', () => {
119
const root = ReactDOM.unstable_createRoot(element);
120
batch = root.createBatch();
121
batch.render(
123
- <React.Placeholder delayMS={100} fallback={<Text text="Loading..." />}>
122
+ <React.unstable_Suspense
123
+ maxDuration={100}
124
+ fallback={<Text text="Loading..." />}>
125
<AsyncText text="Text" ms={200} />
125
- </React.Placeholder>,
126
+ </React.unstable_Suspense>,
127
);
128
batch.then(
129
SchedulerTracing.unstable_wrap(() => {
packages/shared/ReactFeatureFlags.js
-3
@@ -7,11 +7,8 @@
7
* @flow strict
8
*/
9
10
-// Exports ReactDOM.createRoot
10
export const enableUserTimingAPI = __DEV__;
11
13
-// Suspense
14
-export const enableSuspense = false;
12
// Helps identify side effects in begin-phase lifecycle hooks and setState reducers:
13
export const debugRenderPhaseSideEffects = false;
14
packages/shared/ReactSymbols.js
+2
-2
@@ -38,8 +38,8 @@ export const REACT_CONCURRENT_MODE_TYPE = hasSymbol
38
export const REACT_FORWARD_REF_TYPE = hasSymbol
39
? Symbol.for('react.forward_ref')
40
: 0xead0;
41
-export const REACT_PLACEHOLDER_TYPE = hasSymbol
42
- ? Symbol.for('react.placeholder')
41
+export const REACT_SUSPENSE_TYPE = hasSymbol
42
+ ? Symbol.for('react.suspense')
43
: 0xead1;
44
export const REACT_PURE_TYPE = hasSymbol ? Symbol.for('react.pure') : 0xead3;
45
packages/shared/ReactWorkTags.js
+1
-1
@@ -44,6 +44,6 @@ export const ContextProvider = 12;
44
export const ForwardRef = 13;
45
export const ForwardRefLazy = 14;
46
export const Profiler = 15;
47
-export const PlaceholderComponent = 16;
47
+export const SuspenseComponent = 16;
48
export const PureComponent = 17;
49
export const PureComponentLazy = 18;
packages/shared/forks/ReactFeatureFlags.native-fabric-fb.js
-1
@@ -15,7 +15,6 @@ import typeof * as FabricFeatureFlagsType from './ReactFeatureFlags.native-fabri
15
export const debugRenderPhaseSideEffects = false;
16
export const debugRenderPhaseSideEffectsForStrictMode = false;
17
export const enableUserTimingAPI = __DEV__;
18
-export const enableSuspense = false;
18
export const warnAboutDeprecatedLifecycles = false;
19
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
20
export const enableProfilerTimer = __PROFILE__;
packages/shared/forks/ReactFeatureFlags.native-fabric-oss.js
-1
@@ -15,7 +15,6 @@ import typeof * as FabricFeatureFlagsType from './ReactFeatureFlags.native-fabri
15
export const debugRenderPhaseSideEffects = false;
16
export const debugRenderPhaseSideEffectsForStrictMode = false;
17
export const enableUserTimingAPI = __DEV__;
18
-export const enableSuspense = false;
18
export const warnAboutDeprecatedLifecycles = false;
19
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
20
export const enableProfilerTimer = __PROFILE__;
packages/shared/forks/ReactFeatureFlags.native-fb.js
-1
@@ -14,7 +14,6 @@ import typeof * as FeatureFlagsShimType from './ReactFeatureFlags.native-fb';
14
15
// Re-export dynamic flags from the fbsource version.
16
export const {
17
- enableSuspense,
17
debugRenderPhaseSideEffects,
18
debugRenderPhaseSideEffectsForStrictMode,
19
warnAboutDeprecatedLifecycles,
packages/shared/forks/ReactFeatureFlags.native-oss.js
-1
@@ -14,7 +14,6 @@ import typeof * as FeatureFlagsShimType from './ReactFeatureFlags.native-oss';
14
15
export const debugRenderPhaseSideEffects = false;
16
export const debugRenderPhaseSideEffectsForStrictMode = false;
17
-export const enableSuspense = false;
17
export const enableUserTimingAPI = __DEV__;
18
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
19
export const warnAboutDeprecatedLifecycles = false;
packages/shared/forks/ReactFeatureFlags.persistent.js
-1
@@ -15,7 +15,6 @@ import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persiste
15
export const debugRenderPhaseSideEffects = false;
16
export const debugRenderPhaseSideEffectsForStrictMode = false;
17
export const enableUserTimingAPI = __DEV__;
18
-export const enableSuspense = false;
18
export const warnAboutDeprecatedLifecycles = false;
19
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;
20
export const enableProfilerTimer = __PROFILE__;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
-1
@@ -15,7 +15,6 @@ import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persiste
15
export const debugRenderPhaseSideEffects = false;
16
export const debugRenderPhaseSideEffectsForStrictMode = false;
17
export const enableUserTimingAPI = __DEV__;
18
-export const enableSuspense = false;
18
export const warnAboutDeprecatedLifecycles = false;
19
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
20
export const enableProfilerTimer = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
-1
@@ -15,7 +15,6 @@ import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persiste
15
export const debugRenderPhaseSideEffects = false;
16
export const debugRenderPhaseSideEffectsForStrictMode = false;
17
export const enableUserTimingAPI = __DEV__;
18
-export const enableSuspense = true;
18
export const warnAboutDeprecatedLifecycles = false;
19
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
20
export const enableProfilerTimer = false;
packages/shared/forks/ReactFeatureFlags.www.js
-1
@@ -12,7 +12,6 @@ import typeof * as FeatureFlagsShimType from './ReactFeatureFlags.www';
12
13
// Re-export dynamic flags from the www version.
14
export const {
15
- enableSuspense,
15
debugRenderPhaseSideEffects,
16
debugRenderPhaseSideEffectsForStrictMode,
17
enableSuspenseServerRenderer,
packages/shared/getComponentName.js
+3
-3
@@ -19,7 +19,7 @@ import {
19
REACT_PROFILER_TYPE,
20
REACT_PROVIDER_TYPE,
21
REACT_STRICT_MODE_TYPE,
22
- REACT_PLACEHOLDER_TYPE,
22
+ REACT_SUSPENSE_TYPE,
23
} from 'shared/ReactSymbols';
24
import {refineResolvedThenable} from 'shared/ReactLazyComponent';
25
@@ -54,8 +54,8 @@ function getComponentName(type: mixed): string | null {
54
return `Profiler`;
55
case REACT_STRICT_MODE_TYPE:
56
return 'StrictMode';
57
- case REACT_PLACEHOLDER_TYPE:
58
- return 'Placeholder';
57
+ case REACT_SUSPENSE_TYPE:
58
+ return 'Suspense';
59
}
60
if (typeof type === 'object') {
61
switch (type.$$typeof) {
packages/shared/isValidElementType.js
+2
-2
@@ -15,7 +15,7 @@ import {
15
REACT_PROFILER_TYPE,
16
REACT_PROVIDER_TYPE,
17
REACT_STRICT_MODE_TYPE,
18
- REACT_PLACEHOLDER_TYPE,
18
+ REACT_SUSPENSE_TYPE,
19
REACT_PURE_TYPE,
20
} from 'shared/ReactSymbols';
21
@@ -28,7 +28,7 @@ export default function isValidElementType(type: mixed) {
28
type === REACT_CONCURRENT_MODE_TYPE ||
29
type === REACT_PROFILER_TYPE ||
30
type === REACT_STRICT_MODE_TYPE ||
31
- type === REACT_PLACEHOLDER_TYPE ||
31
+ type === REACT_SUSPENSE_TYPE ||
32
(typeof type === 'object' &&
33
type !== null &&
34
(typeof type.then === 'function' ||