Skip to content

Commit 106ea1c

Browse files
authored
Support Iterables in Flight (#26313)
We support any super type of anything that we can serialize. Meaning that as long as the Type that's passed through is less precise, it means that we can encoded it as any subtype and therefore the incoming type doesn't have to be the subtype in that case. Basically, as long as you're only passing through an `Iterable<T>` in TypeScript, then you can pass any `Iterable<T>` and we'll treat it as an array. For example we support Promises *and* Thenables but both are encoded as Promises. We support Arrays and since Arrays are also Iterables, we can support Iterables. For @wongmjane
1 parent f905da2 commit 106ea1c

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

packages/react-client/src/__tests__/ReactFlight-test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,34 @@ describe('ReactFlight', () => {
169169
expect(ReactNoop).toMatchRenderedOutput(<span>Hello, Seb Smith</span>);
170170
});
171171

172+
it('can render an iterable as an array', async () => {
173+
function ItemListClient(props) {
174+
return <span>{props.items}</span>;
175+
}
176+
const ItemList = clientReference(ItemListClient);
177+
178+
function Items() {
179+
const iterable = {
180+
[Symbol.iterator]: function* () {
181+
yield 'A';
182+
yield 'B';
183+
yield 'C';
184+
},
185+
};
186+
return <ItemList items={iterable} />;
187+
}
188+
189+
const model = <Items />;
190+
191+
const transport = ReactNoopFlightServer.render(model);
192+
193+
await act(async () => {
194+
ReactNoop.render(await ReactNoopFlightClient.read(transport));
195+
});
196+
197+
expect(ReactNoop).toMatchRenderedOutput(<span>ABC</span>);
198+
});
199+
172200
it('can render a lazy component as a shared component on the server', async () => {
173201
function SharedComponent({text}) {
174202
return (

packages/react-server/src/ReactFlightServer.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import {
7373
} from './ReactFlightNewContext';
7474

7575
import {
76+
getIteratorFn,
7677
REACT_ELEMENT_TYPE,
7778
REACT_FORWARD_REF_TYPE,
7879
REACT_FRAGMENT_TYPE,
@@ -1059,6 +1060,12 @@ export function resolveModelToJSON(
10591060
}
10601061
return (undefined: any);
10611062
}
1063+
if (!isArray(value)) {
1064+
const iteratorFn = getIteratorFn(value);
1065+
if (iteratorFn) {
1066+
return Array.from((value: any));
1067+
}
1068+
}
10621069

10631070
if (__DEV__) {
10641071
if (value !== null && !isArray(value)) {

0 commit comments

Comments
 (0)