-1

I'm building a React 16.13 application. I want to copy a property from my state in order to manipulate it and leave the underlying state unchanged. I thought this was the way to do it ...

  async handleFormSubmit(e) {
    e.preventDefault();
    const NC = [...this.state.newCoop]
    delete NC.addresses[0].country;

    try {
      const response = await fetch(FormContainer.REACT_APP_PROXY + "/coops/", {
        method: "POST",
        body: JSON.stringify(this.state.newCoop),
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
      });

However this line

const NC = [...this.state.newCoop]

gives the error

Unhandled Rejection (TypeError): this.state.newCoop is not iterable

What's the right way to copy a state variable by value?

Dave
  • 15,639
  • 133
  • 442
  • 830
  • What *is* `this.state.newCoop`? You seem to be treating it in two different ways - as an array when you copy it, and as an object when you access `NC.addresses`. Also note that `[...thing]` is only a *shallow* copy, so `delete NC.addresses[0].country` would mutate the original too. – jonrsharpe Jul 03 '20 at 16:20
  • "newCoop" is an object in my state. Should I include its attributes in my question? I would like to copy it by value as opposed to reference, but haven't figured out how to do that yet. – Dave Jul 03 '20 at 16:48
  • If it's an object, why are you spreading it into an array? And yes, please always give a [mre]. – jonrsharpe Jul 03 '20 at 16:49
  • I was trying to copy the object by value as recommended here -- https://stackoverflow.com/questions/51444827/how-can-i-copy-the-state-in-react-without-reference , but this solution is clearly not right, or doesn't apply to my situation somehow. – Dave Jul 03 '20 at 16:50
  • They're copying an *array*, per the dupe title, and you're saying you don't have an array. – jonrsharpe Jul 03 '20 at 16:51
  • Excuse me, my edited my comment. I want to copy by value, not by reference. Correct, I don't have an array, I just want to copy that state object by value. – Dave Jul 03 '20 at 16:54
  • Then see e.g. https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript – jonrsharpe Jul 03 '20 at 17:10

1 Answers1

1

I think it's just because you're spreading an object into an array; just do:

const NC = {...this.state.newCoop}

Edit:

Regarding the deep copy question, you can take a look at this answer: https://stackoverflow.com/a/38417085

By the way, this has nothing to do with react :)

e-cal
  • 1,661
  • 2
  • 20
  • 28
  • I tried it this way, but I think the value of NC is not a deep copy, but rather a shallow copy of the this.state.newCoop variable. When I run "delete NC.addresses[0].country;" and then print out " this.state.newCoop.addresses[0].country", what is printed out is undefined, whereas before the delete, " this.state.newCoop.addresses[0].country" had a value in it. – Dave Jul 03 '20 at 16:49
  • @Dave yes, as I said above it's a *shallow* copy – jonrsharpe Jul 03 '20 at 16:58
  • Yes, but per my question title, I wanted to know how to do the copy by value, not by reference. If there is a better way of phrasing my question, please let me know so it isn't confusing to others. – Dave Jul 03 '20 at 18:55
  • Ah good call. This FE stuff is endlessly confusing to me. But the "const NC = JSON.parse(JSON.stringify(this.state.newCoop)) " from your link did the trick! – Dave Jul 03 '20 at 20:27
  • Beware that the JSON.parse solution isn’t always safe (look at https://stackoverflow.com/a/122704/653325 as mentioned before by @jonrsharpe in another comment). – e-cal Jul 03 '20 at 20:34