abd*_*hab 4 typescript reactjs react-redux redux-toolkit
Redux 工具包提供了createAction辅助方法。我在引用使用createActionas 类型创建的操作时遇到问题。
例如:
const getData = createAction<PayloadAction<number>>('user/getData')
function* exampleSaga(action: ?) {
...
}
Run Code Online (Sandbox Code Playgroud)
我怎么能说exampleSaga那action是类型getData?
要了解我是如何尝试这样做的,请参考以下(示例)代码并查看我面临的问题的评论:
减速机.ts
import { createAction, PayloadAction } from '@reduxjs/toolkit';
export const getData = createAction<PayloadAction<number>>('user/getData');
const userSlice = createSlice({
name: userSliceName,
initialState,
reducers: {
getUser(state: IUserState): void {
state.loading = true;
state.error = null;
},
getUserSuccess(state: IUserState, action: PayloadAction<{ user: IUser }>): void {
const { user } = action.payload;
state.user = user;
state.loading = false;
state.error = null;
},
getUserFailure(state: IUserState, action: PayloadAction<string>): void {
state.loading = false;
state.error = action.payload;
},
},
});
export type UserSaga = Generator<
| CallEffect<IUser>
| PutEffect<typeof getUserSuccess>
| PutEffect<typeof getUserFailure>
| ForkEffect<never>
>;
Run Code Online (Sandbox Code Playgroud)
sagas.ts
import { UserSaga, getData } from './reducer.ts';
// For the following fetchUser saga arguments, how can I define that 'action' is of type getData, imported from the above 'reducer.ts' file.
function* fetchUser(action: PayloadAction<typeof getData>): UserSaga {
try {
const userId = action.payload;
// Problem is here
// I expect userId to be of type number, whereas it is:
// ActionCreatorWithPayload<{payload: number, type: string}>
...
} catch (e) {
...
}
}
function* userSaga(): UserSaga {
const pattern: any = getData.type;
yield takeLatest(pattern, fetchUser);
}
Run Code Online (Sandbox Code Playgroud)
我做了更多的挖掘,这就是我解决这个问题的方法。
可以在不将其绑定到SliceCaseReducer 的情况下创建动作:(请注意,getData下面创建的不是Action本身,而是ActionCreator)。
常见的.ts
import { createAction } from '@reduxjs/toolkit';
export const getData = createAction<number>('getData');
Run Code Online (Sandbox Code Playgroud)
getData 如果给定正确的有效负载,则已经煮熟以从 FunctionComponent 分派:
组件.tsx
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { useParams } from 'react-router';
import { getData } from './state/common';
const User: React.FC = (): React.ReactElement => {
const { userId } = useParams();
const dispatch = useDispatch();
useEffect((): void => {
dispatch(getData(Number(userId)));
}, []);
return (<>User Component</>);
};
export default UserContainer;
Run Code Online (Sandbox Code Playgroud)
Saga Effects 接受要反应的动作的字符串类型。幸运的是,actionCreator暴露了一个type属性,表示已定义的动作字符串名称。
saga.ts(侦听器)
import { takeLatest } from 'redux-saga/effects';
import { getData } from './common';
function* userSaga() {
// getData.type could be input to a Saga Effect
yield takeLatest(getData.type, fetchUser); // fetchUser is a worker saga explained below
}
Run Code Online (Sandbox Code Playgroud)
将动作指定为 saga 的参数有点棘手,我们必须使用 TypeScript 的Type Guards。有趣的是,redux-toolkit 的文档中也提到了它。简而言之,我们必须使用actionCreator.matchactionCreator 的方法将传递的动作区分为所需的类型。因此,在区分之后,我们会收到匹配操作的有效负载所需的静态类型。
saga.ts(工人)
import { Action } from '@reduxjs/toolkit';
import { call, put } from 'redux-saga/effects';
import * as userApi from '../../../api/user-api';
import { getData } from './common';
import { getUserSuccess, getUserFailure } from './user';
// Note that we can't directly specify that fetchUser only accepts getData action type.
function* fetchUser(action: Action) {
try {
// getData.match could be used to assert that we are only concerned with getData action type
if (getData.match(action)) {
// Inside the body of if, we get correct static typing
const userId = action.payload;
const fetchedUser = yield call(userApi.getUser, userId);
yield put(getUserSuccess({user: fetchedUser}));
}
} catch (e) {
yield put(getUserFailure(e.message));
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
This is how you will get it using return type of your getData.
function* exampleSaga(action: ReturnType<typeof getData>) {
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3452 次 |
| 最近记录: |