@samitouri / QOS-React-2 / commits / ec38def44f

[Fresh] Don't traverse remounted trees (#15685)

* Don't traverse children when hot reloading needs a remount If we're gonna remount that tree anyway, there is no use in traversing its children beforehand. * Add a test verifying hot reload batches updates Otherwise there is a risk of it being super slow due to cascades.

Dan Abramov committed May 20, 2019 at 14:55 UTC ec38def44f2ff696ec0b73c212265fd2324bcdaf
2 files changed +53 -7
packages/react-dom/src/__tests__/ReactFresh-test.internal.js
+41
@@ -1549,6 +1549,47 @@ describe('ReactFresh', () => {
1549 }
1550 });
1551
1552 + it('batches re-renders during a hot update', () => {
1553 + if (__DEV__) {
1554 + let helloRenders = 0;
1555 +
1556 + render(() => {
1557 + function Hello({children}) {
1558 + helloRenders++;
1559 + return <div>X{children}X</div>;
1560 + }
1561 + __register__(Hello, 'Hello');
1562 +
1563 + function App() {
1564 + return (
1565 + <Hello>
1566 + <Hello>
1567 + <Hello />
1568 + </Hello>
1569 + <Hello>
1570 + <Hello />
1571 + </Hello>
1572 + </Hello>
1573 + );
1574 + }
1575 + return App;
1576 + });
1577 + expect(helloRenders).toBe(5);
1578 + expect(container.textContent).toBe('XXXXXXXXXX');
1579 + helloRenders = 0;
1580 +
1581 + patch(() => {
1582 + function Hello({children}) {
1583 + helloRenders++;
1584 + return <div>O{children}O</div>;
1585 + }
1586 + __register__(Hello, 'Hello');
1587 + });
1588 + expect(helloRenders).toBe(5);
1589 + expect(container.textContent).toBe('OOOOOOOOOO');
1590 + }
1591 + });
1592 +
1593 it('does not leak state between components', () => {
1594 if (__DEV__) {
1595 const AppV1 = render(
packages/react-reconciler/src/ReactFiberHotReloading.js
+12 -7
@@ -224,29 +224,34 @@ function scheduleFibersWithFamiliesRecursively(
224 throw new Error('Expected familiesByType to be set during hot reload.');
225 }
226
227 + let needsRender = false;
228 + let needsRemount = false;
229 if (candidateType !== null) {
230 const family = familiesByType.get(candidateType);
231 if (family !== undefined) {
232 if (staleFamilies.has(family)) {
231 - fiber._debugNeedsRemount = true;
232 - scheduleWork(fiber, Sync);
233 + needsRemount = true;
234 } else if (updatedFamilies.has(family)) {
234 - scheduleWork(fiber, Sync);
235 + needsRender = true;
236 }
237 }
238 }
238 -
239 if (failedBoundaries !== null) {
240 if (
241 failedBoundaries.has(fiber) ||
242 (alternate !== null && failedBoundaries.has(alternate))
243 ) {
244 - fiber._debugNeedsRemount = true;
245 - scheduleWork(fiber, Sync);
244 + needsRemount = true;
245 }
246 }
247
249 - if (child !== null) {
248 + if (needsRemount) {
249 + fiber._debugNeedsRemount = true;
250 + }
251 + if (needsRemount || needsRender) {
252 + scheduleWork(fiber, Sync);
253 + }
254 + if (child !== null && !needsRemount) {
255 scheduleFibersWithFamiliesRecursively(
256 child,
257 updatedFamilies,