store.ts
export const store = configureStore({
reducer: {
auth: authReducer
},
middleware: [],
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
hooks.ts
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
authSlice.ts(导致问题的函数)
export const fetchUser = createAsyncThunk(
'users/fetchByTok',
async () => {
const res = await getUser();
return res.data;
}
)
Auth.ts
const Auth = ({ component, isLogged }: {component: any, isLogged: boolean}) => {
const dispatch = useAppDispatch();
useEffect(() => {
dispatch(fetchUser()) // <----------- ERROR
}, []);
return isLogged ? component : <Navigate to='/sign-in' replace={true} />;
}
export default Auth;
我有一个createAsyncThunk函数来获取用户,但我实际上无法将它放入dispatch()中...
AppDispatch
添加到
useDispatch
钩子类型即可解决;
const dispatch = useDispatch<AppDispatch>();
useEffect(() => {
dispatch(getUsers());
}, []);
getUsers() 是我的 createAsyncThunk
函数
store.dispatch
的类型,我也更喜欢。
在这里,如果由于某种原因您无法通过推理解决它,我想建议使用显式类型定义的替代方案(这可能发生在较大的项目等中)
所以这里的想法是使用支持 thunk 操作的更新的调度类型来显式定义 Redux 存储的类型。使用显式类型声明的解决方案
// your redux store config file.
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import reducers from "./path/to/reducers";
// ... your code
// 1. Get the root state's type from reducers
export type RootState = ReturnType<typeof reducers>;
// 2. Create a type for thunk dispatch
export type AppThunkDispatch = ThunkDispatch<RootState, any, AnyAction>;
// 3. Create a type for store using RootState and Thunk enabled dispatch
export type AppStore = Omit<Store<RootState, AnyAction>, "dispatch"> & {
dispatch: AppThunkDispatch;
};
//4. create the store with your custom AppStore
export const store: AppStore = configureStore();
// you can also create some redux hooks using the above explicit types
export const useAppDispatch = () => useDispatch<AppThunkDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
使用上述方法,您还可以使用 store.dispatch
来分派异步 thunk 操作(在编写测试时可能会有所帮助)或使用
useAppDispatch
挂钩或使用
connect
中的旧式
react-redux
消费者功能。它会在所有情况下为您提供正确的类型。
我个人大多数时候更喜欢推理类型声明,但有时由于外部或内部原因我们别无选择。
希望这个答案对您有所帮助。谢谢你:)
所以使用
concat
...
const store = configureStore({
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(FooApi.middleware, apiErrorMiddleware),
...rest_of_the_config,
});
...而不是分散数组...
const store = configureStore({
middleware: (getDefaultMiddleware) =>
[...getDefaultMiddleware(), FooApi.middleware, apiErrorMiddleware],
...rest_of_the_config,
});
import {ThunkDispatch} from "@reduxjs/toolkit";
const dispatch = useDispatch<ThunkDispatch<any, any, any>>();
const dispatch = useDispatch();
与:
const dispatch = useDispatch<any>();
编辑!
由于评论中提到redux工具包实际上默认添加了Thunk,因此Phry的答案更准确。我无法删除已接受的答案,因此此编辑就足够了。
我提供的答案将删除自动添加的其他中间件!
问题在于您实际上缺少存储配置内的 thunk 中间件。只需添加thunkMiddleware
的导入并将其添加到配置中的
middleware
数组中即可。由于未添加中间件,调度不会接受 Thunk Action,因为 redux 不支持开箱即用。
import thunkMiddleware from 'redux-thunk';
export const store = configureStore({
reducer: {
auth: authReducer
},
middleware: [thunkMiddleware],
});
尝试在 redux 存储配置文件或根文件 - app.js/index.js 中添加此导入语句,或者如果是下一个 js - _app.js 在页面目录中。
例如:store.js
import { configureStore } from "@reduxjs/toolkit";
import rootReducer from "./reducers";
import * as reduxThunk from "redux-thunk/extend-redux";
export const store = configureStore({
reducer: rootReducer,
});
export default store;
redux
,那么会出现这样的常见 TS 问题。
对于很多人来说,卸载并重新安装
node_modules
或react-redux
似乎可以解决问题。
否则,您的捆绑程序可能会帮助您找到问题的根源(
@types/react-redux
或npm ls redux
,如果您使用的是这两者之一)。您已在商店配置中将默认中间件替换为空数组。所以,你的应用程序没有 redux-thunk。
yarn why redux
然后将此数组添加到配置对象中。
如果你没有任何中间件,不要将其添加为空数组,只需将其删除即可。
const middleware = [
...getDefaultMiddleware(),
/* custom middlewares */
];
concat
切勿使用扩展运算符来合并中间件。 Spread 运算符不会保留类型,但 middleware: getDefaultMiddleware => getDefaultMiddleware().concat(yourMiddleware)
方法会保留。我想出了我的情况,如果你使用
configureStore
并想使用中间件,那么你不能像这样写一些想法:
'@reduxjs/toolkit'
而不是这个,你应该使用这个:export const store = configureStore({
reducer: {
r1: r1Reducer,
},
devTools: true,
middleware: [
reduxLogger
],
});
或使用
@andrewnosov对我来说这是打字稿的问题,根据文档添加
在createAsyncThunk()
store.ts
在export type AppDispatch = typeof store.dispatch
hooks.ts
在export const useAppDispatch: () => AppDispatch = useDispatch
yourComponent.tsx