1

Sorry about the confusing title, I really didn't know what the categorize this as. I was having an issue regarding changing a variable that was set to an Array element. I have since figured out a way to accomplish what I wanted, but this was still bugging me so I figured I'd ask here.

playCard(event){

    let tempArray = this.state.playerDeck;
    let playArray = this.state.playerDefaultCards;

    playArray.push(tempArray[event.target.id]);
    console.log(playArray[1].image);  //logs image data

    let tempObject = tempArray[event.target.id];
    tempObject.image = "Test";
    console.log(playArray[1].image); //logs "Test"
    tempArray[event.target.id] = tempObject;

    this.setState ({playerDeck: tempArray, playerDefaultCards: playArray});
    console.log(this.state.playerDefaultCards[1].image); //Also logs "Test"
  }

Basically I have 2 arrays of objects with image sources. When an image is clicked on, I wanted it to go from the playerDeck to the playerDefaultCards, and then I just wanted to change the image source in the playerDeck to a blank string.

I thought that if I made a temporary variable and set it equal to the array element, changed that temporary variables image property and then set the array element equal to that new object everything would work out.

However when I change tempObject.image = "Test" it changes in both the tempArray and the playArray, which to my knowledge shouldn't happen. This is the source of my confusion.

Obviously I'm missing something but so far I haven't been able to figure it out.

1
  • 1
    Even though you set tempArray equal to this.state.playerDeck you are not making a copy of this variable. When you push items into tempArray you are still mutating this.state.playerDeck. If you want to make copies of these arrays you'd need to do something like let tempArray = this.state.playerDeck.slice(); ... although I can't say I'd recommend doing this with React state. Commented Aug 8, 2017 at 1:04

1 Answer 1

1

playArray.push(tempArray[event.target.id]) copies the reference at tempArray[event.target.id] to the object rather than the object itself.

You can use Object.assign to create a new object for the card you want to move, then you can edit the original.

You should also .slice() the state arrays to make sure you do not change them outside of setState.

Something like this:

playCard(event){

    const tempArray = this.state.playerDeck.slice();
    const playArray = this.state.playerDefaultCards.slice();

    const selectedCard = Object.assign({}, tempArray[event.target.id]);

    playArray.push(selectedCard);
    tempArray[event.target.id].image = "Test";

    this.setState({playerDeck: tempArray, playerDefaultCards: playArray}); 
}

One thing to watch out for is setState is fast, but it is not instant. A console.log called right after this.setState will possibly execute before the update is completed and return the old value. this.setState can take a callback function if you need to do something as soon as it finishes.

Object.assign is not supported by all browsers, so you may need a polyfill for it.

Object.assign documentation

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

1 Comment

Thanks for the help, object.assign() was the way to go. I was unaware that objects were passed by reference until now.

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.