I have an app with react + redux, and the problem is happening in the editing form.
Description of the issue
- click "edit" to edit a document
- Show the edit form
- I edit/delete one of the values
- instead of saving (dispatching an action to save) I return to any other page without saving
- then comeback to the description page for this object (where the "edit" button is located)
Result
The document is edited.
So, from the Portlets component, when I click on the edit button, I'll setState({isEditing: true})
:
if(this.state.isEditing) {
return (
<div className="col-md-12">
<div className="card">
<div className="card-content">
<PortletForm />
</div>
</div>
</div>
);
Then I open the <PortletForm />
component, and access again the data with 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));
This is the constructor()
in the editing form:
constructor(props) {
super(props);
this.state = {
portlet: this.props.portlet,
addNewKey: [],
addNewKeyDisabled: false,
newKey: '',
newValue: ''
};
...
}
This is the <input />
in jsx where that calls the editing function:
<input
type="text"
className="form-control"
autoFocus={index === 0}
name={Object.keys(key)}
value={Object.values(key)}
onChange={this._updatePortletKey} />
and _updatePortletKey()
, where the problem seems to be happening:
_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 });
}
So I create a new object, and assign it modified to the state, after some debuggin this is what I found:
- When I'm accessing this function
this.props.portlet
contains the original object - Right after I return the new keys from the map function (where the debugger is placed) and before I edit the state,
this.props.portlet
contains the edited key!.
I really don't know what else to try, before this function I'm not triggering any dispatch or somethig, but I also tried a console.log()
inside mapStateToProps()
and after coming back to the non saved document the store is edited, I don't get it! I also checked that the parent function does not contain any other function that might be working at the same time... got nothing.
Any help is appreciated. Thanks in advance!
Edit: this is how this.props.portlet
looks like:
{
country: "AR"
dev: true
slug: "document-name"
test: false
version: 2
_id: "5a798e53f2c5340bb08479f8"
_keys: [
{ newKey: "new key value" }
]
}
This is why suggested method to deal with redux is
ImmutableJS
orimmutable-helper
or the kind.It is very easy to make mistakes otherwise.
Here is what happend:
And this is a mistake I have seen many people making. Also, it is a pain to debug such cases. So please use a helper library.
If you insist on using es6 to construct new object, it could get ugly as the nesting increases.