-1

I have a situation where I want to make a unchangeable copy of a property to restore state to its original... well state.

I have a array of group objects.
Inside each group i have and array of items.
When I make the copy bellow everything is fine.

I start by doing this.

componentDidMount(){
    // originalGroups = Object.assign([], this.props.modalitygroups);
    originalGroups = JSON.parse(JSON.stringify(this.props.modalitygroups));
},

I have tried both of the statements above, but have read that the current active one makes a true deep copy of a object. Needles to say it does copy it properly.

I then have THIS search feature to search for items in the groups and items.

_searchFilter:function(search_term){
    this.setState({modalitygroups:originalGroups});
    let tempGroups = Object.assign([], this.state.modalitygroups);

    if(search_term !== ''){
        for (let x = (tempGroups.length) - 1; x >= 0; x--)
        {
            console.log("originalGroups",x,originalGroups);

            for (let i = (tempGroups[x].items.length) - 1; i >= 0; i--)
            {
                if(!tempGroups[x].items[i].description.toLowerCase().includes(search_term.toLowerCase())){
                    tempGroups[x].items.splice(i,1);
                }
            }
            if(tempGroups[x].items.length === 0){
                tempGroups.splice(x, 1);
            }
        }
        this.setState({modalitygroups:tempGroups});
    }
},

So I start of by restoring the original state to enable searching through everything. The search feature loops though each groups and within each group loop I loop through each item deleting items that dont contain the search phrase.
After looping through each item, if no item remain in the group, I remove that group from the group array aswell.

This works well first time arround.

But when I start searching for a new item, I find that the originalGroups has changed aswell. The previous deleted items has been removed from the unchangable copy aswell and I dont know why. Where and why does it change my safe copy?

Hope this makes sense.

morne
  • 4,035
  • 9
  • 50
  • 96

2 Answers2

1

const state = {
  property1: 42
};

const originalGroups = Object.freeze(state);

originalGroups.property1 = 33;
// Throws an error in strict mode

console.log(originalGroups.property1);
// expected output: 42

Essentially ReactJS is still javascript afterall, so you can apply Object.freeze to save a copy of state

Isaac
  • 12,042
  • 16
  • 52
  • 116
  • That won't freeze the properties of children, if `property1` is an array you can't change `property1`, but you can add or remove objects from the array unless you freeze it as well, right? – Jason Goemaat Jul 18 '18 at 03:11
  • @JasonGoemaat: According to this: https://stackoverflow.com/a/7510003/9816472 , it should be working fine too, however I have yet to test that out – Isaac Jul 18 '18 at 03:24
  • Hmm... Not sure how deep it goes, but in Chrome seems to go 1 level deep in strict mode... [*fiddle*](http://jsfiddle.net/kqW9C/43/). Here you can't change the array or the name property, but you can change phone.mobile: `var arr = Object.freeze([{name: 'Isaac', phone: {mobile: '7025551212'}}]);` – Jason Goemaat Jul 18 '18 at 03:51
  • @JasonGoemaat: Interesting finding, but probably just like the comment owner mentioned it's implementation problem, but if it's one level deep freezing I believe it's enough to handle OP's request right? – Isaac Jul 18 '18 at 03:59
  • I don't know. It would prevent him from removing groups from the original array, but maybe not from removing items from the subproperty. It might help him find the problem by throwing an error. If it's in `Object.assign([], this.state.modalitygroups);` would that fail, or do a shallow copy of frozen 'group' objects? – Jason Goemaat Jul 18 '18 at 05:02
1

So modality groups contains original groups? This is hard to follow... Instead of 'saving' the original groups, I'd leave this.props.modalitygroups alone and copy to a filteredGroups of the state. You can reload that from the props that you never change.

In your filter function when you do let tempGroups = Object.assign([], this.state.modalitygroups); that should probably be where you use json to create a deep copy. That is filling the new array with the same group references in the old array, so you are modifying the same group instance in the original.

_searchFilter:function(search_term){
    // deep copy
    let tempGroups = JSON.parse(JSON.stringify(this.props.modalitygroups));

    if(search_term !== ''){
        for (let x = (tempGroups.length) - 1; x >= 0; x--)
        {
            console.log("originalGroups",x,originalGroups);

            for (let i = (tempGroups[x].items.length) - 1; i >= 0; i--)
            {
                if(!tempGroups[x].items[i].description.toLowerCase().includes(search_term.toLowerCase())){
                    tempGroups[x].items.splice(i,1);
                }
            }
            if(tempGroups[x].items.length === 0){
                tempGroups.splice(x, 1);
            }
        }
        this.setState({modalitygroups:tempGroups});
    }
},
Jason Goemaat
  • 28,692
  • 15
  • 86
  • 113
  • The thing is, I tried that. but for some reason `this.props.modalitygroups` also changes. It loses its items for a reason I do not know yet. – morne Jul 18 '18 at 03:21
  • Yes, `this.props.modalitygroups` contains the original groups. – morne Jul 18 '18 at 03:22
  • What options did you do? If you use `filteredGroups = JSON.parse(JSON.stringify(originalGroups))` in your filter and set a *different* state property (like `filteredGroups`), you should be fine. – Jason Goemaat Jul 18 '18 at 03:27