Skip to content

Commit 39734ee

Browse files
committed
Failing test for Client reconciliation
1 parent ad6f3d5 commit 39734ee

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

0 commit comments

Comments
 (0)