我正试图使用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正常工作。
答案 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 })}
/>