2017-09-05 70 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 
}; 

注意:我不知道你需要在打字稿中輸入這個(如果有的話)。