0

When mapping data from api to render component, i want to shuffle array once. But when i clicked any of answers button, answers array shuffle again. Here is code and https://codesandbox.io/s/wonderful-bartik-p4utm9?file=/public/index.html

    // FETCH QUIZ DATA FROM API
const fetchData = async () => {
    await fetch("https://opentdb.com/api.php?amount=5&type=multiple")
    .then((response) => response.json())
    .then((data) => setData(data.results))
}

React.useEffect(()=> {
    setRestart(false)
    fetchData()
},[restart])


// SHUFFLE ALGORITHM TO USE LATER
function shuffle(array) {
    let currentIndex = array.length,  randomIndex;
  
    // While there remain elements to shuffle.
    while (currentIndex != 0) {
      // Pick a remaining element.
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex--;
      // And swap it with the current element.
      [array[currentIndex], array[randomIndex]] = [
        array[randomIndex], array[currentIndex]];
    }
    return array;
}

// RENDER QUESTIONS
const questionElements = data.map((question, index) => {
    // ANSWERS ARRAY AND SHUFFLE
    let answers = [...question.incorrect_answers,question.correct_answer]
    shuffle(answers)

    return (
        <Question key={index} index={index} question={question.question} answers={answers}/>
    )
})
1

3 Answers 3

1

Simple solution: In the declaration of Data Const [Data,setData] = useStat([]] Then befor calling the fetch api check if not Data.length ===0 then proceed

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

Comments

0

The issue is caused by the "shuffle" function you're calling in your "questionElements" function.

The following is what is currently happening:

  • Each time your "Quiz" component renders, it invokes the "questionElements" function, which inside it calls the "shuffle" function.

  • In your "Question" component, when you select an answer, the onClick event invokes the "toggleBtnBgColor" function

  • In the "toggleBtnBgColor" you dispatch the "calculate" action which changes the "score" value in the Redux slice.

  • Your "Quiz" component is using the "score" value from store in the "useSelector" which means that whenever this value changes, the entire component will re-render.

  • When this component re-renders it will call "questionElements" which will then call "shuffle" yet again. Thus your issue.

What I would do to fix this issue, is on initial render, use useEffect to shuffle all question answers in the order you'd like and then store them in the components state and then map through those. Any further state updates won't re-shuffle them.

Comments

0

SOLVED! Moved shuffle function from mapping component part to the fetchData function.

const fetchData = async () => {
    await fetch("https://opentdb.com/api.php?amount=5&type=multiple")
    .then((response) => response.json())
    .then((data) => {
        for(let question of data.results) {
            question.incorrect_answers = shuffle([...question.incorrect_answers, question.correct_answer])
        }
        setData(data.results)})
}

Comments

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.