网站搜索

reactjs - 使用 React、Redux 和 TypeScript 映射 dispatch 到 props 的更简短方式?


我正在尝试弄清楚在一起使用 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))});

任何建议都很感激!

答案#1

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

动作 - 原版

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。它有助于减少由 actions 创建的许多样板代码,尤其是异步的那些。

答案#2

mapDispatchToProps 将接受一个动作创建者对象而不是函数,并自动将所有它们绑定到 dispatch。

来自文档:

如果传入一个对象,其中的每个函数都被假定为 Redux action 创建者。一个具有相同函数名的对象,但每个 action 创建者都被包裹在 dispatch 调用中,以便可以直接调用,将会合并到组件的 props 中

这允许你将其重写为:

const mapDispatchToProps = { 
  toggleMenu 
};

注意:我不确定你在 TypeScript 中是否需要将其输入为这种类型(如果需要的话)。