Skip to content

Commit 769b13e

Browse files
committed
Failing test for Client reconciliation
1 parent e6a0f27 commit 769b13e

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

packages/react-transport-dom-webpack/src/__tests__/ReactFlightDOM-test.js

+88
Original file line numberDiff line numberDiff line change
@@ -438,4 +438,92 @@ describe('ReactFlightDOM', () => {
438438
'<p>Game over</p>', // TODO: should not have message in prod.
439439
);
440440
});
441+
442+
// @gate experimental
443+
it('should preserve state of client components on refetch', async () => {
444+
const {Suspense} = React;
445+
446+
// Client
447+
448+
function Page({response}) {
449+
return response.readRoot();
450+
}
451+
452+
function Input() {
453+
return <input />;
454+
}
455+
456+
const InputClient = moduleReference(Input);
457+
458+
// Server
459+
460+
function App({color}) {
461+
// Verify both DOM and Client children.
462+
return (
463+
<div style={{color}}>
464+
<input />
465+
<InputClient />
466+
</div>
467+
);
468+
}
469+
470+
const container = document.createElement('div');
471+
const root = ReactDOM.unstable_createRoot(container);
472+
473+
const stream1 = getTestStream();
474+
ReactTransportDOMServer.pipeToNodeWritable(
475+
<App color="red" />,
476+
stream1.writable,
477+
webpackMap,
478+
);
479+
const response1 = ReactTransportDOMClient.createFromReadableStream(
480+
stream1.readable,
481+
);
482+
await act(async () => {
483+
root.render(
484+
<Suspense fallback={<p>(loading)</p>}>
485+
<Page response={response1} />
486+
</Suspense>,
487+
);
488+
});
489+
expect(container.children.length).toBe(1);
490+
expect(container.children[0].tagName).toBe('DIV');
491+
expect(container.children[0].style.color).toBe('red');
492+
493+
// Change the DOM state for both inputs.
494+
const inputA = container.children[0].children[0];
495+
expect(inputA.tagName).toBe('INPUT');
496+
inputA.value = 'hello';
497+
const inputB = container.children[0].children[1];
498+
expect(inputB.tagName).toBe('INPUT');
499+
inputB.value = 'goodbye';
500+
501+
const stream2 = getTestStream();
502+
ReactTransportDOMServer.pipeToNodeWritable(
503+
<App color="blue" />,
504+
stream2.writable,
505+
webpackMap,
506+
);
507+
const response2 = ReactTransportDOMClient.createFromReadableStream(
508+
stream2.readable,
509+
);
510+
await act(async () => {
511+
root.render(
512+
<Suspense fallback={<p>(loading)</p>}>
513+
<Page response={response2} />
514+
</Suspense>,
515+
);
516+
});
517+
expect(container.children.length).toBe(1);
518+
expect(container.children[0].tagName).toBe('DIV');
519+
expect(container.children[0].style.color).toBe('blue');
520+
521+
// Verify we didn't destroy the DOM for either input.
522+
expect(inputA === container.children[0].children[0]).toBe(true);
523+
expect(inputA.tagName).toBe('INPUT');
524+
expect(inputA.value).toBe('hello');
525+
expect(inputB === container.children[0].children[1]).toBe(true);
526+
expect(inputB.tagName).toBe('INPUT');
527+
expect(inputB.value).toBe('goodbye');
528+
});
441529
});

0 commit comments

Comments
 (0)