Javascript 重新复制以前的状态已具有新的状态值

Javascript 重新复制以前的状态已具有新的状态值,javascript,reactjs,redux,Javascript,Reactjs,Redux,我正在尝试使用React&Redux来处理受控表单,我已经让它工作了,这样当我在输入字段中键入时,状态会按照预期更新并传递给输入组件 但是,在我的reducer中,当我控制台记录以前的状态时,表单字段的值不包含键入新字符之前的值,它已经有了新字符 我的减速机: import initialState from '../state/form' const form = (prevState = initialState, action) => { switch (action.type

我正在尝试使用React&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
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
    }
  }
}
如果我的输入字段包含文本“tes”,那么我可以添加一个“t”,并按预期调度操作,但当它到达这个减缩器时,我会记录上一个状态,字段的值是“test”,而不是“tes”

我希望前一个状态有“tes”,减速器返回新状态有“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实现还可以,只是控制台上有一些巫毒。log(prevState)=“test”,调试器允许我观察prevState变量,并显示它等于“tes”,正如预期的那样

谢谢你的回答@Pineda。在研究奇怪的控制台日志行为时(当您键入答案时),我发现变量是对对象的引用fact()-我已停止改变状态,并更新了我的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
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
方法中的错误,我似乎没有改变状态,必须解决这个问题才能使新的缩减器正常工作。

我猜您是在将输入直接绑定到redux存储属性:

<input
  value={this.props.name}
  onChange={e => this.props.name = e.target.value}
/>
this.props.name=e.target.value}
/>
请记住,值是通过引用传递的,而不是通过值传递的,如果您直接修改存储值,那么当操作触发时,您将已经改变了redux存储状态(这是一个很大的禁忌)

我的建议是,试着找出如何在代码库中传递这种状态,您应该有如下内容:

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

您正在这些行中改变状态

  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
然后使用变异状态创建新对象

解决方案:
进一步检查,当我在Chrome中使用debugger时,前面的状态显示为预期状态,因此我猜这可能是一个控制台日志问题。当我在输入标记上将一个函数传递给我的onChange处理程序时,该函数通过mapDispatchToProps传递,实际上完全按照第二个示例所示进行。此后,我使用了Chrome调试器(在console.log行的正上方使用调试器语句),与console.log不同,它按预期显示了以前的状态。看起来除了console.log之外,其他一切都正常工作!你介意用代码更新你的问题吗?