我有一个带有react + redux的应用程序,问题出现在编辑表单中。
问题描述
结果
文档已编辑。
因此,从Portlets组件中,当我点击编辑按钮时,我{l} setState({isEditing: true})
:
if(this.state.isEditing) {
return (
<div className="col-md-12">
<div className="card">
<div className="card-content">
<PortletForm />
</div>
</div>
</div>
);
然后我打开<PortletForm />
组件,再次使用connect()
访问数据:
function mapStateToProps(state, ownProps) {
let portlet = {};
const portletId = ownProps.match.params.id;
if (state.portlets.length > 0) {
portlet = Object.assign({}, state.portlets.find(portlet => portlet._id === portletId));
}
return { portlet: portlet };
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(portletActions, dispatch)
};
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(PortletForm));
这是编辑表单中的constructor()
:
constructor(props) {
super(props);
this.state = {
portlet: this.props.portlet,
addNewKey: [],
addNewKeyDisabled: false,
newKey: '',
newValue: ''
};
...
}
这是jsx中调用编辑功能的<input />
:
<input
type="text"
className="form-control"
autoFocus={index === 0}
name={Object.keys(key)}
value={Object.values(key)}
onChange={this._updatePortletKey} />
和_updatePortletKey()
,问题似乎正在发生:
_updatePortletKey(event) {
const field = event.target.name;
let editedDoc = Object.assign({}, this.state.portlet);
editedDoc._keys.map((elem, index) => {
const key = Object.keys(editedDoc._keys[index]);
if(key[0] === field) {
return editedDoc._keys[index][field] = event.target.value;
}
});
debugger;
this.setState({ portlet: editedDoc });
}
所以我创建了一个新对象,并将其修改为状态,经过一些调试后,这就是我发现的:
this.props.portlet
包含原始对象this.props.portlet
包含已编辑的密钥!。我真的不知道还有什么可以尝试,在此功能之前我没有触发任何调度或某些事情,但我也在console.log()
内mapStateToProps()
尝试了回到未保存的文档,商店已编辑,我不明白!我还检查了父函数不包含任何可能同时工作的其他函数......什么都没有。
感谢任何帮助。提前谢谢!
编辑:这就是this.props.portlet
的样子:
{
country: "AR"
dev: true
slug: "document-name"
test: false
version: 2
_id: "5a798e53f2c5340bb08479f8"
_keys: [
{ newKey: "new key value" }
]
}
答案 0 :(得分:3)
这就是为什么建议的处理redux的方法是ImmutableJS
或immutable-helper
或者那种。
否则很容易犯错误。
以下是发生的事情:
// constructor
this.state = {
portlet: this.props.portlet, // you put props in the state
}
// change handler
let editedDoc = Object.assign({}, this.state.portlet);
// here a new object is created, but if the value is not primitive, it is by reference.
// this means, while editedDoc and this.state.portlet are different objects, "_key"'s value is shared between these object.
这是我看到许多人制作的错误。此外,调试此类案件也很痛苦。所以请使用帮助库。
如果你坚持使用es6构建新对象,那么随着嵌套的增加,它可能会变得丑陋。
// example 1
_updatePortletKey(event) {
const field = event.target.name;
this.setState({
portlet: {
...this.state.portlet,
_keys: this.state.portlet._keys.reduce((agg, el) => {
const key = Object.keys(el);
// btw, what are you trying to do here !! (my logic might be slightly off, as I didn't fully understood the transformation, but you get the idea, right?)
if(key[0] === field) {
return [...agg, {...el, [field]: event.target.value}]
}
return [...agg,el]
}, [])
}
})