网站搜索

reactjs - 我如何构建一个通用的 TypeScript 自定义 Hook?


我有一个 React Hook,它用于多个表单中从 API 调用获取数据。目标 URL 是使用传递给 hook 的参数定义的。返回的对象可能根据使用该 hook 的组件而属于几种类型之一,我在下面提供了一个摘录:

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...
}

这个模式重复了很多次。我更希望不必在每个使用该 hook 的组件中都使用 useEffect 来将传入数据转换为该表单的 FormType。有没有办法使用泛型来“类型化”自定义 hook,这样 useAxios hook 的数据就可以是正确的类型?

答案#1

我使用这里的一个答案解决了这个问题:TypeScript 中带有泛型类型的自定义 Hook

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

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);