使用 React、Redux 和 TypeScript 映射DispatchToProps 的更短方法?

IT技术 reactjs typescript redux
2021-05-27 02:42:45

我试图弄清楚如何在一起使用 React、Redux 和 TypeScript 时减少样板文件的数量。在这种情况下可能你不能,但想看看是否有人有想法。

我目前有一个组件,它调度一个切换菜单的动作,在显示和隐藏它之间交替。为此,我定义了我的类(省略了与状态相关的代码,专注于动作的调度):

import {Action, toggleMenu} from "../../actions/index";    

interface IConnectedDispatch {
  toggleMenu: (isActive: boolean) => Action;
}

class HeaderMenu extends React.Component<IOwnProps & IConnectedState & IConnectedDispatch, any> {

  constructor(props: IOwnProps & IConnectedState & IConnectedDispatch) {
    super(props);
    this.toggleMenuState = this.toggleMenuState.bind(this);
  }

  public render() {        
    return (
      <button className={buttonClass} onClick={this.props.toggleMenu(this.props.isActive)} type="button">
      </button>
    );
  }
}

const mapDispatchToProps = (dispatch: redux.Dispatch<Store.All>): IConnectedDispatch => ({
  toggleMenu: (isActive: boolean) => dispatch(toggleMenu(isActive))});

该动作被定义为

export function toggleMenu(isActive: boolean): Dispatch<Action> {
  return (dispatch: Dispatch<Action>) => {
    dispatch({
      isActive,
      type: "TOGGLE_MENU",
    });
  };
}

感觉应该可以减少实现我的目标所需的代码量。作为 React、Redux 和 TypeScript 的新手,我看不出究竟是怎么回事。具体感觉就是一遍遍的写动作名,toggleMenu,感觉很重复。例如这部分的两次:

const mapDispatchToProps = (dispatch: redux.Dispatch<Store.All>): IConnectedDispatch => ({
  toggleMenu: (isActive: boolean) => dispatch(toggleMenu(isActive))});

任何建议表示赞赏!

2个回答

有一个更短的方法。您可以简化很多代码。

动作 - 原创

export function toggleMenu(isActive: boolean): Dispatch<Action> {
  return (dispatch: Dispatch<Action>) => {
    dispatch({
      isActive,
      type: "TOGGLE_MENU",
    });
  };
}

行动 - 减少

export const toggleMenu = (isActive: boolean) => ({
  isActive,
  type: "TOGGLE_MENU"
})

属性界面 - 原版

interface IConnectedDispatch {
  toggleMenu: (isActive: boolean) => Action;
}

属性界面 - 减少

import { toggleMenu } from "./actions"
interface IConnectedDispatch {
  toggleMenu: typeof toggleMenu
}

MapDispatch - 原始

const mapDispatchToProps = (dispatch: redux.Dispatch<Store.All>): IConnectedDispatch => ({
  toggleMenu: (isActive: boolean) => dispatch(toggleMenu(isActive))});

MapDispatch - 减少

const mapDispatchToProps = { 
  toggleMenu 
};

我可以推荐这个库typescript-fsa它有助于减少由操作创建的大量样板,尤其是异步操作。

mapDispatchToProps将接受动作创建者的对象而不是函数,并自动将它们全部绑定到dispatch.

从文档

如果传递了一个对象,则假定其中的每个函数都是 Redux 动作创建者。具有相同函数名称的对象,但每个动作创建者都包含在一个dispatch调用中,以便可以直接调用它们,将合并到组件的 props 中

这允许您将其重写为:

const mapDispatchToProps = { 
  toggleMenu 
};

注意:我不确定你需要在typescript中输入什么(如果有的话)。