@samitouri / QOS-React-2 / commits / 539527b642

Don't cut off effects at end of list if hydrating (#18872)

Sebastian Markbåge committed May 8, 2020 at 21:26 UTC 539527b642101fbfc0b4ba614d7e253905f46b08
3 files changed +62 -3
packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js
+58 -1
@@ -1699,7 +1699,7 @@ describe('ReactDOMServerPartialHydration', () => {
1699 });
1700
1701 // @gate experimental
1702 - it('clears server boundaries when SuspenseList does a second pass', async () => {
1702 + it('clears server boundaries when SuspenseList runs out of time hydrating', async () => {
1703 let suspend = false;
1704 let resolve;
1705 const promise = new Promise(resolvePromise => (resolve = resolvePromise));
@@ -1791,6 +1791,63 @@ describe('ReactDOMServerPartialHydration', () => {
1791 expect(ref.current).toBe(b);
1792 });
1793
1794 + // @gate experimental
1795 + it('clears server boundaries when SuspenseList suspends last row hydrating', async () => {
1796 + let suspend = false;
1797 + let resolve;
1798 + const promise = new Promise(resolvePromise => (resolve = resolvePromise));
1799 +
1800 + function Child({children}) {
1801 + if (suspend) {
1802 + throw promise;
1803 + } else {
1804 + return children;
1805 + }
1806 + }
1807 +
1808 + function App() {
1809 + return (
1810 + <Suspense fallback={null}>
1811 + <SuspenseList revealOrder="forwards" tail="hidden">
1812 + <Suspense fallback="Loading A">
1813 + <span>A</span>
1814 + </Suspense>
1815 + <Suspense fallback="Loading B">
1816 + <Child>
1817 + <span>B</span>
1818 + </Child>
1819 + </Suspense>
1820 + </SuspenseList>
1821 + </Suspense>
1822 + );
1823 + }
1824 +
1825 + suspend = true;
1826 + const html = ReactDOMServer.renderToString(<App />);
1827 +
1828 + const container = document.createElement('div');
1829 + container.innerHTML = html;
1830 +
1831 + const root = ReactDOM.createRoot(container, {hydrate: true});
1832 +
1833 + suspend = true;
1834 +
1835 + await act(async () => {
1836 + root.render(<App />);
1837 + });
1838 +
1839 + // We haven't hydrated the second child but the placeholder is still in the list.
1840 + expect(container.textContent).toBe('ALoading B');
1841 +
1842 + suspend = false;
1843 + await act(async () => {
1844 + // Resolve the boundary to be in its resolved final state.
1845 + await resolve();
1846 + });
1847 +
1848 + expect(container.textContent).toBe('AB');
1849 + });
1850 +
1851 // @gate experimental
1852 it('can client render nested boundaries', async () => {
1853 let suspend = false;
packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+2 -1
@@ -1098,7 +1098,8 @@ function completeWork(
1098 if (
1099 renderState.tail === null &&
1100 renderState.tailMode === 'hidden' &&
1101 - !renderedTail.alternate
1101 + !renderedTail.alternate &&
1102 + !getIsHydrating() // We don't cut it if we're hydrating.
1103 ) {
1104 // We need to delete the row we just rendered.
1105 // Reset the effect list to what it was before we rendered this
packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+2 -1
@@ -1114,7 +1114,8 @@ function completeWork(
1114 if (
1115 renderState.tail === null &&
1116 renderState.tailMode === 'hidden' &&
1117 - !renderedTail.alternate
1117 + !renderedTail.alternate &&
1118 + !getIsHydrating() // We don't cut it if we're hydrating.
1119 ) {
1120 // We need to delete the row we just rendered.
1121 // Reset the effect list to what it was before we rendered this