'(dispatch: Dispatch<ShopDispatchTypes>) => Promise<void>' 类型的参数不可分配给 'AnyAction' 类型的参数
Argument of type '(dispatch: Dispatch<ShopDispatchTypes>) => Promise<void>' is not assignable to parameter of type 'AnyAction'
错误:
Argument of type '(dispatch: Dispatch<ShopDispatchTypes>) => Promise<void>' is not assignable to parameter of type 'AnyAction'.
useEffect(() => {
dispatch(GetShops());
}, []);
我正在尝试使用 Typescript 实现 redux-thunk。我使用 react、typescript 和 redux-thunk 创建了简单的购物卡应用程序,但遇到了上述问题。
下面是我的代码片段。如果您需要更多信息,请随时询问。
shops.actionTypes.ts
export const SHOP_LOAD_START = 'SHOP_LOAD_START';
export const SHOP_LOAD_SUCCESS = 'SHOP_LOAD_SUCCESS';
export const SHOP_LOAD_ERROR = 'SHOP_LOAD_ERROR';
export type Shop = {
id: string;
name: string;
};
export type ShopType = {
shops: Shop[];
};
export interface ShopLoadStart {
type: typeof SHOP_LOAD_START;
}
export interface ShopLoadError {
type: typeof SHOP_LOAD_ERROR;
}
export interface ShopLoadSuccess {
type: typeof SHOP_LOAD_SUCCESS;
payload: ShopType;
}
export type ShopDispatchTypes = ShopLoadStart | ShopLoadError | ShopLoadSuccess;
shops.action.ts
export const GetShops = () => async (dispatch: Dispatch<ShopDispatchTypes>) => {
try {
dispatch({
type: SHOP_LOAD_START,
});
const res = await http.get('d9b45894-2549-4e34-9486-7668c2e000a0');
dispatch({
type: SHOP_LOAD_SUCCESS,
payload: res.data,
});
} catch (e) {
dispatch({
type: SHOP_LOAD_ERROR,
});
}
};
shops.reducer.ts
export interface IDefaultState {
isLoading: boolean;
shop?: ShopType;
}
export const defaultState: IDefaultState = {
isLoading: false,
};
const shopsReducer = (
state: IDefaultState = defaultState,
action: ShopDispatchTypes
): IDefaultState => {
switch (action.type) {
case SHOP_LOAD_START:
return {
...state,
isLoading: true,
};
case SHOP_LOAD_SUCCESS:
return {
...state,
isLoading: false,
shop: action.payload,
};
case SHOP_LOAD_ERROR:
return {
...state,
isLoading: false,
};
default:
return state;
}
};
export default shopsReducer;
store.ts
const Store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(thunk))
);
export type RootStore = ReturnType<typeof rootReducer>;
export default Store;
ShoppingCard.tsx
const ShoppingCard: React.FC<IShoppingCard> = (props: IShoppingCard) => {
const { label } = props;
const dispatch = useDispatch();
const shopsData = useSelector((state: RootStore) => state.shop);
useEffect(() => {
dispatch(GetShops()); //Getting error here
}, []);
}
如果我做错了什么请告诉我。为此花了几个小时,但没有找到任何解决方案。
GitHub: Source code link
问题是 const dispatch = useDispatch();
只知道来自 redux
核心的基本 Dispatch
类型。 Dispatch
类型不知道 thunk 的存在——它只接受普通的动作对象。因此,当您尝试发送 thunk 时,它(正确地)出错了。
解决方法是遵循我们的“使用 TS”指南,从 store.dispatch
正确推断出 AppDispatch
类型,然后定义 pre-typed 包含 thunk 类型的挂钩:
https://redux.js.org/tutorials/typescript-quick-start
此外,虽然它与问题没有直接关系:您使用的“hand-written”Redux 模式非常过时,而不是我们今天希望人们使用 Redux 的方式。相反,我们现在教授一组更容易学习和使用的“现代 Redux”模式 - Redux Toolkit for logic + React-Redux hooks。今天,我们的官方文档教程将 RTK+hooks 作为标准 Redux 进行教学,但大多数其他教程都已经过时了。请参阅我们的官方文档以了解如何使用 Redux Toolkit,这将大大简化您那里的代码:
错误:
Argument of type '(dispatch: Dispatch<ShopDispatchTypes>) => Promise<void>' is not assignable to parameter of type 'AnyAction'.
useEffect(() => {
dispatch(GetShops());
}, []);
我正在尝试使用 Typescript 实现 redux-thunk。我使用 react、typescript 和 redux-thunk 创建了简单的购物卡应用程序,但遇到了上述问题。 下面是我的代码片段。如果您需要更多信息,请随时询问。
shops.actionTypes.ts
export const SHOP_LOAD_START = 'SHOP_LOAD_START';
export const SHOP_LOAD_SUCCESS = 'SHOP_LOAD_SUCCESS';
export const SHOP_LOAD_ERROR = 'SHOP_LOAD_ERROR';
export type Shop = {
id: string;
name: string;
};
export type ShopType = {
shops: Shop[];
};
export interface ShopLoadStart {
type: typeof SHOP_LOAD_START;
}
export interface ShopLoadError {
type: typeof SHOP_LOAD_ERROR;
}
export interface ShopLoadSuccess {
type: typeof SHOP_LOAD_SUCCESS;
payload: ShopType;
}
export type ShopDispatchTypes = ShopLoadStart | ShopLoadError | ShopLoadSuccess;
shops.action.ts
export const GetShops = () => async (dispatch: Dispatch<ShopDispatchTypes>) => {
try {
dispatch({
type: SHOP_LOAD_START,
});
const res = await http.get('d9b45894-2549-4e34-9486-7668c2e000a0');
dispatch({
type: SHOP_LOAD_SUCCESS,
payload: res.data,
});
} catch (e) {
dispatch({
type: SHOP_LOAD_ERROR,
});
}
};
shops.reducer.ts
export interface IDefaultState {
isLoading: boolean;
shop?: ShopType;
}
export const defaultState: IDefaultState = {
isLoading: false,
};
const shopsReducer = (
state: IDefaultState = defaultState,
action: ShopDispatchTypes
): IDefaultState => {
switch (action.type) {
case SHOP_LOAD_START:
return {
...state,
isLoading: true,
};
case SHOP_LOAD_SUCCESS:
return {
...state,
isLoading: false,
shop: action.payload,
};
case SHOP_LOAD_ERROR:
return {
...state,
isLoading: false,
};
default:
return state;
}
};
export default shopsReducer;
store.ts
const Store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(thunk))
);
export type RootStore = ReturnType<typeof rootReducer>;
export default Store;
ShoppingCard.tsx
const ShoppingCard: React.FC<IShoppingCard> = (props: IShoppingCard) => {
const { label } = props;
const dispatch = useDispatch();
const shopsData = useSelector((state: RootStore) => state.shop);
useEffect(() => {
dispatch(GetShops()); //Getting error here
}, []);
}
如果我做错了什么请告诉我。为此花了几个小时,但没有找到任何解决方案。
GitHub: Source code link
问题是 const dispatch = useDispatch();
只知道来自 redux
核心的基本 Dispatch
类型。 Dispatch
类型不知道 thunk 的存在——它只接受普通的动作对象。因此,当您尝试发送 thunk 时,它(正确地)出错了。
解决方法是遵循我们的“使用 TS”指南,从 store.dispatch
正确推断出 AppDispatch
类型,然后定义 pre-typed 包含 thunk 类型的挂钩:
https://redux.js.org/tutorials/typescript-quick-start
此外,虽然它与问题没有直接关系:您使用的“hand-written”Redux 模式非常过时,而不是我们今天希望人们使用 Redux 的方式。相反,我们现在教授一组更容易学习和使用的“现代 Redux”模式 - Redux Toolkit for logic + React-Redux hooks。今天,我们的官方文档教程将 RTK+hooks 作为标准 Redux 进行教学,但大多数其他教程都已经过时了。请参阅我们的官方文档以了解如何使用 Redux Toolkit,这将大大简化您那里的代码: