[crud] Narrow resource type (#32203)
Small refactor to the `resource` type to narrow it to an arbitrary object or void/null instead of the top type. This makes the overload on useEffect simpler since the return type of create is no longer widened to the top type when we merge their definitions. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32203). * #32206 * #32205 * #32204 * __->__ #32203
lauren committed
Feb 11, 2025 at 13:52 UTC
899e3d1297ec15a5aa8d73e2f1bd478918090a12
6 files changed
+54
-52
packages/react-debug-tools/src/ReactDebugHooks.js
+3
-3
@@ -739,11 +739,11 @@ function useHostTransitionStatus(): TransitionStatus {
739
}
740
741
function useResourceEffect(
742
- create: () => mixed,
742
+ create: () => {...} | void | null,
743
createDeps: Array<mixed> | void | null,
744
- update: ((resource: mixed) => void) | void,
744
+ update: ((resource: {...} | void | null) => void) | void,
745
updateDeps: Array<mixed> | void | null,
746
- destroy: ((resource: mixed) => void) | void,
746
+ destroy: ((resource: {...} | void | null) => void) | void,
747
) {
748
nextHook();
749
hookLog.push({
packages/react-reconciler/src/ReactFiberCallUserSpace.js
+1
-1
@@ -183,7 +183,7 @@ export const callComponentWillUnmountInDEV: (
183
const callCreate = {
184
'react-stack-bottom-frame': function (
185
effect: Effect,
186
- ): (() => void) | mixed | void {
186
+ ): (() => void) | {...} | void | null {
187
if (!enableUseResourceEffectHook) {
188
if (effect.resourceKind != null) {
189
if (__DEV__) {
packages/react-reconciler/src/ReactFiberCommitEffects.js
+5
-3
@@ -274,6 +274,7 @@ export function commitHookEffectListMount(
274
addendum =
275
' You returned null. If your effect does not require clean ' +
276
'up, return undefined (or nothing).';
277
+ // $FlowFixMe (@poteto) this check is safe on arbitrary non-null/void objects
278
} else if (typeof destroy.then === 'function') {
279
addendum =
280
'\n\nIt looks like you wrote ' +
@@ -1036,10 +1037,10 @@ function safelyCallDestroy(
1037
function safelyCallDestroyWithResource(
1038
current: Fiber,
1039
nearestMountedAncestor: Fiber | null,
1039
- destroy: mixed => void,
1040
- resource: mixed,
1040
+ destroy: ({...}) => void,
1041
+ resource: {...},
1042
) {
1042
- const destroy_ = resource == null ? destroy : destroy.bind(null, resource);
1043
+ const destroy_ = destroy.bind(null, resource);
1044
if (__DEV__) {
1045
runWithFiberInDEV(
1046
current,
@@ -1050,6 +1051,7 @@ function safelyCallDestroyWithResource(
1051
);
1052
} else {
1053
try {
1054
+ // $FlowFixMe(incompatible-call) Already bound to resource
1055
destroy_();
1056
} catch (error) {
1057
captureCommitPhaseError(current, nearestMountedAncestor, error);
packages/react-reconciler/src/ReactFiberHooks.js
+39
-39
@@ -205,8 +205,8 @@ export type Hook = {
205
// the additional memory and we can follow up with performance
206
// optimizations later.
207
type EffectInstance = {
208
- resource: mixed,
209
- destroy: void | (() => void) | ((resource: mixed) => void),
208
+ resource: {...} | void | null,
209
+ destroy: void | (() => void) | ((resource: {...} | void | null) => void),
210
};
211
212
export const ResourceEffectIdentityKind: 0 = 0;
@@ -229,7 +229,7 @@ export type ResourceEffectIdentity = {
229
resourceKind: typeof ResourceEffectIdentityKind,
230
tag: HookFlags,
231
inst: EffectInstance,
232
- create: () => mixed,
232
+ create: () => {...} | void | null,
233
deps: Array<mixed> | void | null,
234
next: Effect,
235
};
@@ -237,7 +237,7 @@ export type ResourceEffectUpdate = {
237
resourceKind: typeof ResourceEffectUpdateKind,
238
tag: HookFlags,
239
inst: EffectInstance,
240
- update: ((resource: mixed) => void) | void,
240
+ update: ((resource: {...} | void | null) => void) | void,
241
deps: Array<mixed> | void | null,
242
next: Effect,
243
identity: ResourceEffectIdentity,
@@ -2540,9 +2540,9 @@ function pushResourceEffect(
2540
identityTag: HookFlags,
2541
updateTag: HookFlags,
2542
inst: EffectInstance,
2543
- create: () => mixed,
2543
+ create: () => {...} | void | null,
2544
createDeps: Array<mixed> | void | null,
2545
- update: ((resource: mixed) => void) | void,
2545
+ update: ((resource: {...} | void | null) => void) | void,
2546
updateDeps: Array<mixed> | void | null,
2547
): Effect {
2548
const effectIdentity: ResourceEffectIdentity = {
@@ -2694,11 +2694,11 @@ function updateEffect(
2694
}
2695
2696
function mountResourceEffect(
2697
- create: () => mixed,
2697
+ create: () => {...} | void | null,
2698
createDeps: Array<mixed> | void | null,
2699
- update: ((resource: mixed) => void) | void,
2699
+ update: ((resource: {...} | void | null) => void) | void,
2700
updateDeps: Array<mixed> | void | null,
2701
- destroy: ((resource: mixed) => void) | void,
2701
+ destroy: ((resource: {...} | void | null) => void) | void,
2702
) {
2703
if (
2704
__DEV__ &&
@@ -2730,11 +2730,11 @@ function mountResourceEffect(
2730
function mountResourceEffectImpl(
2731
fiberFlags: Flags,
2732
hookFlags: HookFlags,
2733
- create: () => mixed,
2733
+ create: () => {...} | void | null,
2734
createDeps: Array<mixed> | void | null,
2735
- update: ((resource: mixed) => void) | void,
2735
+ update: ((resource: {...} | void | null) => void) | void,
2736
updateDeps: Array<mixed> | void | null,
2737
- destroy: ((resource: mixed) => void) | void,
2737
+ destroy: ((resource: {...} | void | null) => void) | void,
2738
) {
2739
const hook = mountWorkInProgressHook();
2740
currentlyRenderingFiber.flags |= fiberFlags;
@@ -2752,11 +2752,11 @@ function mountResourceEffectImpl(
2752
}
2753
2754
function updateResourceEffect(
2755
- create: () => mixed,
2755
+ create: () => {...} | void | null,
2756
createDeps: Array<mixed> | void | null,
2757
- update: ((resource: mixed) => void) | void,
2757
+ update: ((resource: {...} | void | null) => void) | void,
2758
updateDeps: Array<mixed> | void | null,
2759
- destroy: ((resource: mixed) => void) | void,
2759
+ destroy: ((resource: {...} | void | null) => void) | void,
2760
) {
2761
updateResourceEffectImpl(
2762
PassiveEffect,
@@ -2772,11 +2772,11 @@ function updateResourceEffect(
2772
function updateResourceEffectImpl(
2773
fiberFlags: Flags,
2774
hookFlags: HookFlags,
2775
- create: () => mixed,
2775
+ create: () => {...} | void | null,
2776
createDeps: Array<mixed> | void | null,
2777
- update: ((resource: mixed) => void) | void,
2777
+ update: ((resource: {...} | void | null) => void) | void,
2778
updateDeps: Array<mixed> | void | null,
2779
- destroy: ((resource: mixed) => void) | void,
2779
+ destroy: ((resource: {...} | void | null) => void) | void,
2780
) {
2781
const hook = updateWorkInProgressHook();
2782
const effect: Effect = hook.memoizedState;
@@ -4245,11 +4245,11 @@ if (__DEV__) {
4245
if (enableUseResourceEffectHook) {
4246
(HooksDispatcherOnMountInDEV: Dispatcher).useResourceEffect =
4247
function useResourceEffect(
4248
- create: () => mixed,
4248
+ create: () => {...} | void | null,
4249
createDeps: Array<mixed> | void | null,
4250
- update: ((resource: mixed) => void) | void,
4250
+ update: ((resource: {...} | void | null) => void) | void,
4251
updateDeps: Array<mixed> | void | null,
4252
- destroy: ((resource: mixed) => void) | void,
4252
+ destroy: ((resource: {...} | void | null) => void) | void,
4253
): void {
4254
currentHookNameInDev = 'useResourceEffect';
4255
mountHookTypesDev();
@@ -4433,11 +4433,11 @@ if (__DEV__) {
4433
if (enableUseResourceEffectHook) {
4434
(HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useResourceEffect =
4435
function useResourceEffect(
4436
- create: () => mixed,
4436
+ create: () => {...} | void | null,
4437
createDeps: Array<mixed> | void | null,
4438
- update: ((resource: mixed) => void) | void,
4438
+ update: ((resource: {...} | void | null) => void) | void,
4439
updateDeps: Array<mixed> | void | null,
4440
- destroy: ((resource: mixed) => void) | void,
4440
+ destroy: ((resource: {...} | void | null) => void) | void,
4441
): void {
4442
currentHookNameInDev = 'useResourceEffect';
4443
updateHookTypesDev();
@@ -4620,11 +4620,11 @@ if (__DEV__) {
4620
if (enableUseResourceEffectHook) {
4621
(HooksDispatcherOnUpdateInDEV: Dispatcher).useResourceEffect =
4622
function useResourceEffect(
4623
- create: () => mixed,
4623
+ create: () => {...} | void | null,
4624
createDeps: Array<mixed> | void | null,
4625
- update: ((resource: mixed) => void) | void,
4625
+ update: ((resource: {...} | void | null) => void) | void,
4626
updateDeps: Array<mixed> | void | null,
4627
- destroy: ((resource: mixed) => void) | void,
4627
+ destroy: ((resource: {...} | void | null) => void) | void,
4628
) {
4629
currentHookNameInDev = 'useResourceEffect';
4630
updateHookTypesDev();
@@ -4807,11 +4807,11 @@ if (__DEV__) {
4807
if (enableUseResourceEffectHook) {
4808
(HooksDispatcherOnRerenderInDEV: Dispatcher).useResourceEffect =
4809
function useResourceEffect(
4810
- create: () => mixed,
4810
+ create: () => {...} | void | null,
4811
createDeps: Array<mixed> | void | null,
4812
- update: ((resource: mixed) => void) | void,
4812
+ update: ((resource: {...} | void | null) => void) | void,
4813
updateDeps: Array<mixed> | void | null,
4814
- destroy: ((resource: mixed) => void) | void,
4814
+ destroy: ((resource: {...} | void | null) => void) | void,
4815
) {
4816
currentHookNameInDev = 'useResourceEffect';
4817
updateHookTypesDev();
@@ -5019,11 +5019,11 @@ if (__DEV__) {
5019
if (enableUseResourceEffectHook) {
5020
(InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useResourceEffect =
5021
function useResourceEffect(
5022
- create: () => mixed,
5022
+ create: () => {...} | void | null,
5023
createDeps: Array<mixed> | void | null,
5024
- update: ((resource: mixed) => void) | void,
5024
+ update: ((resource: {...} | void | null) => void) | void,
5025
updateDeps: Array<mixed> | void | null,
5026
- destroy: ((resource: mixed) => void) | void,
5026
+ destroy: ((resource: {...} | void | null) => void) | void,
5027
): void {
5028
currentHookNameInDev = 'useResourceEffect';
5029
warnInvalidHookAccess();
@@ -5232,11 +5232,11 @@ if (__DEV__) {
5232
if (enableUseResourceEffectHook) {
5233
(InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useResourceEffect =
5234
function useResourceEffect(
5235
- create: () => mixed,
5235
+ create: () => {...} | void | null,
5236
createDeps: Array<mixed> | void | null,
5237
- update: ((resource: mixed) => void) | void,
5237
+ update: ((resource: {...} | void | null) => void) | void,
5238
updateDeps: Array<mixed> | void | null,
5239
- destroy: ((resource: mixed) => void) | void,
5239
+ destroy: ((resource: {...} | void | null) => void) | void,
5240
) {
5241
currentHookNameInDev = 'useResourceEffect';
5242
warnInvalidHookAccess();
@@ -5445,11 +5445,11 @@ if (__DEV__) {
5445
if (enableUseResourceEffectHook) {
5446
(InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useResourceEffect =
5447
function useResourceEffect(
5448
- create: () => mixed,
5448
+ create: () => {...} | void | null,
5449
createDeps: Array<mixed> | void | null,
5450
- update: ((resource: mixed) => void) | void,
5450
+ update: ((resource: {...} | void | null) => void) | void,
5451
updateDeps: Array<mixed> | void | null,
5452
- destroy: ((resource: mixed) => void) | void,
5452
+ destroy: ((resource: {...} | void | null) => void) | void,
5453
) {
5454
currentHookNameInDev = 'useResourceEffect';
5455
warnInvalidHookAccess();
packages/react-reconciler/src/ReactInternalTypes.js
+3
-3
@@ -398,11 +398,11 @@ export type Dispatcher = {
398
useEffectEvent?: <Args, F: (...Array<Args>) => mixed>(callback: F) => F,
399
// TODO: Non-nullable once `enableUseResourceEffectHook` is on everywhere.
400
useResourceEffect?: (
401
- create: () => mixed,
401
+ create: () => {...} | void | null,
402
createDeps: Array<mixed> | void | null,
403
- update: ((resource: mixed) => void) | void,
403
+ update: ((resource: {...} | void | null) => void) | void,
404
updateDeps: Array<mixed> | void | null,
405
- destroy: ((resource: mixed) => void) | void,
405
+ destroy: ((resource: {...} | void | null) => void) | void,
406
) => void,
407
useInsertionEffect(
408
create: () => (() => void) | void,
packages/react/src/ReactHooks.js
+3
-3
@@ -202,11 +202,11 @@ export function useEffectEvent<Args, F: (...Array<Args>) => mixed>(
202
}
203
204
export function useResourceEffect(
205
- create: () => mixed,
205
+ create: () => {...} | void | null,
206
createDeps: Array<mixed> | void | null,
207
- update: ((resource: mixed) => void) | void,
207
+ update: ((resource: {...} | void | null) => void) | void,
208
updateDeps: Array<mixed> | void | null,
209
- destroy: ((resource: mixed) => void) | void,
209
+ destroy: ((resource: {...} | void | null) => void) | void,
210
): void {
211
if (!enableUseResourceEffectHook) {
212
throw new Error('Not implemented.');