2

I use mapStateToProps to map some value from the redux store to props:

function mapStateToProps(state, ownProps) {
    // state.layers has 3 Objects containing arrays
    return {
        layers: state.availableLayers.toObject()
    };
}

I am displaying the different layers and the user can chose the one he/she wants to create. On click event I write the chosen layer to state:

openParams(layer){
    this.setState({
        showLayer: layer
    });
}

The argument for the layer is passed from a click event where I iterate through all the posible layers in this.props.layers.

Now I want the user to be able to change some config. For that I have a handleInput event whenever the input of a config field changes:

handleChange(e) {
    let field = e.target.name;
    let value = e.target.value;

    let tmpLayer= this.state.showLayer;
    tmpLayer[field]["value"] = value;

    this.setState({ showLayer: tmpLayer });
}

When the user is done I call the redux action: this.props.actions.createLayer(this.state.showLayer);

But when I do that, the store does not only create the layer. But also changes the state.availableLayers in the redux store. But that data should stay untouched. My reducer does not change it, I already checked that. It seems like the line tmpLayer[field]["value"] = value; is changing the redux store. But I don't understand why? It seems like there is some reference from my this.state.showLayer to the redux store?! I already tried to copy the object on mapStateToProps with immutable.js and with Object.assign({}, state.availableLayer.toObject(), but it didn't help.

EDIT: using JSON.parse(JSON.stringify(this.state.showLayer)) resolves the issue while Object.assign({}, this.state.showLayer) and {...this.state.showLayer} suggested by @mkatanski do not. How that?

2 Answers 2

1

Alright. There is a reference into the store and to change that a deep copy is needed as the strucutre and fields of showLayer are not known beforehand and can vary depending the type of layer.

Using either this JSON.parse(JSON.stringify(this.state.showLayer)) in the handleChange()function or JSON.parse(JSON.stringify(state.availableLayers.toObject)) in mapStateToProps() resolves the issue.

Sign up to request clarification or add additional context in comments.

Comments

0

You can use the spread operator, for example:

const tmpLayer = {
 ...this.state.showLayer
}

This is recommended way of doing clone without reference by redux documentation.

Also, you can try to use immutability helpers from react addons: React: Immutability Helpers

EDIT:

If none of above work, you can also do it manually:

const tmpLayer = {}
Object.keys(showLayer).forEach(elem => {
   tmpLayer[elem] = showLayer[elem]
})

4 Comments

I tried your first suggestion. It does not resolve the issue. JSON.parse(JSON.stringify(this.state.showLayer)) seems to work on the other hand... but what I have read it is quite expensive.
That is strange. Maybe doing a method which manualy copies object elements would be better? I think faster than JSON aproach. See my edit.
Its becaues it only clones the first level. And [field][value] is the second level. Since I have different data structures and don't know the fields in advance I need a deep copy.
Yeah, it also only copys the first level of the object. If you do something like that: l.deep.deepTest = 'change Deep', both objects in your example change. jsfiddle.net/g8jea0e5/1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.