首页 > 解决方案 > 如何构建通用打字稿自定义钩子?

问题描述

我有一个 React Hook,它以多种形式用于从 API 调用中获取数据。目标 URL 是使用挂钩的参数定义的。返回的对象可能是几种类型之一,具体取决于使用钩子的组件,我在下面包含了一个摘录:

export const useFormControl = (
    feature: Feature,
    id?: string,
) => {

    const [{ data, error, loading}] = useAxios({
        url: `https://this.is.the.url?feature=feature&id=id`,
    });

    ...

    return {
        data,
        error,
        loading,
        ...
    } as const;
};

我正在使用如下效果:

const FormType1 = {
   prop1 : string;
   prop2: string
}

export const Form = ({ ... }: FormProps) => {

    const [formData, setFormData] = useState<FormType1>();

    const {
        data,
        error,
        loading,
        ...
    } = useFormControl(mode,id);

    
    useEffect(() => {
        if (data) {
            setFormData(data as FormType );
        }
    }, [formData]);

    // use formData here...
}

这种模式重复了很多次。我宁愿不必在每个组件中都有一个 useEffect 使用钩子将传入的数据转换为该表单的 FormType。有没有办法使用泛型来“键入”自定义钩子,以便 useAxios 钩子的数据可以是正确的类型?

标签: reactjstypescriptgenericsaxiosreact-hooks

解决方案


我在这里使用答案解决了这个问题:Custom Hook with Generic Types TypeScript

将钩子更改为具有类型化接口的函数。

interface ReturnedData<TResponse> {
    data: TResponse;
    error: AxiosError<any> | undefined;
    loading: boolean;
    ...
}
 
export function useFormControl<T> = (
    feature: Feature,
    id?: string,
 ):ReturnedData<T> => {

    const [{ data, error, loading}] = useAxios<T>({
        url: `https://this.is.the.url?feature=feature&id=id`,
    });

    ...

    return {
        data,
        error,
        loading,
        ...
    } as const;
};

然后用作:

const {
    data,
    error,
    loading,
    ...
} = useFormControl<FormType>(mode,id);

推荐阅读