Home > OS >  React how to clone props
React how to clone props

Time:01-21

I'm learning

I have problem with this function in my component:

...
export default function Main(props) {
...
...
...
const deleteMessage = (index) => {
        let test = props.data.contacts;
        // let test2 = { ...props.data.contacts}; Also tried with this
        test[currentContact].messages.splice(index, 1);
        // props.setData({ ...props.data, test }) this is commented and should't be executed
    }
return (...<JSX Elements>...)
}

When I run <li onCLick={() => deleteMessage(index)}> Delete this message </li> the change is performed on the parent component's status.

Although props.setData () is commented out in this sample code, props.data is still affected by this function's changes.

How can I clone props.data in a new object and work only on this, without chaging props.data?

CodePudding user response:

When updating the state make sure that every part of the nested structure until you reach the actual thing that you want to update gets cloned.

test[currentContact].messages.splice(index, 1);

This is bad because splice modifies the messages array.

Infact test[currentContact].messages itself is bad because test[currentContact] is being mutated.


// let test2 = { ...props.data.contacts}; Also tried with this

Object and Array spread syntaxes can be used to clone and prevent mutation, but here too make sure that props.data gets cloned first and then contacts.


Examples of updating arrays and objects immutably:

const bla = {
  foo: {
    bar: [1]
  }
}

// here's how you can update `bla` immutably if you want to add an element to the nested array
const clonedBla = { ...bla,
  foo: {
    ...bla.foo,
    bar: [...bla.foo.bar, 2]
  }
}
console.log(bla, clonedBla)

const bla = {
  foo: [{
      a: "a",
    },
    {
      b: "b",
      arr: [1, 2],
    },
  ],
};

// if we want to remove the second element of `bla.foo[1].arr`
const updatedBla = {
  ...bla,
  foo: bla.foo.map((el, index) =>
    index === 1 ?
    {
      ...el,
      arr: el.arr.filter((_, iIndex) => iIndex !== 1),
    } :
    el
  ),
};
console.log(updatedBla)

CodePudding user response:

Cloning is the right approach, we usually want to avoid mutating arrays / objects directly.

I think to most common modern way to clone either an array or an object is by spreading it's contents into a new variable via the spread operator.

Example -

const originalArray = [1, 2, 3, 4];
const originalObject = {
  'a': 1,
  'b': 2,
  'c': 3,
  'd': 4,
};

const newArray = [...originalArray, 5, 6];
const newObject = {
  ...originalObject,
  'e': 5,
  'f': 6,
};

console.log(newArray); // [1, 2, 3, 4, 5, 6]
console.log(newObject); // {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}

As you can see, it acts as a member in the array / object, and essentially spreads the original variable while creating a new one instead of being a reference to the original.

  •  Tags:  
  • Related