feat(striker-ui): add hooks to handle async cleanup

main
Tsu-ba-me 2 years ago
parent 4caaf3bdda
commit 76fa37e466
  1. 30
      striker-ui/hooks/useProtect.ts
  2. 25
      striker-ui/hooks/useProtectedState.ts

@ -0,0 +1,30 @@
import { useEffect, useRef } from 'react';
// Allow any function as callback in the protect function.
// Could be used to wrap async callbacks to prevent them from running after
// component unmount.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyFunction = (...args: any[]) => any;
type ProtectFunction = <F extends AnyFunction>(
fn: F,
...args: Parameters<F>
) => ReturnType<F>;
const useProtect = (): { protect: ProtectFunction } => {
const isComponentMountedRef = useRef<boolean>(true);
useEffect(
() => () => {
isComponentMountedRef.current = false;
},
[],
);
return {
protect: (fn, ...args) =>
isComponentMountedRef.current ? fn(...args) : undefined,
};
};
export default useProtect;

@ -0,0 +1,25 @@
import { Dispatch, SetStateAction, useState } from 'react';
type SetStateFunction<S> = Dispatch<SetStateAction<S>>;
type SetStateParameters<S> = Parameters<SetStateFunction<S>>;
type SetStateReturnType<S> = ReturnType<SetStateFunction<S>>;
const useProtectedState = <S>(
initialState: S | (() => S),
protect: (
fn: SetStateFunction<S>,
...args: SetStateParameters<S>
) => SetStateReturnType<S>,
): [S, SetStateFunction<S>] => {
const [state, setState] = useState<S>(initialState);
return [
state,
(...args: SetStateParameters<S>): SetStateReturnType<S> =>
protect(setState, ...args),
];
};
export default useProtectedState;
Loading…
Cancel
Save