0

I'm making an quiz app in react. Everything is working perfectly exept from a function that shuffles my array so the answers seem random every time. Here's the code.

  shuffleArray() {
    let array = this.state.answerArray;
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  }

Fetching and storing is working, but anytime I call that shuffleArray function, my original array (answerArray) also shuffles exactly like shuffledArray.

Im calling function after setState after fetching my data

this.setState(
          {
            qid: _id,
            question: question,
            correct_answer: correct_answer,
            answerArray: [
              correct_answer,
              answer1 || " ",
              answer2 || " ",
              answer3 || " "
            ]
          },
          () => {
            this.setState({
              shuffledArray: this.shuffleArray()
            });
          }
        );

Any idea why do both arrays shuffle?

2 Answers 2

3

Let's look shuffleArray :

 shuffleArray() {
    let array = this.state.answerArray;
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  }

This line here :

 let array = this.state.answerArray;

It is NOT copying the value of this.state.answerArray into array. array IS this.state.answerArray, so by modifying array you modify this.state.answerArray.

You can use spread syntax to copy your array :

let array = [...this.state.answerArray];

But WHY ? You may ask.

Well, Array are mutable (so do object and functions), so assignement are made by reference, not copy.

What do I do if I have an array of object ?

Check Josh answer below !

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

1 Comment

@F.Frlić you're welcome, Please take time to read links that are in my answer, you will earn valuable knowledge in Javascript and become able to help others in the future ! Also, do not forget to accept my answer :)
2

You are mutating the array returned by React state, that's why. You should not do that - see here.

Do this instead:

shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  }
() => {
   this.setState({
    shuffledArray: this.shuffleArray([...this.state.answerArray])
  });

This assumes that your array is made up of primitives (numbers, strings). If it is made up of objects, you need to do this:

this.shuffleArray(this.state.answerArray.map(answer => {...answer}))

If those objects contain other objects, then you should deep clone it with _.cloneDeep. This a method from the Lodash utility library that recursively clones objects to give you a true deep copy.

Arrays and objects are passed by reference in JavaScript. And React state is not cloned, you get a real reference to the state object.

You get the actual state object from React in your code so that React doesn't need to do a deep comparison of the state. It just needs to check the object reference.

If you are interested to know more about this, check out "Avoiding global mutable state in Browser JS" and the section "Understanding Object References" in the article "Shun the mutant - the case for const".

2 Comments

Hi Josh. Talking about made up object and deep cloning is a nice idea. May I suggest that you do talk about lodash as you are linking a method from the library in your answer ? You wouldn't want readers to think that it's a native javascript methods ^^
FYI, I linked your answer in mine if anyone need help on array made of objects ;)

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.