How to update an array of arrays by replacing an array item with the new corresponding array item? Reactjs

Viewed 23

Apologies for the poorly worded title, I'm not sure how to phrase the question. I have made a quiz app in React which allows the user to choose the number of questions and for each question, there are five possible answers they can toggle between.

Because of the toggle feature, if they toggle between the possible answers, I need to be able to add the new array and replace the old corresponding one, which will then be checked to see if they are correct when they check the score. I've tried for hours to figure this out but I just can't. I've come sort of close but it only works if the user doesn't toggle between the answers.

Here's my code so far and the only semi-workable solution that I've come up with but is ugly and only works if the user doesn't toggle between answers for the same question.

function getDataFromQuestionComponent(dataFromComponent){
    getQuizData.push(dataFromComponent)
    // stop the score data array from growing continously 
    if (getQuizData.length > amount) {
        maintainScoreArrayLength(getQuizData)
    }
}
function maintainScoreArrayLength(quizDataArray){
    // to find if which answers are matching so the original can be replaced
    // with the new answer (too obscure - find a better solution)
    let lastItemZeroIndexText = (quizDataArray[quizDataArray.length - 1][0].body)

    for (let i=0; i<quizDataArray.length; i++) {
        if (lastItemZeroIndexText === getQuizData[i][0].body) {
            newArray.push(getQuizData.indexOf(getQuizData[i]))                 
        }
    }
    // remove the previous item from the array
    getQuizData.splice(newArray[0], 1)
}

This is what the array of object arrays looks like in the console: enter image description here

1 Answers

The .map array method and array destructuring make it possible to do this more cleanly.

I can't quite tell how you are storing the data for the quiz questions/answers, but here's an example of how you could do it if you are saving all of the quiz data in a state object and storing the index of the current question:

const [quizData, setQuizData] = useState(initialQuizData);
const [currentQuestion, setCurrentQuestion] = useState(0);

const onSelectAnswer = (selectedAnswer) => {
    // create an object with updated data for the current question
    const updatedQuestionData = {
      ...quizData[currentQuestion],
      multipleChoiceAnswers: quizData[
        currentQuestion
      ].multipleChoiceAnswers.map((answerOption) => ({
        ...answerOption,
        selected: selectedAnswer === answerOption.body
      }))
    };

    // iterate through the questions
    // and save either the
    // updatedQuestionData or the prevState data
    // (store the updatedQuestionData over the prevState data for that question)
    setQuizData((prevState) => [
      ...prevState.map((question, index) =>
        currentQuestion === index ? updatedQuestionData : question
      )
    ]);
  };

To break it down, we create a copy of the answers array but we set selected to false unless it is the answer the user just clicked:

multipleChoiceAnswers.map(answerOption) => ({
   ...answerOption,
   selected: selectedAnswer === answerOption.body
})

The updated question object is made by copying the data from the current question, then overriding the array of answers with the updated copy of the answers we just made in the code snippet above. That is what is happening in this part:

 const updatedQuestionData = {
      ...quizData[currentQuestion],
      multipleChoiceAnswers: // The updated answers array
    };

Here's a full example on code sandbox: Edit Quiz With Immutable State

Related