Report refreshed families to the caller (#15957)
Dan Abramov committed
Jun 22, 2019 at 23:57 UTC
39b97e8eb87b2b3b0d938660e1ac12223470fdf5
3 files changed
+41
-9
packages/react-refresh/src/ReactFreshRuntime.js
+8
-7
@@ -142,10 +142,10 @@ function resolveFamily(type) {
142
return familiesByType.get(type);
143
}
144
145
-export function performReactRefresh(): boolean {
145
+export function performReactRefresh(): RefreshUpdate | null {
146
if (__DEV__) {
147
if (pendingUpdates.length === 0) {
148
- return false;
148
+ return null;
149
}
150
151
const staleFamilies = new Set();
@@ -169,9 +169,10 @@ export function performReactRefresh(): boolean {
169
}
170
});
171
172
+ // TODO: rename these fields to something more meaningful.
173
const update: RefreshUpdate = {
173
- updatedFamilies,
174
- staleFamilies,
174
+ updatedFamilies, // Families that will re-render preserving state
175
+ staleFamilies, // Families that will be remounted
176
};
177
178
if (typeof setRefreshHandler !== 'function') {
@@ -182,7 +183,7 @@ export function performReactRefresh(): boolean {
183
'called before the global DevTools hook was set up, or after the ' +
184
'renderer has already initialized. Please file an issue with a reproducing case.',
185
);
185
- return false;
186
+ return null;
187
}
188
189
if (typeof scheduleRefresh !== 'function') {
@@ -193,7 +194,7 @@ export function performReactRefresh(): boolean {
194
'called before the global DevTools hook was set up, or after the ' +
195
'renderer has already initialized. Please file an issue with a reproducing case.',
196
);
196
- return false;
197
+ return null;
198
}
199
const scheduleRefreshForRoot = scheduleRefresh;
200
@@ -217,7 +218,7 @@ export function performReactRefresh(): boolean {
218
if (didError) {
219
throw firstError;
220
}
220
- return true;
221
+ return update;
222
} else {
223
throw new Error(
224
'Unexpected call to React Refresh in a production environment.',
packages/react-refresh/src/__tests__/ReactFresh-test.js
+31
@@ -3266,4 +3266,35 @@ describe('ReactFresh', () => {
3266
)(global, React, ReactFreshRuntime, expect, createReactClass);
3267
}
3268
});
3269
+
3270
+ it('reports updated and remounted families to the caller', () => {
3271
+ if (__DEV__) {
3272
+ const HelloV1 = () => {
3273
+ const [val, setVal] = React.useState(0);
3274
+ return (
3275
+ <p style={{color: 'blue'}} onClick={() => setVal(val + 1)}>
3276
+ {val}
3277
+ </p>
3278
+ );
3279
+ };
3280
+ $RefreshReg$(HelloV1, 'Hello');
3281
+
3282
+ const HelloV2 = () => {
3283
+ const [val, setVal] = React.useState(0);
3284
+ return (
3285
+ <p style={{color: 'red'}} onClick={() => setVal(val + 1)}>
3286
+ {val}
3287
+ </p>
3288
+ );
3289
+ };
3290
+ $RefreshReg$(HelloV2, 'Hello');
3291
+
3292
+ const update = ReactFreshRuntime.performReactRefresh();
3293
+ expect(update.updatedFamilies.size).toBe(1);
3294
+ expect(update.staleFamilies.size).toBe(0);
3295
+ const family = update.updatedFamilies.values().next().value;
3296
+ expect(family.current.name).toBe('HelloV2');
3297
+ // For example, we can use this to print a log of what was updated.
3298
+ }
3299
+ });
3300
});
packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js
+2
-2
@@ -82,13 +82,13 @@ describe('ReactFreshIntegration', () => {
82
ReactDOM.render(<Component />, container);
83
});
84
// Module initialization shouldn't be counted as a hot update.
85
- expect(ReactFreshRuntime.performReactRefresh()).toBe(false);
85
+ expect(ReactFreshRuntime.performReactRefresh()).toBe(null);
86
}
87
88
function patch(source) {
89
execute(source);
90
act(() => {
91
- expect(ReactFreshRuntime.performReactRefresh()).toBe(true);
91
+ expect(ReactFreshRuntime.performReactRefresh()).not.toBe(null);
92
});
93
expect(ReactFreshRuntime._getMountedRootCount()).toBe(1);
94
}