Skip to content

Commit 5a5fae4

Browse files
committed
Expose lower level async hooks to Relay
This requires an external helper file that we'll wire up internally.
1 parent a64c5e1 commit 5a5fae4

File tree

8 files changed

+104
-70
lines changed

8 files changed

+104
-70
lines changed

packages/react-flight-dom-relay/src/ReactFlightDOMRelayClient.js

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
* @flow
88
*/
99

10-
import type {ReactModelRoot} from 'react-client/src/ReactFlightClient';
11-
12-
import type {Chunk} from './ReactFlightDOMRelayClientHostConfig';
10+
import type {Response, JSONValue} from 'react-client/src/ReactFlightClient';
1311

1412
import {
1513
createResponse,
@@ -20,8 +18,6 @@ import {
2018
close,
2119
} from 'react-client/src/ReactFlightClient';
2220

23-
type EncodedData = Array<Chunk>;
24-
2521
function parseModel(response, targetObj, key, value) {
2622
if (typeof value === 'object' && value !== null) {
2723
if (Array.isArray(value)) {
@@ -42,27 +38,8 @@ function parseModel(response, targetObj, key, value) {
4238
return parseModelFromJSON(response, targetObj, key, value);
4339
}
4440

45-
function read<T>(data: EncodedData): ReactModelRoot<T> {
46-
let response = createResponse();
47-
for (let i = 0; i < data.length; i++) {
48-
let chunk = data[i];
49-
if (chunk.type === 'json') {
50-
resolveModelChunk(
51-
response,
52-
chunk.id,
53-
parseModel(response, {}, '', chunk.json),
54-
);
55-
} else {
56-
resolveErrorChunk(
57-
response,
58-
chunk.id,
59-
chunk.json.message,
60-
chunk.json.stack,
61-
);
62-
}
63-
}
64-
close(response);
65-
return getModelRoot(response);
66-
}
41+
export {createResponse, getModelRoot, resolveErrorChunk, close};
6742

68-
export {read};
43+
export function resolveModel(response: Response, id: number, json: JSONValue) {
44+
resolveModelChunk(response, id, parseModel(response, {}, '', json));
45+
}

packages/react-flight-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,6 @@
77
* @flow
88
*/
99

10-
type JSONValue =
11-
| string
12-
| number
13-
| boolean
14-
| null
15-
| {[key: string]: JSONValue}
16-
| Array<JSONValue>;
17-
18-
export type Chunk =
19-
| {
20-
type: 'json',
21-
id: number,
22-
json: JSONValue,
23-
}
24-
| {
25-
type: 'error',
26-
id: number,
27-
json: {
28-
message: string,
29-
stack: string,
30-
...
31-
},
32-
};
33-
3410
export type StringDecoder = void;
3511

3612
export const supportsBinaryStreams = false;

packages/react-flight-dom-relay/src/ReactFlightDOMRelayServer.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,13 @@
88
*/
99

1010
import type {ReactModel} from 'react-server/src/ReactFlightServer';
11-
import type {Chunk} from './ReactFlightDOMRelayServerHostConfig';
11+
import type {Destination} from './ReactFlightDOMRelayServerHostConfig';
1212

1313
import {createRequest, startWork} from 'react-server/src/ReactFlightServer';
1414

15-
type EncodedData = Array<Chunk>;
16-
17-
function render(model: ReactModel): EncodedData {
18-
let data: EncodedData = [];
19-
let request = createRequest(model, data);
15+
function render(model: ReactModel, destination: Destination): void {
16+
let request = createRequest(model, destination);
2017
startWork(request);
21-
return data;
2218
}
2319

2420
export {render};

packages/react-flight-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@
99

1010
import type {Request, ReactModel} from 'react-server/src/ReactFlightServer';
1111

12+
import type {Destination} from 'ReactFlightDOMRelayServerIntegration';
13+
1214
import {resolveModelToJSON} from 'react-server/src/ReactFlightServer';
1315

14-
export type Destination = Array<Chunk>;
16+
import {emitModel, emitError} from 'ReactFlightDOMRelayServerIntegration';
17+
18+
export type {Destination} from 'ReactFlightDOMRelayServerIntegration';
1519

1620
type JSONValue =
1721
| string
@@ -95,10 +99,14 @@ export function flushBuffered(destination: Destination) {}
9599
export function beginWriting(destination: Destination) {}
96100

97101
export function writeChunk(destination: Destination, chunk: Chunk): boolean {
98-
destination.push(chunk);
102+
if (chunk.type === 'json') {
103+
emitModel(destination, chunk.id, chunk.json);
104+
} else {
105+
emitError(destination, chunk.id, chunk.json.message, chunk.json.stack);
106+
}
99107
return true;
100108
}
101109

102110
export function completeWriting(destination: Destination) {}
103111

104-
export function close(destination: Destination) {}
112+
export {close} from 'ReactFlightDOMRelayServerIntegration';
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
'use strict';
9+
10+
const ReactFlightDOMRelayServerIntegration = {
11+
emitModel(destination, id, json) {
12+
destination.push({
13+
type: 'json',
14+
id: id,
15+
json: json,
16+
});
17+
},
18+
emitError(destination, id, message, stack) {
19+
destination.push({
20+
type: 'error',
21+
id: id,
22+
json: {message, stack},
23+
});
24+
},
25+
close(destination) {},
26+
};
27+
28+
module.exports = ReactFlightDOMRelayServerIntegration;

packages/react-flight-dom-relay/src/__tests__/ReactFlightDOMRelay-test.internal.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77

88
'use strict';
99

10-
// Polyfills for test environment
11-
global.TextDecoder = require('util').TextDecoder;
12-
1310
let React;
1411
let ReactDOMFlightRelayServer;
1512
let ReactDOMFlightRelayClient;
@@ -32,11 +29,30 @@ describe('ReactFlightDOMRelay', () => {
3229
bar: [<Bar text="a" />, <Bar text="b" />],
3330
};
3431
}
35-
let data = ReactDOMFlightRelayServer.render({
36-
foo: <Foo />,
37-
});
38-
let root = ReactDOMFlightRelayClient.read(data);
39-
let model = root.model;
32+
let data = [];
33+
ReactDOMFlightRelayServer.render(
34+
{
35+
foo: <Foo />,
36+
},
37+
data,
38+
);
39+
40+
let response = ReactDOMFlightRelayClient.createResponse();
41+
for (let i = 0; i < data.length; i++) {
42+
let chunk = data[i];
43+
if (chunk.type === 'json') {
44+
ReactDOMFlightRelayClient.resolveModel(response, chunk.id, chunk.json);
45+
} else {
46+
ReactDOMFlightRelayClient.resolveError(
47+
response,
48+
chunk.id,
49+
chunk.json.message,
50+
chunk.json.stack,
51+
);
52+
}
53+
}
54+
let model = ReactDOMFlightRelayClient.getModelRoot(response).model;
55+
ReactDOMFlightRelayClient.close(response);
4056
expect(model).toEqual({foo: {bar: ['A', 'B']}});
4157
});
4258
});

scripts/flow/config/flowconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
../environment.js
3030
../react-devtools.js
3131
../react-native-host-hooks.js
32+
../react-relay-hooks.js
3233

3334
[lints]
3435
untyped-type-import=error

scripts/flow/react-relay-hooks.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow
8+
*/
9+
10+
type JSONValue =
11+
| string
12+
| number
13+
| boolean
14+
| null
15+
| {[key: string]: JSONValue}
16+
| Array<JSONValue>;
17+
18+
declare module 'ReactFlightDOMRelayServerIntegration' {
19+
declare export opaque type Destination;
20+
declare export function emitModel(
21+
destination: Destination,
22+
id: number,
23+
json: JSONValue,
24+
): void;
25+
declare export function emitError(
26+
destination: Destination,
27+
id: number,
28+
message: string,
29+
stack: string,
30+
): void;
31+
declare export function close(destination: Destination): void;
32+
}

0 commit comments

Comments
 (0)