我有一个带有 react + redux 的应用程序,问题出现在编辑表单中。
问题描述
- 点击“编辑”编辑文档
- 显示编辑表单
- 我编辑/删除其中一个值
- 我没有保存(发送保存操作),而是返回到任何其他页面而不保存
- 然后返回到该对象的描述页面(“编辑”按钮所在的页面)
结果
文档已编辑。
因此,在 Portlets 组件中,当我单击编辑按钮时,我将 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: ''
};
...
}
这是 <input />
在调用编辑功能的 jsx 中:
<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
包含已编辑的 key !。
我真的不知道还能尝试什么,在这个函数之前我没有触发任何调度或其他东西,但我也尝试了 console.log()
里面mapStateToProps()
回到未保存的文档后,商店被编辑,我不明白!我还检查了父函数不包含可能同时工作的任何其他函数……什么也没有。
感谢任何帮助。提前致谢!
编辑:这就是this.props.portlet
看起来像:
{
country: "AR"
dev: true
slug: "document-name"
test: false
version: 2
_id: "5a798e53f2c5340bb08479f8"
_keys: [
{ newKey: "new key value" }
]
}
最佳答案
这就是为什么建议处理 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]
}, [])
}
})
关于javascript - 正在编辑 Redux 状态而不派发任何操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48648736/