diff --git a/src/mutation/index.ts b/src/mutation/index.ts index 2b32967d3..363c2138b 100644 --- a/src/mutation/index.ts +++ b/src/mutation/index.ts @@ -33,11 +33,16 @@ const mutation = (() => // Ditch all mutation results that happened earlier than this timestamp. const ditchMutationsUntilRef = useRef(0) - const [stateRef, stateDependencies, setState] = useStateWithDeps({ + const [stateRef, stateDependencies, setState] = useStateWithDeps<{ + data: Data | undefined + error: Error | undefined + isMutating: boolean + }>({ data: UNDEFINED, error: UNDEFINED, isMutating: false }) + const currentState = stateRef.current const trigger = useCallback( diff --git a/src/mutation/state.ts b/src/mutation/state.ts index 5a3fb7795..ea1d5c46a 100644 --- a/src/mutation/state.ts +++ b/src/mutation/state.ts @@ -11,17 +11,18 @@ export const startTransition: (scope: TransitionFunction) => void = /** * An implementation of state with dependency-tracking. + * @param initialState - The initial state object. */ -export const useStateWithDeps = ( - state: any +export const useStateWithDeps = >( + initialState: S ): [ - MutableRefObject, + MutableRefObject, Record, (payload: Partial) => void ] => { const [, rerender] = useState>({}) const unmountedRef = useRef(false) - const stateRef = useRef(state) + const stateRef = useRef(initialState) // If a state property (data, error, or isValidating) is accessed by the render // function, we mark the property as a dependency so if it is updated again @@ -31,9 +32,10 @@ export const useStateWithDeps = ( data: false, error: false, isValidating: false - } as any) + } as Record) /** + * Updates state and triggers re-render if necessary. * @param payload To change stateRef, pass the values explicitly to setState: * @example * ```js @@ -54,18 +56,21 @@ export const useStateWithDeps = ( let shouldRerender = false const currentState = stateRef.current - for (const _ in payload) { - const k = _ as keyof S + for (const key in payload) { + if (Object.prototype.hasOwnProperty.call(payload, key)) { + const k = key as keyof S - // If the property has changed, update the state and mark rerender as - // needed. - if (currentState[k] !== payload[k]) { - currentState[k] = payload[k] + // If the property has changed, update the state and mark rerender as + // needed. + if (currentState[k] !== payload[k]) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + currentState[k] = payload[k]! - // If the property is accessed by the component, a rerender should be - // triggered. - if (stateDependenciesRef.current[k]) { - shouldRerender = true + // If the property is accessed by the component, a rerender should be + // triggered. + if (stateDependenciesRef.current[k]) { + shouldRerender = true + } } } }