[Flight] Gated test for dropped transport of undefined object values (#26478)
## Summary With https://github.com/facebook/react/pull/26349 we now serialize `undefined`. However, deserializing it on the client is currently indistinguishable from the value missing entirely due to how `JSON.parse` treats `undefined` return value of reviver functions. This leads to inconsistent behavior of the `Object.hasOwn` or `in` operator (used for narrowing in TypeScript). In TypeScript-speak, `{ prop: T | undefined}` will arrive as `{ prop?: T }`. ## How did you test this change? - Added test that is expected to fail. Though ideally the implementation of the component would not care whether it's used on the client or server.
Sebastian Silbermann committed
Mar 29, 2023 at 18:27 UTC
f118b7cebf9c15d11c5973bfd40860b5f457df08
1 file changed
+34
packages/react-client/src/__tests__/ReactFlight-test.js
+34
@@ -213,6 +213,40 @@ describe('ReactFlight', () => {
213
expect(ReactNoop).toMatchRenderedOutput(null);
214
});
215
216
+ // @gate FIXME
217
+ it('should transport undefined object values', async () => {
218
+ function ServerComponent(props) {
219
+ return 'prop' in props
220
+ ? `\`prop\` in props as '${props.prop}'`
221
+ : '`prop` not in props';
222
+ }
223
+ const ClientComponent = clientReference(ServerComponent);
224
+
225
+ const model = (
226
+ <>
227
+ <div>
228
+ Server: <ServerComponent prop={undefined} />
229
+ </div>
230
+ <div>
231
+ Client: <ClientComponent prop={undefined} />
232
+ </div>
233
+ </>
234
+ );
235
+
236
+ const transport = ReactNoopFlightServer.render(model);
237
+
238
+ await act(async () => {
239
+ ReactNoop.render(await ReactNoopFlightClient.read(transport));
240
+ });
241
+
242
+ expect(ReactNoop).toMatchRenderedOutput(
243
+ <>
244
+ <div>Server: `prop` in props as 'undefined'</div>
245
+ <div>Client: `prop` in props as 'undefined'</div>
246
+ </>,
247
+ );
248
+ });
249
+
250
it('can render an empty fragment', async () => {
251
function Empty() {
252
return <React.Fragment />;