[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.
This commit is contained in:
Dan Abramov
2019-05-20 14:55:01 +01:00
committed by GitHub
parent 5731e522d4
commit ec38def44f
2 changed files with 53 additions and 7 deletions
@@ -1549,6 +1549,47 @@ describe('ReactFresh', () => {
}
});
it('batches re-renders during a hot update', () => {
if (__DEV__) {
let helloRenders = 0;
render(() => {
function Hello({children}) {
helloRenders++;
return <div>X{children}X</div>;
}
__register__(Hello, 'Hello');
function App() {
return (
<Hello>
<Hello>
<Hello />
</Hello>
<Hello>
<Hello />
</Hello>
</Hello>
);
}
return App;
});
expect(helloRenders).toBe(5);
expect(container.textContent).toBe('XXXXXXXXXX');
helloRenders = 0;
patch(() => {
function Hello({children}) {
helloRenders++;
return <div>O{children}O</div>;
}
__register__(Hello, 'Hello');
});
expect(helloRenders).toBe(5);
expect(container.textContent).toBe('OOOOOOOOOO');
}
});
it('does not leak state between components', () => {
if (__DEV__) {
const AppV1 = render(
+12 -7
View File
@@ -224,29 +224,34 @@ function scheduleFibersWithFamiliesRecursively(
throw new Error('Expected familiesByType to be set during hot reload.');
}
let needsRender = false;
let needsRemount = false;
if (candidateType !== null) {
const family = familiesByType.get(candidateType);
if (family !== undefined) {
if (staleFamilies.has(family)) {
fiber._debugNeedsRemount = true;
scheduleWork(fiber, Sync);
needsRemount = true;
} else if (updatedFamilies.has(family)) {
scheduleWork(fiber, Sync);
needsRender = true;
}
}
}
if (failedBoundaries !== null) {
if (
failedBoundaries.has(fiber) ||
(alternate !== null && failedBoundaries.has(alternate))
) {
fiber._debugNeedsRemount = true;
scheduleWork(fiber, Sync);
needsRemount = true;
}
}
if (child !== null) {
if (needsRemount) {
fiber._debugNeedsRemount = true;
}
if (needsRemount || needsRender) {
scheduleWork(fiber, Sync);
}
if (child !== null && !needsRemount) {
scheduleFibersWithFamiliesRecursively(
child,
updatedFamilies,