0

I have the following React.js component where I get 10 multiple-choice trivia questions via an API call using fetch and recursively list them on the page via nested components.

The API provides 'correct_answer' as string, and 'incorrect_answers' separately as an array of strings. In my current code, I am only able to list the 'correct' and 'incorrect' answers in their own components.

What I would like to do is combine the 'correct' and 'incorrect' answers into a single array and then randomise the output of them, so that the correct answer is not always in the same place in the list. How would I alter my current code to that? I am an absolute beginner at React.js so any pointers are welcome, thanks.

import React, { Component } from "react";

    class QuestionContainer extends Component {

        constructor() {
            super();
            this.state = {
                questions: []
            };
        }

        componentWillMount() {
            const RenderHTMLQuestion = (props) => (<p dangerouslySetInnerHTML={{__html:props.HTML}}></p>)
            const RenderHTMLAnswer = (props) => (<li dangerouslySetInnerHTML={{__html:props.HTML}}></li>)
            fetch('https://opentdb.com/api.php?amount=10&category=9&type=multiple')
                .then(results => {
                    return results.json();
                }).then(data => {
                    let questions = data.results.map((question, index) => {
                        return(
                            <div key={index} className="questionWrapper">
                                <div className="question" key={question.question}>
                                     <RenderHTMLQuestion HTML={question.question} />
                                </div>
                                <ul className="answers">
                                    <RenderHTMLAnswer key={question.correct_answer} HTML={question.correct_answer} />

                                   {question.incorrect_answers.map((answer, index) => (
                                        <RenderHTMLAnswer key={index} HTML={answer} />
                                    ))}
                               </ul>
                            </div>
                        )
                    })

                    this.setState({questions: questions});
                })

            }


        render() {
            return (
                <div className="container2">
                    {this.state.questions}
                </div>
            )
        }
    }


    export default QuestionContainer;
1
  • Hi, check my solution and let me know if that helps. Commented Dec 20, 2019 at 3:55

2 Answers 2

1

You can try this,

let questions = data.results.map((question, index) => {
  let correctAnswer = false
  return (
    <div key={index} className="questionWrapper">
      <div className="question" key={question.question}>
           <RenderHTMLQuestion HTML={question.question} />
      </div>
      <ul className="answers">
        {question.incorrect_answers.map((answer, index) => {    
            if(Math.floor(Math.random() * Math.floor(question.incorrect_answers.length-1)) === index && !correctAnswer) {
                  correctAnswer = true
                  return <> <RenderHTMLAnswer key={question.correct_answer} HTML={question.correct_answer} /> <RenderHTMLAnswer key={index} HTML={answer} /> </>
             }
            return <RenderHTMLAnswer key={index} HTML={answer} />
        })}
      </ul>
    </div>
  )
})

Math.random()

Note: Don't use componentWillMount (UNSAFE), instead you can go for componentDidMount for your API call.


Update

You can also try this,

let questions = data.results.map((question, index) => {
  question.incorrect_answers.splice(Math.floor(Math.random() * Math.floor(question.incorrect_answers.length + 1)), 0, question.correct_answer)
  return (
    <div key={index} className="questionWrapper">
      <div className="question" key={question.question}>
          <RenderHTMLQuestion HTML={question.question} />
      </div>
      <ul className="answers">
        {question.incorrect_answers.map((answer, index) => { 
            return <RenderHTMLAnswer key={index} HTML={answer} />
        })}
      </ul>
    </div>
  )
})

Array.prototype.splice()

Demo

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

7 Comments

Thanks, this is moving in the right direction, it does randomise the output, but it is not outputting all of the incorrect answers (there are 3 incorrect and 1 correct answers provided from the API) and it is sometimes adding the correct answer more than once. e.g. The first three items list out as: Question correct answer correct answer incorrect answer Question incorrect answer correct answer incorrect answer Question correct answer correct answer incorrect answer So the logic needs to be adjusted somewhere I think?
I think part of the problem is that '{question.incorrect_answers.map((answer, index)...' only iterates 3 times as there are 3 incorrect answers. I need to be able to add the 4th correct answer in there at a random point.
Thanks, that is now adding the additional answer but is adding the correct answer twice in some instances. e.g. Question1: incorrect, correct, incorrect, incorrect (this is how it should be). Question 2: correct, incorrect, correct, incorrect, incorrect (this has the correct answer duplicated).
@SilentDesigns, try adding a flag as updated in answer.
@ravibaul91 Thanks, splicing the correct answer into the incorrect_answer array was the solution. Thanks for your efforts looking at this. I will mark your answer as accepted.
|
1

You can try using lodash https://lodash.com/docs/4.17.15#shuffle

const answers = _.shuffle(_.concat(correct_answers, incorrect_answers));
return (
 <ul className="answers">
  {answers.map((answer, index) => (<RenderHTMLAnswer key={index} HTML={answer} />))}
 </ul>
)

2 Comments

I don't think this will work, because as stated in my question 'correct_answer' is a string, not an array.
@SilentDesigns that can be easily fixed by changing the code above to something like: const answers = _.shuffle([correct_answer, ...incorrect_answers]);. I'd also recommend keeping the key the answer itself instead of using the index

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.