有问题请教老师
来源:9-7 【中间件】使用redux-thunk中间价实现异步action

粉墨登场
2021-11-29
老师您好,在使用中间件时有两个问题不太明白,要请教一下老师。
第一个:关于 ThunkAction 的四个泛型参数的类型定义(第一个代码片段)
-
ThunkAction<函数返回类型, store的类型, 参数的类型, 要使用到的 action 的类型>
其中 函数返回类型 指的是第二个函数的返回类型吗?也就是如下代码中 return () => {} 这个函数吗? -
参数的类型 我尝试定义为 boolean,但是入参的类型明显是string,却没有报错,因此疑惑这里的参数到底是哪一个函数的参数呢?以及对于这四个泛型参数的大白话解释是否有偏差呢?
第二个问题:在类组件中使用这个中间件时报错了,报错信息是缺少 type,但是函数组件中没有问题,并且可以正常调用。(第二个代码片段)
我尝试在dispatch 时加上类型断言为 any
dispatch(changeLanguage_thunk(code) as any); 这样就不报错了。但是不知道是什么原因导致类型错误?
// 切换语言的中间件,在这里将语言切换掉
export const changeLanguage_thunk = (
languageCode: 'zh' | 'en'
): ThunkAction<void, RootStoreType, boolean, languageActionsType> => {
return (dispatch, getState) => {
i18n.changeLanguage(languageCode);
dispatch(changeLanguageActionCreator(languageCode));
};
};
类组件中类型报错的代码
调用
handleClickMenu = (ev) => {
const { addLanguage, changeLanguage_thunk } = this.props;
// 添加新的语言配置项
if (ev.key === 'addMenuItem') {
addLanguage({ name: '新的语言', code: 'newLanguage' });
// 更改当前显示的语言
} else {
changeLanguage_thunk(ev.key);
};
};
HOC高阶组件中的 dispatch 定义
// disptach action 的函数
const mapDispatchToProps = (dispatch: Dispatch) => {
// 返回一个对象,key值是 action 的名字,值是对应的 action 函数
return {
changeLanguage_thunk (code: 'zh' | 'en') {
dispatch(changeLanguage_thunk(code));
},
addLanguage: (code: { name: string; code: string; }) => {
const action = addLanguageActionCreator(code);
dispatch(action);
}
};
};
类型报错的截图
写回答
1回答
-
阿莱克斯刘
2025-01-22
### 问题 1:ThunkAction 的四个泛型参数
`ThunkAction` 的定义如下:
```typescript
ThunkAction<R, S, E, A>
```
- **R**: 函数返回类型 (Thunk 返回的函数的返回类型)。
- **S**: store 的类型 (RootState 的类型)。
- **E**: 额外的参数类型 (通常用不到,可以用 `null` 或 `unknown`)。
- **A**: 要使用到的 action 的类型。
在你的代码中:
```typescript
export const changeLanguage_thunk = (
languageCode: 'zh' | 'en'
): ThunkAction<void, RootStoreType, boolean, languageActionsType> => {
return (dispatch, getState) => {
i18n.changeLanguage(languageCode);
dispatch(changeLanguageActionCreator(languageCode));
};
};
```
- **R**: `void`(因为返回的 thunk 函数没有返回值)
- **S**: `RootStoreType`(store 的类型)
- **E**: `boolean`(额外的参数类型,不过在 thunk 中并未使用这个参数)
- **A**: `languageActionsType`(action 的类型)
### 参数的类型
如果你定义 `E` 为 `boolean`,而实际传递的参数是 `string`,那么这显然不匹配,可能是因为该参数并未被实际使用导致 TypeScript 没有报错。因此你可以将这个参数设为 `unknown` 或 `null`。
### 问题 2:类组件中 dispatch 报错
你提到在类组件中使用时出现了类型报错。通常是因为 TypeScript 的类型定义未能正确推断出 action 的类型。
### 解决方法
1. **确保 action 类型正确**:
确保你的 action 类型定义是正确且完整的。
2. **改进类型定义**:
在 dispatch 中添加类型断言或者明确 action 的类型。
```typescript
const mapDispatchToProps = (dispatch: Dispatch) => {
return {
changeLanguage_thunk: (code: 'zh' | 'en') => {
dispatch(changeLanguage_thunk(code) as ThunkAction<void, RootStoreType, unknown, AnyAction>);
},
addLanguage: (code: { name: string; code: string; }) => {
const action = addLanguageActionCreator(code);
dispatch(action);
}
};
};
```
3. **使用 `bindActionCreators`**:
使用 Redux 提供的 `bindActionCreators` 可以简化 action 和 dispatch 的绑定,并解决类型问题。
```typescript
import { bindActionCreators } from 'redux';
const mapDispatchToProps = (dispatch: Dispatch) =>
bindActionCreators({
changeLanguage_thunk,
addLanguage
}, dispatch);
```
### 示例改进
```typescript
class MyComponent extends React.Component {
handleClickMenu = (ev) => {
const { addLanguage, changeLanguage_thunk } = this.props;
if (ev.key === 'addMenuItem') {
addLanguage({ name: '新的语言', code: 'newLanguage' });
} else {
changeLanguage_thunk(ev.key as 'zh' | 'en');
}
};
render() {
return (
<button onClick={this.handleClickMenu}>Change Language</button>
);
}
}
const mapDispatchToProps = (dispatch: Dispatch) => ({
changeLanguage_thunk: (code: 'zh' | 'en') => dispatch(changeLanguage_thunk(code)),
addLanguage: (code: { name: string; code: string; }) => dispatch(addLanguageActionCreator(code))
});
```
这样可以确保你在类组件中使用中间件时不会报错。00
相似问题