Redux以前的状态已经具有新的状态值

时间:2017-01-29 14:10:01

标签: javascript reactjs redux

我正试图使用​​React& amp;来掌握受控表格。 Redux,我已经让它工作了,所以当我输入输入字段时,状态正在更新并按预期传递给输入组件。

但是,在我的reducer中,当我在控制台上记录上一个状态时,表单字段的值不包含新字符输入之前的值,它已经有了新字符。

我的减速机:

import initialState from '../state/form'
const form = (prevState = initialState, action) => {

  switch (action.type) {

    case 'INPUT': {
      console.log(prevState) // the value here equals "test"
      debugger // the value here equals "tes"
      let newFields = prevState.fields
      newFields[action.field].value = action.value
      return Object.assign({}, prevState, {
        fields: newFields
      })
    }

    default: {
      return prevState
    }
  }
}

export default form

如果我的输入字段包含文本“tes”,我可以添加一个“t”并按预期调度操作,但当它到达此reducer时,我控制台记录前一个状态,字段的值为“测试“,而不是”测试“。

我期待之前的状态有“tes”,而reducer则以“test”返回新状态。

在我的容器中,我有:

const dispatchToProps = (dispatch, ownProps) => {
  return {
    control: (e) => {
      dispatch({
        type: 'INPUT',
        form: ownProps.formId,
        field: e.target.getAttribute('name'),
        value: e.target.value
      })
    },
    clear: () => {
      dispatch({
        type: 'CLEAR_FORM',
        form: ownProps.formId
      })
    }
  }
}

所以我的输入组件正在传递'control'功能。我已经在上面的reducer代码中的console.log旁边使用了一个调试器语句,并使用Chrome的开发工具,这显示了prevState具有我预期的(tes,而不是test)。 console.log仍在记录“test”!

所以看来我的redux实现可能没问题,只有一些伏都教作为console.log(prevState)==“test”,调试器允许我观察prevState变量并显示它等于“tes”,如预期!

感谢您的回答@Pineda。在查看奇怪的控制台日志行为时(当您输入答案时)我遇到了变量是对象的引用事实(here) - 我已经停止改变我的状态,并更新了我的减速机:

import initialState from '../state/form'
const form = (state = initialState, action) => {
  switch (action.type) {

    case 'INPUT': {
      return Object.assign({}, state, {
        fields: {
          ...state.fields,
          [action.field]: {
            ...state.fields[action.field],
            value: action.value
          }
        }
      })
    }

    default: {
      return state
    }
  }
}

现在一切正常。由于我的mapStateToProps方法中的错误,我可能一直试图逃避变异状态,必须解决这个问题才能让新的reducer正常工作。

2 个答案:

答案 0 :(得分:1)

您正在改变这些行中的状态

  let newFields = prevState.fields
  newFields[action.field].value = action.value
  // it's also worth noting that you're trying to access a 'value'
  // property on newFields[action.field], which doesn't look
  // like it'll exist

可以重写为:

  prevState.fields[action.field] = action value

然后使用变异状态创建新对象。

解决方案:

import initialState from '../state/form'
const form = (prevState = initialState, action) => {

  switch (action.type) {

    case 'INPUT': {
      console.log(prevState);
      // You create a new un-mutated state here
      // With a property 'fields' which is an object
      // with property name whose value is action.field
      // which has the value action.value assigned to it
      const newState = Object.assign({}, prevState, {
        fields: { [action.field]: action.value}
      });
      return 
    }

    default: {
      return prevState
    }
  }
}

export default form

答案 1 :(得分:0)

我猜你将输入直接绑定到redux商店属性:

<input
  value={this.props.name}
  onChange={e => this.props.name = e.target.value}
/>

请记住,值是通过引用传递的,而不是通过值传递的,如果您直接修改商店值,那么当操作触发时您将已经改变了您的redux存储状态(这是一个很大的否定)

我的建议是,试着找到你在代码库中如何传递这种状态,你应该有类似的东西:

<input
  value={this.props.name}
  onChange={e => dispatch({type: 'INPUT', field: 'name', value: e.target.value })}
/>