I am working on a project that fetchs data from the open Trivia api. I have developed everything already and everything seems to work fine so far. However, when I first render the app, the first time I click the button to submit my answer it calls the function, but doesn't render the new question, answer choices... In order to render I have to click to choose the answer again and click the button again. Once it has rendered after clicking the check answer button for the second time, the rest of the app works perfectly at first click. I am not completely sure what is causing this bug, could you please help me?
Here it is my code:
import React, { useEffect, useState } from "react";
import { Container, Row, Card, Button, Alert } from "react-bootstrap";
import axios from "axios";
import "../App.css";
import Results from "./Results";
export const createMarkup = (text) => {
return { __html: text };
};
const QuizCategory = () => {
const [quizData, setquizData] = useState([]);
const [category, setCategory] = useState([]);
const [question, setQuestion] = useState([]);
const [options, setOptions] = useState([]);
const [questionsData, setQuestionsData] = useState([]);
const [questionNumber, setQuestionNumber] = useState(0);
const [selectedAnswer, setSelectedAnswer] = useState();
const [correctAnswer, setCorrectAnswer] = useState();
const [score, setScore] = useState(0);
const [prevSelectedElement, setPrevSelectedElement] = useState();
const [quizState, setQuizState] = useState("start");
const [showAlert, setShowAlert] = useState(false);
const [rightAlert, setRightAlert] = useState(false);
const [wrongAlert, setWrongAlert] = useState(false);
const totalQuestion = 10;
const fetchQuizData = async () => {
const { data } = await axios.get("https://opentdb.com/api.php?amount=10");
setQuestionsData(data);
console.log(data);
setCategory(data.results[questionNumber].category);
setQuestion(data.results[questionNumber].question);
setCorrectAnswer(data.results[questionNumber].correct_answer);
const formattedData = data.results.map((category) => {
const incorrectAnswersIndexes = category.incorrect_answers.length;
const randomIndexes = Math.random() * (incorrectAnswersIndexes - 0) + 0;
category.incorrect_answers.splice(
randomIndexes,
0,
category.correct_answer
);
return {
...category,
answers: category.incorrect_answers,
};
});
setquizData(formattedData);
setOptions(formattedData[questionNumber].answers);
};
useEffect(() => {
fetchQuizData();
}, []);
const selectAnswer = (e, answer) => {
setSelectedAnswer(answer);
console.log("Answer Selected:", answer);
const optionSelected = "options-selected";
const newSelectedElement = e.target;
if (newSelectedElement.classList.value === optionSelected) {
newSelectedElement.classList.replace("options-selected", "options");
setPrevSelectedElement(newSelectedElement);
} else if (prevSelectedElement) {
prevSelectedElement.classList.replace("options-selected", "options");
newSelectedElement.classList.replace("options", "options-selected");
setPrevSelectedElement(newSelectedElement);
} else {
newSelectedElement.classList.replace("options", "options-selected");
setPrevSelectedElement(newSelectedElement);
}
};
const checkAnswer = () => {
console.log(
selectedAnswer,
correctAnswer,
score,
questionNumber,
question,
category,
options
);
if (selectedAnswer === correctAnswer && questionNumber < 10) {
setScore(score + 1);
setQuestionNumber(questionNumber + 1);
setQuestion(questionsData.results[questionNumber].question);
setCategory(questionsData.results[questionNumber].category);
setOptions(quizData[questionNumber].answers);
setSelectedAnswer();
setCorrectAnswer(questionsData.results[questionNumber].correct_answer);
setShowAlert(false);
console.log("Correct", questionNumber);
} else if (
selectedAnswer !== undefined &&
selectedAnswer !== correctAnswer &&
questionNumber < 10
) {
setQuestionNumber(questionNumber + 1);
setQuestion(questionsData.results[questionNumber].question);
setCategory(questionsData.results[questionNumber].category);
setOptions(quizData[questionNumber].answers);
setSelectedAnswer();
setCorrectAnswer(questionsData.results[questionNumber].correct_answer);
setShowAlert(false);
console.log("Incorrect", questionNumber);
} else if (
selectedAnswer !== undefined &&
selectedAnswer === correctAnswer &&
questionNumber === 10
) {
console.log("Ready to start again?");
setScore(score + 1);
setQuizState("results");
setShowAlert(false);
} else if (
selectedAnswer !== undefined &&
selectedAnswer !== correctAnswer &&
questionNumber === 10
) {
console.log("Ready to start again?");
setShowAlert(false);
setQuizState("results");
} else {
setShowAlert(true);
}
console.log(
selectedAnswer,
correctAnswer,
score,
questionNumber,
question,
category
);
};
console.log(selectedAnswer);
return (
<div>
<Container>
<div className="title-text">
<h1 className="trivia-text">Trivia</h1>
<h1 className="coin-text"> Coin</h1>
<h1 className="game-text">Game</h1>
</div>
<Row>
{quizState === "start" ? (
<>
<Card className="card-big">
<Card.Title>
<div
className="category"
dangerouslySetInnerHTML={createMarkup(category)}
></div>
</Card.Title>
<Card.Body>
<div className="score">
<p
dangerouslySetInnerHTML={createMarkup(score)}
className="correct-score"
></p>
/
<p
className="total-question"
dangerouslySetInnerHTML={createMarkup(totalQuestion)}
></p>
</div>
<div
className="question"
dangerouslySetInnerHTML={createMarkup(question)}
></div>
{options.map((answer) => (
<div
onClick={(e) => selectAnswer(e, answer)}
key={answer}
value={answer}
>
<li
className="options"
dangerouslySetInnerHTML={createMarkup(answer)}
></li>
</div>
))}
{showAlert === true ? (
<>
<Alert
variant="light"
onClose={() => setShowAlert(false)}
dismissible
>
<Alert.Heading>Please choose an answer!</Alert.Heading>
</Alert>
</>
) : (
<div className="alert-component"></div>
)}
{rightAlert === true ? (
<>
<Alert
variant="success"
onClose={() => setShowAlert(false)}
dismissible
>
<Alert.Heading>That's Right, Good Job!</Alert.Heading>
</Alert>
</>
) : (
<div className="alert-component"></div>
)}
{wrongAlert === true ? (
<>
<Alert
variant="danger"
onClose={() => setShowAlert(false)}
dismissible
>
<Alert.Heading>
The Right Answer is <b>{correctAnswer}</b>. You Got
the Next One!
</Alert.Heading>
</Alert>
</>
) : (
<div className="alert-component"></div>
)}
<Button
className="check-btn"
size="large"
variant="outline-light"
onClick={() => checkAnswer()}
>
CHECK ANSWER
</Button>
</Card.Body>
</Card>
</>
) : (
<Results
createMarkup={createMarkup}
score={score}
totalQuestion={totalQuestion}
/>
)}
</Row>
</Container>
</div>
);
};
export default QuizCategory;