React.Timeout -> React.Placeholder (#13105)
Changed the API to match what we've been using in our latest discussions. Our tentative plans are for <Placeholder> to automatically hide the timed-out children, instead of removing them, so their state is not lost. This part is not yet implemented. We'll likely have a lower level API that does not include the hiding behavior. This is also not yet implemented.
Andrew Clark committed
Jul 3, 2018 at 19:47 UTC
88d7ed8bfbccd860c3e309da39d356d0a3127aa7
11 files changed
+135
-127
packages/react-reconciler/src/ReactFiber.js
+4
-4
@@ -31,7 +31,7 @@ import {
31
ContextProvider,
32
ContextConsumer,
33
Profiler,
34
- TimeoutComponent,
34
+ PlaceholderComponent,
35
} from 'shared/ReactTypeOfWork';
36
import getComponentName from 'shared/getComponentName';
37
@@ -46,7 +46,7 @@ import {
46
REACT_PROVIDER_TYPE,
47
REACT_CONTEXT_TYPE,
48
REACT_ASYNC_MODE_TYPE,
49
- REACT_TIMEOUT_TYPE,
49
+ REACT_PLACEHOLDER_TYPE,
50
} from 'shared/ReactSymbols';
51
52
let hasBadMapPolyfill;
@@ -397,8 +397,8 @@ export function createFiberFromElement(
397
break;
398
case REACT_PROFILER_TYPE:
399
return createFiberFromProfiler(pendingProps, mode, expirationTime, key);
400
- case REACT_TIMEOUT_TYPE:
401
- fiberTag = TimeoutComponent;
400
+ case REACT_PLACEHOLDER_TYPE:
401
+ fiberTag = PlaceholderComponent;
402
break;
403
default:
404
fiberTag = getFiberTagFromObjectType(type, owner);
packages/react-reconciler/src/ReactFiberBeginWork.js
+19
-7
@@ -27,7 +27,7 @@ import {
27
ContextProvider,
28
ContextConsumer,
29
Profiler,
30
- TimeoutComponent,
30
+ PlaceholderComponent,
31
} from 'shared/ReactTypeOfWork';
32
import {
33
NoEffect,
@@ -703,7 +703,11 @@ function mountIndeterminateComponent(
703
}
704
}
705
706
-function updateTimeoutComponent(current, workInProgress, renderExpirationTime) {
706
+function updatePlaceholderComponent(
707
+ current,
708
+ workInProgress,
709
+ renderExpirationTime,
710
+) {
711
if (enableSuspense) {
712
const nextProps = workInProgress.pendingProps;
713
const prevProps = workInProgress.memoizedProps;
@@ -717,7 +721,7 @@ function updateTimeoutComponent(current, workInProgress, renderExpirationTime) {
721
722
let nextDidTimeout;
723
if (current !== null && workInProgress.updateQueue !== null) {
720
- // We're outside strict mode. Something inside this Timeout boundary
724
+ // We're outside strict mode. Something inside this Placeholder boundary
725
// suspended during the last commit. Switch to the placholder.
726
workInProgress.updateQueue = null;
727
nextDidTimeout = true;
@@ -756,8 +760,16 @@ function updateTimeoutComponent(current, workInProgress, renderExpirationTime) {
760
}
761
}
762
759
- const render = nextProps.children;
760
- const nextChildren = render(nextDidTimeout);
763
+ // If the `children` prop is a function, treat it like a render prop.
764
+ // TODO: This is temporary until we finalize a lower level API.
765
+ const children = nextProps.children;
766
+ let nextChildren;
767
+ if (typeof children === 'function') {
768
+ nextChildren = children(nextDidTimeout);
769
+ } else {
770
+ nextChildren = nextDidTimeout ? nextProps.fallback : children;
771
+ }
772
+
773
workInProgress.memoizedProps = nextProps;
774
workInProgress.memoizedState = nextDidTimeout;
775
reconcileChildren(current, workInProgress, nextChildren);
@@ -1197,8 +1209,8 @@ function beginWork(
1209
return updateHostComponent(current, workInProgress, renderExpirationTime);
1210
case HostText:
1211
return updateHostText(current, workInProgress);
1200
- case TimeoutComponent:
1201
- return updateTimeoutComponent(
1212
+ case PlaceholderComponent:
1213
+ return updatePlaceholderComponent(
1214
current,
1215
workInProgress,
1216
renderExpirationTime,
packages/react-reconciler/src/ReactFiberCommitWork.js
+3
-3
@@ -28,7 +28,7 @@ import {
28
HostText,
29
HostPortal,
30
Profiler,
31
- TimeoutComponent,
31
+ PlaceholderComponent,
32
} from 'shared/ReactTypeOfWork';
33
import ReactErrorUtils from 'shared/ReactErrorUtils';
34
import {
@@ -322,7 +322,7 @@ function commitLifeCycles(
322
// We have no life-cycles associated with Profiler.
323
return;
324
}
325
- case TimeoutComponent: {
325
+ case PlaceholderComponent: {
326
if (enableSuspense) {
327
if ((finishedWork.mode & StrictMode) === NoEffect) {
328
// In loose mode, a placeholder times out by scheduling a synchronous
@@ -837,7 +837,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
837
}
838
return;
839
}
840
- case TimeoutComponent: {
840
+ case PlaceholderComponent: {
841
return;
842
}
843
default: {
packages/react-reconciler/src/ReactFiberCompleteWork.js
+2
-2
@@ -35,7 +35,7 @@ import {
35
Fragment,
36
Mode,
37
Profiler,
38
- TimeoutComponent,
38
+ PlaceholderComponent,
39
} from 'shared/ReactTypeOfWork';
40
import {Placement, Ref, Update} from 'shared/ReactTypeOfSideEffect';
41
import {ProfileMode} from './ReactTypeOfMode';
@@ -490,7 +490,7 @@ function completeWork(
490
}
491
case ForwardRef:
492
return null;
493
- case TimeoutComponent:
493
+ case PlaceholderComponent:
494
return null;
495
case Fragment:
496
return null;
packages/react-reconciler/src/ReactFiberUnwindWork.js
+26
-25
@@ -22,7 +22,7 @@ import {
22
HostComponent,
23
HostPortal,
24
ContextProvider,
25
- TimeoutComponent,
25
+ PlaceholderComponent,
26
} from 'shared/ReactTypeOfWork';
27
import {
28
DidCapture,
@@ -157,16 +157,16 @@ function throwException(
157
// This is a thenable.
158
const thenable: Thenable = (value: any);
159
160
- // Find the earliest timeout of all the timeouts in the ancestor path. We
161
- // could avoid this traversal by storing the timeouts on the stack, but we
162
- // choose not to because we only hit this path if we're IO-bound (i.e. if
163
- // something suspends). Whereas the stack is used even in the non-IO-
164
- // bound case.
160
+ // Find the earliest timeout threshold of all the placeholders in the
161
+ // ancestor path. We could avoid this traversal by storing the thresholds on
162
+ // the stack, but we choose not to because we only hit this path if we're
163
+ // IO-bound (i.e. if something suspends). Whereas the stack is used even in
164
+ // the non-IO- bound case.
165
let workInProgress = returnFiber;
166
let earliestTimeoutMs = -1;
167
let startTimeMs = -1;
168
do {
169
- if (workInProgress.tag === TimeoutComponent) {
169
+ if (workInProgress.tag === PlaceholderComponent) {
170
const current = workInProgress.alternate;
171
if (
172
current !== null &&
@@ -184,7 +184,7 @@ function throwException(
184
// Do not search any further.
185
break;
186
}
187
- let timeoutPropMs = workInProgress.pendingProps.ms;
187
+ let timeoutPropMs = workInProgress.pendingProps.delayMs;
188
if (typeof timeoutPropMs === 'number') {
189
if (timeoutPropMs <= 0) {
190
earliestTimeoutMs = 0;
@@ -199,15 +199,15 @@ function throwException(
199
workInProgress = workInProgress.return;
200
} while (workInProgress !== null);
201
202
- // Schedule the nearest Timeout to re-render using a placeholder.
202
+ // Schedule the nearest Placeholder to re-render the timed out view.
203
workInProgress = returnFiber;
204
do {
205
- if (workInProgress.tag === TimeoutComponent) {
205
+ if (workInProgress.tag === PlaceholderComponent) {
206
const didTimeout = workInProgress.memoizedState;
207
if (!didTimeout) {
208
- // Found the nearest Timeout.
208
+ // Found the nearest boundary.
209
210
- // If the Timeout is not in async mode, we should not suspend, and
210
+ // If the boundary is not in async mode, we should not suspend, and
211
// likewise, when the promise resolves, we should ping synchronously.
212
const pingTime =
213
(workInProgress.mode & AsyncMode) === NoEffect
@@ -223,13 +223,13 @@ function throwException(
223
);
224
thenable.then(onResolveOrReject, onResolveOrReject);
225
226
- // If the Timeout component is outside of strict mode, we should *not*
227
- // suspend the commit. Pretend as if the suspended component rendered
228
- // null and keep rendering. In the commit phase, we'll schedule a
229
- // subsequent synchronous update to re-render the Timeout.
226
+ // If the boundary is outside of strict mode, we should *not* suspend
227
+ // the commit. Pretend as if the suspended component rendered null and
228
+ // keep rendering. In the commit phase, we'll schedule a subsequent
229
+ // synchronous update to re-render the Placeholder.
230
//
231
// Note: It doesn't matter whether the component that suspended was
232
- // inside a strict mode tree. If the Timeout is outside of it, we
232
+ // inside a strict mode tree. If the Placeholder is outside of it, we
233
// should *not* suspend the commit.
234
if ((workInProgress.mode & StrictMode) === NoEffect) {
235
workInProgress.effectTag |= UpdateEffect;
@@ -253,7 +253,7 @@ function throwException(
253
return;
254
}
255
256
- // Confirmed that the Timeout is in a strict mode tree. Continue with
256
+ // Confirmed that the bounary is in a strict mode tree. Continue with
257
// the normal suspend path.
258
259
let absoluteTimeoutMs;
@@ -285,20 +285,21 @@ function throwException(
285
absoluteTimeoutMs = startTimeMs + earliestTimeoutMs;
286
}
287
288
- // Mark the earliest timeout in the suspended fiber's ancestor path. After
289
- // completing the root, we'll take the largest of all the suspended
290
- // fiber's timeouts and use it to compute a timeout for the whole tree.
288
+ // Mark the earliest timeout in the suspended fiber's ancestor path.
289
+ // After completing the root, we'll take the largest of all the
290
+ // suspended fiber's timeouts and use it to compute a timeout for the
291
+ // whole tree.
292
renderDidSuspend(root, absoluteTimeoutMs, renderExpirationTime);
293
294
workInProgress.effectTag |= ShouldCapture;
295
return;
296
}
296
- // Already captured during this render. Continue to the next
297
- // Timeout ancestor.
297
+ // This boundary already captured during this render. Continue to the
298
+ // next boundary.
299
}
300
workInProgress = workInProgress.return;
301
} while (workInProgress !== null);
301
- // No Timeout was found. Fallthrough to error mode.
302
+ // No boundary was found. Fallthrough to error mode.
303
value = new Error(
304
'An update was suspended, but no placeholder UI was provided.',
305
);
@@ -390,7 +391,7 @@ function unwindWork(
391
popHostContext(workInProgress);
392
return null;
393
}
393
- case TimeoutComponent: {
394
+ case PlaceholderComponent: {
395
const effectTag = workInProgress.effectTag;
396
if (effectTag & ShouldCapture) {
397
workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture;
packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js
+71
-76
@@ -3,7 +3,7 @@ let ReactFeatureFlags;
3
let Fragment;
4
let ReactNoop;
5
let SimpleCacheProvider;
6
-let Timeout;
6
+let Placeholder;
7
let StrictMode;
8
let AsyncMode;
9
@@ -22,7 +22,7 @@ describe('ReactSuspense', () => {
22
Fragment = React.Fragment;
23
ReactNoop = require('react-noop-renderer');
24
SimpleCacheProvider = require('simple-cache-provider');
25
- Timeout = React.Timeout;
25
+ Placeholder = React.Placeholder;
26
StrictMode = React.StrictMode;
27
AsyncMode = React.unstable_AsyncMode;
28
@@ -89,14 +89,6 @@ describe('ReactSuspense', () => {
89
}
90
}
91
92
- function Fallback(props) {
93
- return (
94
- <Timeout ms={props.timeout}>
95
- {didExpire => (didExpire ? props.placeholder : props.children)}
96
- </Timeout>
97
- );
98
- }
99
-
92
it('suspends rendering and continues later', async () => {
93
function Bar(props) {
94
ReactNoop.yield('Bar');
@@ -106,12 +98,12 @@ describe('ReactSuspense', () => {
98
function Foo() {
99
ReactNoop.yield('Foo');
100
return (
109
- <Fallback>
101
+ <Placeholder>
102
<Bar>
103
<AsyncText text="A" ms={100} />
104
<Text text="B" />
105
</Bar>
114
- </Fallback>
106
+ </Placeholder>
107
);
108
}
109
@@ -146,15 +138,15 @@ describe('ReactSuspense', () => {
138
});
139
140
it('suspends siblings and later recovers each independently', async () => {
149
- // Render two sibling Timeout components
141
+ // Render two sibling Placeholder components
142
ReactNoop.render(
143
<Fragment>
152
- <Fallback timeout={1000} placeholder={<Text text="Loading A..." />}>
144
+ <Placeholder delayMs={1000} fallback={<Text text="Loading A..." />}>
145
<AsyncText text="A" ms={5000} />
154
- </Fallback>
155
- <Fallback timeout={3000} placeholder={<Text text="Loading B..." />}>
146
+ </Placeholder>
147
+ <Placeholder delayMs={3000} fallback={<Text text="Loading B..." />}>
148
<AsyncText text="B" ms={6000} />
157
- </Fallback>
149
+ </Placeholder>
150
</Fragment>,
151
);
152
expect(ReactNoop.flush()).toEqual([
@@ -175,15 +167,16 @@ describe('ReactSuspense', () => {
167
span('Loading B...'),
168
]);
169
178
- // Advance time by enough that the first Timeout's promise resolves
179
- // and switches back to the normal view. The second Timeout should still show the placeholder
170
+ // Advance time by enough that the first Placeholder's promise resolves and
171
+ // switches back to the normal view. The second Placeholder should still
172
+ // show the placeholder
173
ReactNoop.expire(1000);
174
await advanceTimers(1000);
175
176
expect(ReactNoop.flush()).toEqual(['Promise resolved [A]', 'A']);
177
expect(ReactNoop.getChildren()).toEqual([span('A'), span('Loading B...')]);
178
186
- // Advance time by enough that the second Timeout's promise resolves
179
+ // Advance time by enough that the second Placeholder's promise resolves
180
// and switches back to the normal view
181
ReactNoop.expire(1000);
182
await advanceTimers(1000);
@@ -194,12 +187,12 @@ describe('ReactSuspense', () => {
187
188
it('continues rendering siblings after suspending', async () => {
189
ReactNoop.render(
197
- <Fallback>
190
+ <Placeholder>
191
<Text text="A" />
192
<AsyncText text="B" />
193
<Text text="C" />
194
<Text text="D" />
202
- </Fallback>,
195
+ </Placeholder>,
196
);
197
// B suspends. Continue rendering the remaining siblings.
198
expect(ReactNoop.flush()).toEqual(['A', 'Suspend! [B]', 'C', 'D']);
@@ -244,11 +237,11 @@ describe('ReactSuspense', () => {
237
const errorBoundary = React.createRef();
238
function App() {
239
return (
247
- <Fallback>
240
+ <Placeholder>
241
<ErrorBoundary ref={errorBoundary}>
242
<AsyncText text="Result" ms={1000} />
243
</ErrorBoundary>
251
- </Fallback>
244
+ </Placeholder>
245
);
246
}
247
@@ -306,11 +299,11 @@ describe('ReactSuspense', () => {
299
const errorBoundary = React.createRef();
300
function App() {
301
return (
309
- <Fallback timeout={1000} placeholder={<Text text="Loading..." />}>
302
+ <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
303
<ErrorBoundary ref={errorBoundary}>
304
<AsyncText text="Result" ms={3000} />
305
</ErrorBoundary>
313
- </Fallback>
306
+ </Placeholder>
307
);
308
}
309
@@ -357,10 +350,10 @@ describe('ReactSuspense', () => {
350
it('can update at a higher priority while in a suspended state', async () => {
351
function App(props) {
352
return (
360
- <Fallback>
353
+ <Placeholder>
354
<Text text={props.highPri} />
355
<AsyncText text={props.lowPri} />
363
- </Fallback>
356
+ </Placeholder>
357
);
358
}
359
@@ -396,10 +389,10 @@ describe('ReactSuspense', () => {
389
it('keeps working on lower priority work after being pinged', async () => {
390
function App(props) {
391
return (
399
- <Fallback>
392
+ <Placeholder>
393
<AsyncText text="A" />
394
{props.showB && <Text text="B" />}
402
- </Fallback>
395
+ </Placeholder>
396
);
397
}
398
@@ -424,9 +417,9 @@ describe('ReactSuspense', () => {
417
return <Text text="(empty)" />;
418
}
419
return (
427
- <Fallback>
420
+ <Placeholder>
421
<AsyncText ms={2000} text="Async" />
429
- </Fallback>
422
+ </Placeholder>
423
);
424
}
425
@@ -451,9 +444,9 @@ describe('ReactSuspense', () => {
444
it('forces an expiration after an update times out', async () => {
445
ReactNoop.render(
446
<Fragment>
454
- <Fallback placeholder={<Text text="Loading..." />}>
447
+ <Placeholder fallback={<Text text="Loading..." />}>
448
<AsyncText text="Async" ms={20000} />
456
- </Fallback>
449
+ </Placeholder>
450
<Text text="Sync" />
451
</Fragment>,
452
);
@@ -489,14 +482,14 @@ describe('ReactSuspense', () => {
482
ReactNoop.render(
483
<Fragment>
484
<Text text="Sync" />
492
- <Fallback timeout={1000} placeholder={<Text text="Loading outer..." />}>
485
+ <Placeholder delayMs={1000} fallback={<Text text="Loading outer..." />}>
486
<AsyncText text="Outer content" ms={2000} />
494
- <Fallback
495
- timeout={2500}
496
- placeholder={<Text text="Loading inner..." />}>
487
+ <Placeholder
488
+ delayMs={2500}
489
+ fallback={<Text text="Loading inner..." />}>
490
<AsyncText text="Inner content" ms={5000} />
498
- </Fallback>
499
- </Fallback>
491
+ </Placeholder>
492
+ </Placeholder>
493
</Fragment>,
494
);
495
@@ -570,9 +563,9 @@ describe('ReactSuspense', () => {
563
ReactNoop.flushSync(() =>
564
ReactNoop.render(
565
<Fragment>
573
- <Fallback placeholder={<Text text="Loading..." />}>
566
+ <Placeholder fallback={<Text text="Loading..." />}>
567
<AsyncText text="Async" />
575
- </Fallback>
568
+ </Placeholder>
569
<Text text="Sync" />
570
</Fragment>,
571
),
@@ -598,12 +591,12 @@ describe('ReactSuspense', () => {
591
ReactNoop.flushSync(() =>
592
ReactNoop.render(
593
<Fragment>
601
- <Fallback placeholder={<Text text="Loading (outer)..." />}>
602
- <Fallback placeholder={<AsyncText text="Loading (inner)..." />}>
594
+ <Placeholder fallback={<Text text="Loading (outer)..." />}>
595
+ <Placeholder fallback={<AsyncText text="Loading (inner)..." />}>
596
<AsyncText text="Async" />
604
- </Fallback>
597
+ </Placeholder>
598
<Text text="Sync" />
606
- </Fallback>
599
+ </Placeholder>
600
</Fragment>,
601
),
602
);
@@ -617,12 +610,12 @@ describe('ReactSuspense', () => {
610
expect(ReactNoop.getChildren()).toEqual([span('Loading (outer)...')]);
611
});
612
620
- it('expires early with a `timeout` option', async () => {
613
+ it('expires early with a `delayMs` option', async () => {
614
ReactNoop.render(
615
<Fragment>
623
- <Fallback timeout={1000} placeholder={<Text text="Loading..." />}>
616
+ <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
617
<AsyncText text="Async" ms={3000} />
625
- </Fallback>
618
+ </Placeholder>
619
<Text text="Sync" />
620
</Fragment>,
621
);
@@ -654,17 +647,19 @@ describe('ReactSuspense', () => {
647
it('throws a helpful error when an update is suspends without a placeholder', () => {
648
expect(() => {
649
ReactNoop.flushSync(() =>
657
- ReactNoop.render(<Timeout>{() => <AsyncText text="Async" />}</Timeout>),
650
+ ReactNoop.render(
651
+ <Placeholder>{() => <AsyncText text="Async" />}</Placeholder>,
652
+ ),
653
);
654
}).toThrow('An update was suspended, but no placeholder UI was provided.');
655
});
656
662
- it('a Timeout component correctly handles more than one suspended child', async () => {
657
+ it('a Placeholder component correctly handles more than one suspended child', async () => {
658
ReactNoop.render(
664
- <Fallback timeout={0}>
659
+ <Placeholder delayMs={0}>
660
<AsyncText text="A" ms={100} />
661
<AsyncText text="B" ms={100} />
667
- </Fallback>,
662
+ </Placeholder>,
663
);
664
expect(ReactNoop.expire(10000)).toEqual(['Suspend! [A]', 'Suspend! [B]']);
665
expect(ReactNoop.getChildren()).toEqual([]);
@@ -682,9 +677,9 @@ describe('ReactSuspense', () => {
677
678
it('can resume rendering earlier than a timeout', async () => {
679
ReactNoop.render(
685
- <Fallback timeout={1000} placeholder={<Text text="Loading..." />}>
680
+ <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
681
<AsyncText text="Async" ms={100} />
687
- </Fallback>,
682
+ </Placeholder>,
683
);
684
expect(ReactNoop.flush()).toEqual(['Suspend! [Async]', 'Loading...']);
685
expect(ReactNoop.getChildren()).toEqual([]);
@@ -707,13 +702,13 @@ describe('ReactSuspense', () => {
702
it('starts working on an update even if its priority falls between two suspended levels', async () => {
703
function App(props) {
704
return (
710
- <Fallback timeout={10000}>
705
+ <Placeholder delayMs={10000}>
706
{props.text === 'C' ? (
707
<Text text="C" />
708
) : (
709
<AsyncText text={props.text} ms={10000} />
710
)}
716
- </Fallback>
711
+ </Placeholder>
712
);
713
}
714
@@ -756,7 +751,7 @@ describe('ReactSuspense', () => {
751
it('can hide a tree to unblock its surroundings', async () => {
752
function App() {
753
return (
759
- <Timeout ms={1000}>
754
+ <Placeholder delayMs={1000}>
755
{didTimeout => (
756
<Fragment>
757
<div hidden={didTimeout}>
@@ -765,7 +760,7 @@ describe('ReactSuspense', () => {
760
{didTimeout ? <Text text="Loading..." /> : null}
761
</Fragment>
762
)}
768
- </Timeout>
763
+ </Placeholder>
764
);
765
}
766
@@ -789,13 +784,13 @@ describe('ReactSuspense', () => {
784
function Never() {
785
// Throws a promise that resolves after some arbitrarily large
786
// number of seconds. The idea is that this component will never
792
- // resolve. It's always wrapped by a Timeout.
787
+ // resolve. It's always wrapped by a Placeholder.
788
throw new Promise(resolve => setTimeout(() => resolve(), 10000));
789
}
790
791
function Delay({ms}) {
792
return (
798
- <Timeout ms={ms}>
793
+ <Placeholder delayMs={ms}>
794
{didTimeout => {
795
if (didTimeout) {
796
// Once ms has elapsed, render null. This allows the rest of the
@@ -804,7 +799,7 @@ describe('ReactSuspense', () => {
799
}
800
return <Never />;
801
}}
807
- </Timeout>
802
+ </Placeholder>
803
);
804
}
805
@@ -838,9 +833,9 @@ describe('ReactSuspense', () => {
833
it('times out immediately', async () => {
834
function App() {
835
return (
841
- <Fallback timeout={1000} placeholder={<Text text="Loading..." />}>
836
+ <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
837
<AsyncText ms={100} text="Result" />
843
- </Fallback>
838
+ </Placeholder>
839
);
840
}
841
@@ -861,7 +856,7 @@ describe('ReactSuspense', () => {
856
expect(ReactNoop.getChildren()).toEqual([span('Result')]);
857
});
858
864
- it('times out immediately when Timeout is in loose mode, even if the suspender is async', async () => {
859
+ it('times out immediately when Placeholder is in loose mode, even if the suspender is async', async () => {
860
class UpdatingText extends React.Component {
861
state = {step: 1};
862
render() {
@@ -869,7 +864,7 @@ describe('ReactSuspense', () => {
864
}
865
}
866
872
- function Placeholder() {
867
+ function Spinner() {
868
return (
869
<Fragment>
870
<Text text="Loading (1)" />
@@ -882,12 +877,12 @@ describe('ReactSuspense', () => {
877
const text = React.createRef(null);
878
function App() {
879
return (
885
- <Fallback timeout={1000} placeholder={<Placeholder />}>
880
+ <Placeholder delayMs={1000} fallback={<Spinner />}>
881
<AsyncMode>
882
<UpdatingText ref={text} />
883
<Text text="Sibling" />
884
</AsyncMode>
890
- </Fallback>
885
+ </Placeholder>
886
);
887
}
888
@@ -959,7 +954,7 @@ describe('ReactSuspense', () => {
954
function App() {
955
return (
956
<StrictMode>
962
- <Fallback timeout={1000} placeholder={<Text text="Loading..." />}>
957
+ <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
958
<AsyncMode>
959
<UpdatingText ref={text1} initialText="Async: 1">
960
{text => (
@@ -971,7 +966,7 @@ describe('ReactSuspense', () => {
966
)}
967
</UpdatingText>
968
</AsyncMode>
974
- </Fallback>
969
+ </Placeholder>
970
<AsyncMode>
971
<UpdatingText ref={text2} initialText="Sync: 1">
972
{text => (
@@ -1091,7 +1086,7 @@ describe('ReactSuspense', () => {
1086
function App() {
1087
return (
1088
<Fragment>
1094
- <Fallback timeout={1000} placeholder={<Text text="Loading..." />}>
1089
+ <Placeholder delayMs={1000} fallback={<Text text="Loading..." />}>
1090
<AsyncMode>
1091
<UpdatingText ref={text1} initialText="Async: 1">
1092
{text => (
@@ -1103,7 +1098,7 @@ describe('ReactSuspense', () => {
1098
)}
1099
</UpdatingText>
1100
</AsyncMode>
1106
- </Fallback>
1101
+ </Placeholder>
1102
<AsyncMode>
1103
<UpdatingText ref={text2} initialText="Sync: 1">
1104
{text => (
@@ -1235,13 +1230,13 @@ describe('ReactSuspense', () => {
1230
1231
function App() {
1232
return (
1238
- <Fallback
1239
- timeout={1000}
1240
- placeholder={<TextWithLifecycle text="Loading..." />}>
1233
+ <Placeholder
1234
+ delayMs={1000}
1235
+ fallback={<TextWithLifecycle text="Loading..." />}>
1236
<TextWithLifecycle text="A" />
1237
<AsyncTextWithLifecycle ms={100} text="B" />
1238
<TextWithLifecycle text="C" />
1244
- </Fallback>
1239
+ </Placeholder>
1240
);
1241
}
1242
packages/react/src/React.js
+2
-2
@@ -12,7 +12,7 @@ import {
12
REACT_FRAGMENT_TYPE,
13
REACT_PROFILER_TYPE,
14
REACT_STRICT_MODE_TYPE,
15
- REACT_TIMEOUT_TYPE,
15
+ REACT_PLACEHOLDER_TYPE,
16
} from 'shared/ReactSymbols';
17
import {enableSuspense} from 'shared/ReactFeatureFlags';
18
@@ -71,7 +71,7 @@ const React = {
71
};
72
73
if (enableSuspense) {
74
- React.Timeout = REACT_TIMEOUT_TYPE;
74
+ React.Placeholder = REACT_PLACEHOLDER_TYPE;
75
}
76
77
if (__DEV__) {
packages/shared/ReactSymbols.js
+2
-2
@@ -38,8 +38,8 @@ export const REACT_ASYNC_MODE_TYPE = hasSymbol
38
export const REACT_FORWARD_REF_TYPE = hasSymbol
39
? Symbol.for('react.forward_ref')
40
: 0xead0;
41
-export const REACT_TIMEOUT_TYPE = hasSymbol
42
- ? Symbol.for('react.timeout')
41
+export const REACT_PLACEHOLDER_TYPE = hasSymbol
42
+ ? Symbol.for('react.placeholder')
43
: 0xead1;
44
45
const MAYBE_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
packages/shared/ReactTypeOfWork.js
+1
-1
@@ -42,4 +42,4 @@ export const ContextConsumer = 12;
42
export const ContextProvider = 13;
43
export const ForwardRef = 14;
44
export const Profiler = 15;
45
-export const TimeoutComponent = 16;
45
+export const PlaceholderComponent = 16;
packages/shared/getComponentName.js
+3
-3
@@ -18,7 +18,7 @@ import {
18
REACT_PROFILER_TYPE,
19
REACT_PROVIDER_TYPE,
20
REACT_STRICT_MODE_TYPE,
21
- REACT_TIMEOUT_TYPE,
21
+ REACT_PLACEHOLDER_TYPE,
22
} from 'shared/ReactSymbols';
23
24
function getComponentName(fiber: Fiber): string | null {
@@ -44,8 +44,8 @@ function getComponentName(fiber: Fiber): string | null {
44
return 'Context.Provider';
45
case REACT_STRICT_MODE_TYPE:
46
return 'StrictMode';
47
- case REACT_TIMEOUT_TYPE:
48
- return 'Timeout';
47
+ case REACT_PLACEHOLDER_TYPE:
48
+ return 'Placeholder';
49
}
50
if (typeof type === 'object' && type !== null) {
51
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_TIMEOUT_TYPE,
18
+ REACT_PLACEHOLDER_TYPE,
19
} from 'shared/ReactSymbols';
20
21
export default function isValidElementType(type: mixed) {
@@ -27,7 +27,7 @@ export default function isValidElementType(type: mixed) {
27
type === REACT_ASYNC_MODE_TYPE ||
28
type === REACT_PROFILER_TYPE ||
29
type === REACT_STRICT_MODE_TYPE ||
30
- type === REACT_TIMEOUT_TYPE ||
30
+ type === REACT_PLACEHOLDER_TYPE ||
31
(typeof type === 'object' &&
32
type !== null &&
33
(type.$$typeof === REACT_PROVIDER_TYPE ||