2017-09-05 44 views
1

我想弄清楚如何一起使用React,Redux和TypeScript来减少样板的数量。这可能是你不能在这种情况下,但想看看是否有人有想法。使用React,Redux和TypeScript映射DispatchToProps的更简单方法?

我目前有一个组件调度切换菜单的动作,在显示和隐藏它之间交替。要做到这一点,我定义我的课是这样的(涉及国家省略代码,注重行动的调度):

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))}); 

任何意见表示赞赏!

回答

4

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

行动 - 原始

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

+0

太棒了!谢谢@niba! – langkilde

+0

@niba你怎么称'连接'这个?除非我将'mapDispatchToProps'声明为'const mapDispatchToProps =(dispatch):IConnectedDispatch => {toggleMenu}','connect'并不能为我正确地推断出类型。我会用'export default ReactRedux.connect(mapStateToProps,mapDispatchToProps)(HeaderMenu)来调用它;'... – mikebridge

+0

我不使用标准的'connect'。我有'connect'的特殊包装器,它可以自动从'mapStateToProps'和'mapDispatchToProps'中检索类型,我可以稍后将它放入我的容器定义中。无论如何,我只是试图做'connect(state => state,{... actions})(Component);'并且我没有看到任何问题。你的连接不能正确推断哪些类型? – niba

2

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

From the docs

如果对象被传递,则假定在其内部的各功能是一个终极版动作创建者。具有相同功能名称的对象,但每一个行动的创建者裹成dispatch调用,这样他们可以直接调用,将​​被合并到组件的道具

这可以让你把它改写为:

const mapDispatchToProps = { 
    toggleMenu 
}; 

注意:我不知道你需要在打字稿中输入这个(如果有的话)。