1853
assertLog(['App', 'A', 'App', 'AA', 'DefaultContext', 'Commit']);
1854
});
1855
});
1856
+
1857
+ it('regression: selective hydration does not contribute to "maximum update limit" count', async () => {
1858
+ const outsideRef = React.createRef(null);
1859
+ const insideRef = React.createRef(null);
1860
+ function Child() {
1861
+ return (
1862
+ <Suspense fallback="Loading...">
1863
+ <div ref={insideRef} />
1864
+ </Suspense>
1865
+ );
1866
+ }
1867
+
1868
+ let setIsMounted = false;
1869
+ function App() {
1870
+ const [isMounted, setState] = React.useState(false);
1871
+ setIsMounted = setState;
1872
+
1873
+ const children = [];
1874
+ for (let i = 0; i < 100; i++) {
1875
+ children.push(<Child key={i} isMounted={isMounted} />);
1876
+ }
1877
+
1878
+ return <div ref={outsideRef}>{children}</div>;
1879
+ }
1880
+
1881
+ const finalHTML = ReactDOMServer.renderToString(<App />);
1882
+ const container = document.createElement('div');
1883
+ container.innerHTML = finalHTML;
1884
+
1885
+ await act(async () => {
1886
+ ReactDOMClient.hydrateRoot(container, <App />);
1887
+
1888
+ // Commit just the shell
1889
+ await waitForPaint([]);
1890
+
1891
+ // Assert that the shell has hydrated, but not the children
1892
+ expect(outsideRef.current).not.toBe(null);
1893
+ expect(insideRef.current).toBe(null);
1894
+
1895
+ // Update the shell synchronously. The update will flow into the children,
1896
+ // which haven't hydrated yet. This will trigger a cascade of commits
1897
+ // caused by selective hydration. However, since there's really only one
1898
+ // update, it should not be treated as an update loop.
1899
+ // NOTE: It's unfortunate that every sibling boundary is separately
1900
+ // committed in this case. We should be able to commit everything in a
1901
+ // render phase, which we could do if we had resumable context stacks.
1902
+ ReactDOM.flushSync(() => {
1903
+ setIsMounted(true);
1904
+ });
1905
+ });
1906
+
1907
+ // Should have successfully hydrated with no errors.
1908
+ expect(insideRef.current).not.toBe(null);
1909
+ });
1910
});