自定义 React 挂钩在 useReducer 状态值上接收打字稿错误
Custom React hook receiving typescript error on useReducer state value
我正在尝试用 typescript 编写一个 fetch helper hook。我在下面的代码中收到一个打字稿错误,我不知道如何修复。
import * as React from 'react';
const INITIAL_STATE = {data: undefined, loading: false, error: undefined};
const ACTIONS = {
LOADING: 'LOADING',
ERROR: 'ERROR',
DONE: 'DONE',
};
interface UseApiFetch<DataType> {
data?: DataType;
error: any;
loading: boolean;
}
interface Action<DataType> {
type: string;
error?: any;
data?: DataType;
}
const reducer = <DataType>(
state: UseApiFetch<DataType>,
{type, error, data}: Action<DataType>
): UseApiFetch<DataType> => {
switch (type) {
case ACTIONS.LOADING:
return {...INITIAL_STATE, loading: true};
case ACTIONS.ERROR:
return {...INITIAL_STATE, error};
case ACTIONS.DONE:
return {...INITIAL_STATE, data};
default:
return state;
}
};
const useApiFetch = <DataType>(
fetcher: (...args: any[]) => Promise<any>,
...params: any[]
): UseApiFetch<DataType> => {
const [state, dispatch] = React.useReducer(reducer, INITIAL_STATE);
React.useEffect(() => {
if (fetcher) {
dispatch({type: ACTIONS.LOADING});
fetcher(...params)
.then((data) => dispatch({type: ACTIONS.DONE, data}))
.catch((error) => dispatch({type: ACTIONS.ERROR, error}));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [fetcher, ...params]);
/*
Error occurs here:
Type 'UseApiFetch<unknown>' is not assignable to type 'UseApiFetch<DataType>'.
Type 'unknown' is not assignable to type 'DataType'.
'DataType' could be instantiated with an arbitrary type which could be unrelated to 'unknown'.
*/
return state;
};
export default useApiFetch;
// in another file I call it like this
function myFetcherFunction(
userId: number
): Promise<MyFetcherReturnType> {
return client.api('myRequest', userId);
}
const {data, error, loading} = useApiFetch<MyFetcherReturnType>(myFetcherFunction, userId);
我认为您需要向 useReducer
添加类型。
const [state, dispatch] = React.useReducer<
(
state: UseApiFetch<DataType>,
action: Action<DataType>
) => UseApiFetch<DataType>
>(reducer, INITIAL_STATE)
type参数定义reducer函数的类型。如果没有这种类型,TypeScript 将尝试从 reducer 推断类型,但由于 reducer 是一个通用函数,TypeScript(或可能是 React)将状态类型推断为 UseApiFetch<unknown>
,因为它不能键入一个值通用类型 UseApiFetch<T>
.
理想情况下,您可以在这里重用现有类型的减速器(类似于 typeof reducer<DataType>
),但我还没有找到实现该目标的方法。
我正在尝试用 typescript 编写一个 fetch helper hook。我在下面的代码中收到一个打字稿错误,我不知道如何修复。
import * as React from 'react';
const INITIAL_STATE = {data: undefined, loading: false, error: undefined};
const ACTIONS = {
LOADING: 'LOADING',
ERROR: 'ERROR',
DONE: 'DONE',
};
interface UseApiFetch<DataType> {
data?: DataType;
error: any;
loading: boolean;
}
interface Action<DataType> {
type: string;
error?: any;
data?: DataType;
}
const reducer = <DataType>(
state: UseApiFetch<DataType>,
{type, error, data}: Action<DataType>
): UseApiFetch<DataType> => {
switch (type) {
case ACTIONS.LOADING:
return {...INITIAL_STATE, loading: true};
case ACTIONS.ERROR:
return {...INITIAL_STATE, error};
case ACTIONS.DONE:
return {...INITIAL_STATE, data};
default:
return state;
}
};
const useApiFetch = <DataType>(
fetcher: (...args: any[]) => Promise<any>,
...params: any[]
): UseApiFetch<DataType> => {
const [state, dispatch] = React.useReducer(reducer, INITIAL_STATE);
React.useEffect(() => {
if (fetcher) {
dispatch({type: ACTIONS.LOADING});
fetcher(...params)
.then((data) => dispatch({type: ACTIONS.DONE, data}))
.catch((error) => dispatch({type: ACTIONS.ERROR, error}));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [fetcher, ...params]);
/*
Error occurs here:
Type 'UseApiFetch<unknown>' is not assignable to type 'UseApiFetch<DataType>'.
Type 'unknown' is not assignable to type 'DataType'.
'DataType' could be instantiated with an arbitrary type which could be unrelated to 'unknown'.
*/
return state;
};
export default useApiFetch;
// in another file I call it like this
function myFetcherFunction(
userId: number
): Promise<MyFetcherReturnType> {
return client.api('myRequest', userId);
}
const {data, error, loading} = useApiFetch<MyFetcherReturnType>(myFetcherFunction, userId);
我认为您需要向 useReducer
添加类型。
const [state, dispatch] = React.useReducer<
(
state: UseApiFetch<DataType>,
action: Action<DataType>
) => UseApiFetch<DataType>
>(reducer, INITIAL_STATE)
type参数定义reducer函数的类型。如果没有这种类型,TypeScript 将尝试从 reducer 推断类型,但由于 reducer 是一个通用函数,TypeScript(或可能是 React)将状态类型推断为 UseApiFetch<unknown>
,因为它不能键入一个值通用类型 UseApiFetch<T>
.
理想情况下,您可以在这里重用现有类型的减速器(类似于 typeof reducer<DataType>
),但我还没有找到实现该目标的方法。