2016-06-29 78 views
3

所以,我有兩個輸入字段:如何正確更新對象的狀態(ReactJS + Redux)?

<TextField onChange={this.handleUserUsername.bind(this)} 
    value={this.props.userInfo.username} 
    /> 

    <TextField onChange={this.handleUserEmail.bind(this)} 
    value={this.props.userInfo.email} 
    /> 
一旦進入

,我想將它們存儲在一個名爲「用戶信息」的對象的狀態,就像這樣:

handleUserUsername(event){ 
    this.props.actions.updateUsername(event.target.value) 
    } 

    handleUserEmail(event){ 
    this.props.actions.updateEmail(event.target.value) 
    } 

和行動創造者有:

updateUsername: function(eventValue){ 
    return { 
     type: 'UPDATE_USERNAME', 
     username: eventValue 
    } 
    }, 

    updateEmail: function(eventValue){ 
    return { 
     type: 'UPDATE_USERNAME', 
     email: eventValue 
    } 
    } 

和減速器是:

function(userInfo={}, action){ 
    switch(action.type){ 
    case 'UPDATE_USERNAME': 
     return { 
     username: action.username 
     } 

    case 'UPDATE_EMAIL': 
     return { 
     email: action.email 
     } 

但是,一旦文本輸入到用戶名TextField中,它將顯示在TextField中輸入的任何內容,並正確存儲'用戶名'的'Z'並記錄以下內容(在本例中輸入'Z'):

enter image description here

然後,當在這個例子中一文中,「M」,輸入到電子郵件文本字段,用戶名狀態變爲「未定義」時,它應該保持爲Z,和電子郵件狀態甚至沒有存儲:

enter image description here

在日誌的例子中,我所希望看到的是:

userInfo: Object 
    username: "Z" 
    email: "M" 

,我使用下面的訪問狀況和措施:

function mapStateToProps(state) { 
    return state 
} 

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

爲什麼是不是正確貯存'userInfo'對象的狀態?更新這樣一個對象的正確方法是什麼?最終,我想將'userInfo'對象存儲到一個名爲users的數組中,它將存儲所有用戶信息。

編輯**

當我的用戶名文本框,下面顯示進入 'Q':

enter image description here

然後,當我在密碼文本框 'M',無論是不確定的現在:

enter image description here

EDIT 2 **

const registerReducer = function(userInfo={}, action){ 
    switch(action.type){ 
    case 'UPDATE_USERNAME': 
     return { 
     ...userInfo, 
     username: action.username 
     } 

    case 'UPDATE_EMAIL': 
     return { 
     ...userInfo, 
     email: action.email 
     } 

回答

0

我認爲問題在於您創建的更新狀態對象僅包含有關更改字段的信息。由於其中一個Redux的principles其狀態應該是不可變的,並且每次你想更新它時,你都應該創建一個新的狀態對象並進行必要的更改。

在你的情況,你應該在創建新的狀態對象時返回兩個字段(即使其中一個沒有變化):

function(userInfo={}, action){ 
    switch(action.type){ 
    case 'UPDATE_USERNAME': 
    return { 
     username: action.username, 
     email: userInfo.email  // userInfo is current state, we should save old value 
    } 

    case 'UPDATE_EMAIL': 
    return { 
     username: userInfo.username, // userInfo is current state, we should save old value 
     email: action.email  
    } 

通過這一點,你創建一個包含未領域的新狀態改變(具有相同的值),並且改變(用新值)

EDIT字段:

多個例子:

假設你的應用程序的這種狀態是:

oldState = { 
    email: "oldValue", 
    userName: "oldValue" 
} 

這時如果你想改變的電子郵件,你減速應以下列方式返回狀態對象:上述

return Object.assign({}, oldState, { 
    email: "newValue" 
}) 

代碼將產生新的狀態基於舊狀態的對象並更改新屬性中的電子郵件屬性。 Object.assign

其結果是新的國家將是這樣的:

{ 
    email: "newValue", 
    userName: "oldValue"  
} 

在你的榜樣你這樣的減速返回狀態對象:

{ 
    email: "newValue", 
} 

所以終極版無法理解什麼電流值用戶名是。

+0

我下編輯**用新日誌更新原來的職位。它現在顯示對象狀態電子郵件,但是一旦第二個文本字段接收到任何文本,它們都會變得不確定。 –

+0

但是我的回答對你來說仍然是實際的,因爲@ElodSzopos在下面提到,在reducer中,每當你通過動作進行修改時,你應該返回整個狀態對象(包括電子郵件,用戶名,密碼)。 – muphblu

+0

我試過像我這樣提供在編輯2 **,但得到以下錯誤:意外的令牌(5:8)在'...'開始,並不能找出什麼是錯的。 –

1

在您的示例中,您錯過了應該返回現有狀態以及作爲操作結果發生的更改,以改變以前的狀態。

這是一個減速的作用:

Actions describe the fact that something happened, but don’t specify how the application’s state changes in response. This is the job of a reducer.

你需要做的是始終返回一個新的狀態對象,它是將你的減速老狀態對象所發生的特定作用的結果。

而不是

case 'SOME_ACTION_TYPE': 
    return { 
    someProperty: 'theNewValue' 
    } 

你應該做的是:

case 'SOME_ACTION_TYPE': 
    return { 
    ...state, // notice how I create a new object, but preserve all of the old 
    propertyThatIChangedInMyReducer: 'theNewValue' // this will override the old 
    } 

基本上,你把減速機,應用更改,你會爲所發生並返回新對象的具體行動,也包含狀態樹的其他部分保持不變。你錯過了回來的另一部分。

如果讓我們說你有一個密碼字段太多,你會以同樣的方式對待,你會做這樣的事情:

case 'UPDATE_PASSWORD': 
    return { 
    ...state, //preserve current state, apply changes to it below 
    password: action.password, 
    }; 
+0

非常感謝你的澄清!我接受了你的建議並嘗試實現它,在原始的EDIT 2 **中提供,但得到以下錯誤:意外的標記(5:8)在'...'開始的位置,並且無法找出錯誤。 –

+0

這意味着你沒有使用ES6。我強烈建議你切換到使用它,因爲你會發現在React和Redux上的大多數示例和源代碼都將使用它。如果無法或者您不想,您可以使用Object.assign來保留您的狀態保持不變的舊屬性。 –

+0

我更喜歡ES6,如果是這樣的話。有沒有一種方法可以告訴我正在使用哪個版本?似乎'...'在某些情況下有效,但不在其他情況下,所以要確認。另外我該如何去切換到ES6? –