[Fast Refresh] Fix for intentional unmounts after an error (#17368)
Ricky committed
Nov 14, 2019 at 18:40 UTC
769dd522a2f6843f7e22d903fce296cb9faab88b
2 files changed
+40
packages/react-refresh/src/ReactFreshRuntime.js
+4
@@ -468,6 +468,10 @@ export function injectIntoGlobalHook(globalObject: any): void {
468
// TODO: Maybe we could fix this as the same time as when we fix
469
// DevTools to not depend on `alternate.memoizedState.element`.
470
didSomeRootFailOnMount = true;
471
+ } else if (!didError && failedRoots.has(root)) {
472
+ // The error is fixed but the component is still unmounted.
473
+ // This means that the unmount was not caused by a failed refresh.
474
+ failedRoots.delete(root);
475
}
476
}
477
} else {
packages/react-refresh/src/__tests__/ReactFresh-test.js
+36
@@ -2870,6 +2870,42 @@ describe('ReactFresh', () => {
2870
});
2871
expect(container.innerHTML).toBe('');
2872
expect(ReactFreshRuntime.hasUnrecoverableErrors()).toBe(false);
2873
+
2874
+ // Mount a new container.
2875
+ render(() => {
2876
+ function Hello() {
2877
+ return <h1>Hi</h1>;
2878
+ }
2879
+ $RefreshReg$(Hello, 'Hello');
2880
+
2881
+ return Hello;
2882
+ });
2883
+ expect(container.innerHTML).toBe('<h1>Hi</h1>');
2884
+ expect(ReactFreshRuntime.hasUnrecoverableErrors()).toBe(false);
2885
+
2886
+ // Break again.
2887
+ expect(() => {
2888
+ patch(() => {
2889
+ function Hello() {
2890
+ throw new Error('Oops');
2891
+ }
2892
+ $RefreshReg$(Hello, 'Hello');
2893
+ });
2894
+ }).toThrow('Oops');
2895
+ expect(container.innerHTML).toBe('');
2896
+ expect(ReactFreshRuntime.hasUnrecoverableErrors()).toBe(false);
2897
+
2898
+ // Check we don't attempt to reverse an intentional unmount, even after an error.
2899
+ ReactDOM.unmountComponentAtNode(container);
2900
+ expect(container.innerHTML).toBe('');
2901
+ patch(() => {
2902
+ function Hello() {
2903
+ return <h1>Never mind me!</h1>;
2904
+ }
2905
+ $RefreshReg$(Hello, 'Hello');
2906
+ });
2907
+ expect(container.innerHTML).toBe('');
2908
+ expect(ReactFreshRuntime.hasUnrecoverableErrors()).toBe(false);
2909
}
2910
});
2911