2015-11-19 32 views
3

我在我的行動創造者進行異步調用,並與結果調用我的減速機,但由於某種原因,我無法摸清減速機沒有被調用。反應:行動的創造者不打電話減速機

actions.js(動作和動作的創造者)

export const GET_FORMS = 'GET_FORMS' 

export function getForms() { 
    $.get("server url", function(result) { 
    return { 
    type: GET_FORMS, 
    formlist: result.data.forms 
    } 
    }) 
} 

reducers.js

import { GET_FORMS } from '../actions/actions' 

export default function formAction(state = {forms:[]}, action) { 
    console.log("received action"+action.type) 
    switch (action.type) { 

    case GET_FORMS: 
     console.log("Action:"+action); 
     return Object.assign({},state,{ 
     forms:action.formlist 
     }) 

    default: 
    return state 
} 
} 

App.js

import React, { Component, PropTypes } from 'react' 
import ReactDOM from 'react-dom'; 
import { bindActionCreators } from 'redux' 
import { connect } from 'react-redux' 
import auth from '../auth' 
import FormTable from '../components/FormTable' 
import * as FormActions from '../actions/actions' 


class App extends Component { 

constructor(props) { 
    super(props); 
    this.state = {forms: []}; 
} 

componentDidMount() { 
    // for some reason if i write this.props.actions.getForms() i get an error 
    // Uncaught Error: Actions must be plain objects. Use custom middleware for 
    // async actions. 
    FormActions.getForms(); 
} 

render() { 
    const {forms,actions} = this.props 
    console.log(forms); 
    return (
    <FormTable results={forms} actions = {actions} /> 
) 
} 
} 

App.PropTypes = { 
    forms: PropTypes.array.isRequired 
} 

function mapStateToProps() { 
const { 
    forms:forms 
} = {forms:[]} 

return { 
    forms 
} 
} 

function mapDispatchToProps(dispatch) { 
return { 
    actions: bindActionCreators(FormActions, dispatch) 
} 
} 

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(App) 

回答

12

這裏有幾件事情。

  1. 您的動作創建者不會返回它正在創建的動作。 $.get不返回任何操作,因此將其映射到dispatch不具有生產力。

    合理地說,這可能會導致如何從異步操作創建者返回操作。由於它是異步的,它本質上不能返回最終結果(除非你使用es7 asyncawait)。你嘗試的模式是相同的:

    class App extends Component { 
        ... 
        componentDidMount() { 
        // Instead of calling getForms, do the same directly 
        $.get(url, function(res) { 
         return { type: GET_FORMS, forms: res }; 
        }); 
        } 
    
        render() { ... } 
    } 
    

    $.get API,我們知道$.get返回jqXHR object ,沒有任何一種行動。所以你必須在自己的回調中使用結果 - 你不能只是返回它。這是一個什麼樣componentDidMount然後可以看起來像一個例子(注意回調勢必this):

    componentDidMount() { 
        $.get(url, function(res) { 
        this.props.dispatch({ type: GET_FORMS, forms: res }); 
        }.bind(this)) 
    } 
    
  2. 做在您的組件或行動的創建者異步是一種反模式,或至少氣餒。在這種情況下,你是定義行動創建者內部的異步,這是偉大的。但是你的也執行異步操作,這是不好的。相反,您應該使用某種中間件來處理異步操作。中間件只是在派遣之後採取行動並執行任務的功能,爲此目的最常見的是redux-thunk。使用redux-thunk,您只需返回一個接受dispatch作爲參數的函數。在這種情況下,你的行動創造者應該是這樣的:

    export function getForms() { 
        return function(dispatch) { 
        $.get(url, function(result) { 
         dispatch({ type: GET_FORMS, forms: result }); 
        }) 
        } 
    } 
    

    這是非常相似,你已經做什麼,除非你正在創建一個thunk,可呈現就是一個定義其他功能的功能稍後執行 - 而不是實際執行異步操作現在,您正在定義它以便稍後執行。

  3. 你實際上並沒有調度任何東西。

    最簡單的問題來解決,但絕對是一個障礙:)在componentDidMount,你打電話給你導入的動作創建者,但你不打電話dispatch。儘管如此,你已經達到了50%,因爲你將行動創建者傳遞給了connect,但即使你這麼做了,你也沒有將connect傳遞給prop的綁定動作創建者稱爲未綁定動作。

    因此,不要致電FormActions.getForms(),您需要致電this.props.actions.formActions()。前者不受約束,但後者是。調用後者與做this.props.dispatch(FormActions.getForms())相同。

  4. 最後:在這種情況下,您不需要定義mapDispatchToProps。您可以將對象傳遞給參數connect。請看下圖:

    // Instead of this 
    export default connect(mapStateToProps, mapDispatchToProps)(App); 
    
    // do this: 
    export default connect(mapStateToProps, FormActions)(App); 
    // creates the bound action creator 'this.props.getForms()' 
    

    這其中主要是一個風格的選擇,但我覺得這是一個很好的模式:)對於多個行動的創建者源對象,你可以這樣做:

    export default connect(mapStateToProps, { ...FormActions, ...UserActions })(App); 
    
+0

謝謝關於redux流程是如何工作的詳細解釋,我能夠讓reducer捕獲動作創建者的動作,並使用記錄器我可以驗證是否有狀態變化。但是在App.js的渲染方法中,forms/object仍然是空的。我在mapstatetoprops中做錯了什麼。 –

+1

yes - mapStateToProps將始終返回一個空數組。你正在使用解構賦值,所以const {forms:forms} = {forms:[]};將永遠是形式= []。如果您使用的是連接,則需要指定您想要注入組件的全局狀態的哪一部分。你可以在這裏閱讀更多關於使用方法的文章:http://rackt.org/redux/docs/basics/UsageWithReact.html –

+0

是的。我得知我沒有將表格映射到狀態,因此無法獲得更改。該鏈接幫助我將我的狀態映射到窗體並顯示在我的渲染方法中獲取數據。 –