@samitouri / QOS-React / commits / 899e3d1297

[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.');