有问题请教老师

来源:9-7 【中间件】使用redux-thunk中间价实现异步action

粉墨登场

2021-11-29

老师您好,在使用中间件时有两个问题不太明白,要请教一下老师。
第一个:关于 ThunkAction 的四个泛型参数的类型定义(第一个代码片段)

  1. ThunkAction<函数返回类型, store的类型, 参数的类型, 要使用到的 action 的类型>
    其中 函数返回类型 指的是第二个函数的返回类型吗?也就是如下代码中 return () => {} 这个函数吗?

  2. 参数的类型 我尝试定义为 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))
});
```

这样可以确保你在类组件中使用中间件时不会报错。
0
0

React18 系统精讲 结合TS打造旅游电商平台

React18 精讲 + 结合 TS 实战 + 热门业务开发,获取必备技能

1993 学习 · 1015 问题

查看课程