|
7 | 7 | * @flow |
8 | 8 | */ |
9 | 9 |
|
10 | | -import type { |
11 | | - ReactNodeList, |
12 | | - Thenable, |
13 | | - PendingThenable, |
14 | | - FulfilledThenable, |
15 | | - RejectedThenable, |
16 | | -} from 'shared/ReactTypes'; |
| 10 | +import type {ReactNodeList} from 'shared/ReactTypes'; |
17 | 11 |
|
18 | 12 | import isArray from 'shared/isArray'; |
19 | 13 | import { |
@@ -81,68 +75,6 @@ function getElementKey(element: any, index: number): string { |
81 | 75 | return index.toString(36); |
82 | 76 | } |
83 | 77 |
|
84 | | -function noop() {} |
85 | | - |
86 | | -function resolveThenable<T>(thenable: Thenable<T>): T { |
87 | | - switch (thenable.status) { |
88 | | - case 'fulfilled': { |
89 | | - const fulfilledValue: T = thenable.value; |
90 | | - return fulfilledValue; |
91 | | - } |
92 | | - case 'rejected': { |
93 | | - const rejectedError = thenable.reason; |
94 | | - throw rejectedError; |
95 | | - } |
96 | | - default: { |
97 | | - if (typeof thenable.status === 'string') { |
98 | | - // Only instrument the thenable if the status if not defined. If |
99 | | - // it's defined, but an unknown value, assume it's been instrumented by |
100 | | - // some custom userspace implementation. We treat it as "pending". |
101 | | - // Attach a dummy listener, to ensure that any lazy initialization can |
102 | | - // happen. Flight lazily parses JSON when the value is actually awaited. |
103 | | - thenable.then(noop, noop); |
104 | | - } else { |
105 | | - // This is an uncached thenable that we haven't seen before. |
106 | | - |
107 | | - // TODO: Detect infinite ping loops caused by uncached promises. |
108 | | - |
109 | | - const pendingThenable: PendingThenable<T> = (thenable: any); |
110 | | - pendingThenable.status = 'pending'; |
111 | | - pendingThenable.then( |
112 | | - fulfilledValue => { |
113 | | - if (thenable.status === 'pending') { |
114 | | - const fulfilledThenable: FulfilledThenable<T> = (thenable: any); |
115 | | - fulfilledThenable.status = 'fulfilled'; |
116 | | - fulfilledThenable.value = fulfilledValue; |
117 | | - } |
118 | | - }, |
119 | | - (error: mixed) => { |
120 | | - if (thenable.status === 'pending') { |
121 | | - const rejectedThenable: RejectedThenable<T> = (thenable: any); |
122 | | - rejectedThenable.status = 'rejected'; |
123 | | - rejectedThenable.reason = error; |
124 | | - } |
125 | | - }, |
126 | | - ); |
127 | | - } |
128 | | - |
129 | | - // Check one more time in case the thenable resolved synchronously. |
130 | | - switch (thenable.status) { |
131 | | - case 'fulfilled': { |
132 | | - const fulfilledThenable: FulfilledThenable<T> = (thenable: any); |
133 | | - return fulfilledThenable.value; |
134 | | - } |
135 | | - case 'rejected': { |
136 | | - const rejectedThenable: RejectedThenable<T> = (thenable: any); |
137 | | - const rejectedError = rejectedThenable.reason; |
138 | | - throw rejectedError; |
139 | | - } |
140 | | - } |
141 | | - } |
142 | | - } |
143 | | - throw thenable; |
144 | | -} |
145 | | - |
146 | 78 | function mapIntoArray( |
147 | 79 | children: ?ReactNodeList, |
148 | 80 | array: Array<React$Node>, |
@@ -175,14 +107,9 @@ function mapIntoArray( |
175 | 107 | invokeCallback = true; |
176 | 108 | break; |
177 | 109 | case REACT_LAZY_TYPE: |
178 | | - const payload = (children: any)._payload; |
179 | | - const init = (children: any)._init; |
180 | | - return mapIntoArray( |
181 | | - init(payload), |
182 | | - array, |
183 | | - escapedPrefix, |
184 | | - nameSoFar, |
185 | | - callback, |
| 110 | + throw new Error( |
| 111 | + 'Cannot render an Async Component, Promise or React.Lazy inside React.Children. ' + |
| 112 | + 'We recommend not iterating over children and just rendering them plain.', |
186 | 113 | ); |
187 | 114 | } |
188 | 115 | } |
@@ -285,19 +212,16 @@ function mapIntoArray( |
285 | 212 | ); |
286 | 213 | } |
287 | 214 | } else if (type === 'object') { |
| 215 | + // eslint-disable-next-line react-internal/safe-string-coercion |
| 216 | + const childrenString = String((children: any)); |
| 217 | + |
288 | 218 | if (typeof (children: any).then === 'function') { |
289 | | - return mapIntoArray( |
290 | | - resolveThenable((children: any)), |
291 | | - array, |
292 | | - escapedPrefix, |
293 | | - nameSoFar, |
294 | | - callback, |
| 219 | + throw new Error( |
| 220 | + 'Cannot render an Async Component, Promise or React.Lazy inside React.Children. ' + |
| 221 | + 'We recommend not iterating over children and just rendering them plain.', |
295 | 222 | ); |
296 | 223 | } |
297 | 224 |
|
298 | | - // eslint-disable-next-line react-internal/safe-string-coercion |
299 | | - const childrenString = String((children: any)); |
300 | | - |
301 | 225 | throw new Error( |
302 | 226 | `Objects are not valid as a React child (found: ${ |
303 | 227 | childrenString === '[object Object]' |
|
0 commit comments