2016-06-29 3 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} 
    /> 

однажды вошел, я хотел бы хранить их в состоянии объекта с именем «USERINFO», вот так:

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

Затем, когда текст, «М» в этом примере, вводится в электронный TextField, состояние имя пользователя становится «неопределенным», когда оно должно остаться как 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 в массив, называемый пользователями, где он будет хранить всю информацию о пользователе.

EDIT **

Когда я вошел в «д» в имени пользователя, текстовое поле следующие шоу:

enter image description here

Тогда, когда я вхожу «м» в пароль текстовое поле, оба становятся неопределенными Сейчас:

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 его состояние должно быть неизменным, и каждый раз, когда вы хотите его обновить, вы должны создать новый объект состояния с необходимыми изменениями.

В вашем случае, вы должны вернуть оба поля при создании нового объекта состояния (даже если один из них не изменился):

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", 
} 

Так перевождь не может понять, что текущее значение userName есть.

+0

Я обновил оригинальный пост под EDIT ** с новыми бревнами. Теперь он показывает адрес состояния объекта, но оба они становятся неопределенными, когда второе текстовое поле получает какие-либо тексты. –

+0

Но мой ответ по-прежнему актуальен для вас, а также @ElodSzopos, упомянутый ниже, в редукторе вы должны возвращать весь объект состояния (включая адрес электронной почты, имя пользователя, пароль) каждый раз, когда вы вносите изменения в действия. – muphblu

+0

Я попытался реализовать как таковой, в EDIT 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? –

 Смежные вопросы

  • Нет связанных вопросов^_^