0

Hello! I am having some difficulties with the states of my quiz. Every time I click one of the three option buttons (from the JSX), the states [questionsAnswered] and [correctAnswers] get properly incremented, but only for a brief second before the page "refreshes" and the states return to their initial state. I need to stop these two states from returning to their initial states when changes are made to the page (specifically: when buttons are clicked). Is there any way to do this?

Here is my code:


import { useState, useContext, useEffect } from 'react'
import { Link } from 'react-router-dom'

import Logo from '../Components/Logo'
import Game_ById from '../Components/Game_ById';
import { QuizContext } from '../Contexts/QuizContext';
import IQuizContext from '../Interfaces/IQuizContext';

import '../Quiz.css';

const Quiz_Play = () => {

    const {questions} = useContext(QuizContext) as IQuizContext; // get all questions from contexts

    const [firstRender, setFirstRender] = useState(false);

      useEffect(() => {
        if(questions.length > 0){
            generateRandomNumber()
            nextQuestion()
            setFirstRender(true);
        }
    
        return () => {
          if (window.performance.navigation.type == 1) {
             window.location.href = "/quiz"
          }
    
        };
      }, [firstRender, questions]);

    const [questionNum, setQuestionNum] = useState<number>(0)
    const [questionText, setQuestionText] = useState<string>("")
    const [questionImageId, setQuestionImageId] = useState<number | undefined>(0)
    const [questionOptions, setQuestionOptions] = useState<string[]>([])
    const [questionCorrect, setQuestionCorrect] = useState<string>("")

    // these two states keep resetting back to 0 (initial state) when I click a button
    const [questionsAnswered, setQuestionsAnswered] = useState<number>(0)
    const [correctAnswers, setCorrectAnswers] = useState<number>(0)

    const [random, setRandom] = useState<number>(0)

    const generateRandomNumber = () => {
        const rand = Math.floor(Math.random() * questions.length)
        setRandom(rand)
    }
    
    const nextQuestion = () => {
        
        generateRandomNumber()

        const q = questions[random]

        setQuestionNum(questionNum+1)
        setQuestionImageId(q.gameId)
        setQuestionText(q.question)
        setQuestionOptions(q.options)
        setQuestionCorrect(q.correct)
    }

    const chooseOption = (e : any) => {

        console.log("current value is :" + e.currentTarget.value)
    
        if(questionsAnswered != undefined){
            setQuestionsAnswered(questionsAnswered+1)
        }
        
        if(e.currentTarget.value === questionCorrect){
            setCorrectAnswers(correctAnswers+1)
        }
    }
  
  return (
    <div>
        
        <Logo />

        <div className="wrapper">
            <h1 className="quizInfo_h1"> Question {questionNum} </h1>
            <h2 className="quizQuestion_h2 text-align-center">{questionText}</h2>
            <p className="correctCounter_p text-align-center no-margin "><span style={{color: '#f2c112'}}>{correctAnswers}</span>/{questionsAnswered}</p>
            
            <div className="quizImage">
                <Game_ById id={questionImageId}/>
            </div>

        </div>
        
        <div className="quiz-options">
            <form>
                <button className="btn small-med-btn quiz-option-btn" id="option-1" onClick={chooseOption} value={questionOptions[0]}>{questionOptions[0]}</button>
                <button className="btn small-med-btn quiz-option-btn" id="option-2" onClick={chooseOption} value={questionOptions[1]}>{questionOptions[1]}</button>
                <button className="btn small-med-btn quiz-option-btn" id="option-3" onClick={chooseOption} value={questionOptions[2]}>{questionOptions[2]}</button>   
            </form>    
        </div>

        <p style={{marginTop: 10, color:"rgba(255, 255, 255, 0.5)"}} className="text-align-center">
            Don't want to play anymore? Feeling like a <Link to="/quiz" className="yellowlink">coward</Link>?
        </p>

        

    </div>
  );
}

export default Quiz_Play;

I have read around online and I assume this could be fixed with the useRef hook, somehow? I have tried to implement something of the kind after seing some posts about it but I can't get it to work.

Thanks in advance to anyone taking the time to help. It's greatly appreciated

Also, let me know if you need me to provide additional information in order for you to assist.

  • You're setting the window location manually instead of using react-router. The page reloads so your current JS context goes away. You **could** use local/sessionStorage, or use react-router. – Dave Newton Nov 22 '22 at 16:13
  • @DaveNewton Thanks for the comment, but the line of code you are referencing to redirects the user to another page called /Pages/Quiz on route /quiz . This is not what's causing the problem I'm trying to address here. – nostrad0muz Nov 22 '22 at 16:46
  • Could you point out which states that have this issue? – Disco Nov 22 '22 at 16:52
  • @Disco basically the only states I need to maintain throughout the quiz are questionsAnswered and correctAnswer. But I guess all of them go back to the state defined inside their parentheses, for example: const [questionOptions, setQuestionOptions] = useState([]) will return to an empty array, but immediately after it is injected with data from the {questions} array from Context. But questionsAnswered and correctAnswers are not being set in nextQuestion() , therefore they go back to 0 – nostrad0muz Nov 22 '22 at 16:58
  • @Disco but to directly answer your questions. The states that have this issue (hence the states im trying to ensure are not being reset) are: questionsAnswered and correctAnswers – nostrad0muz Nov 22 '22 at 17:06
  • 2
    type="button" or remove your form element. – Kevin B Nov 22 '22 at 17:10
  • @KevinB has the correct answer here, the buttons submits the form. Just remove the wrapping form. And one extra thing dont use the current state like this. `setQuestionsAnswered(questionsAnswered+1)` If you need the current state use the function version instead: `setQuestionsAnswered((current) => current+1)` – Disco Nov 22 '22 at 17:13
  • @KevinB dang, I did not think of this. I will try it out and get back to you. – nostrad0muz Nov 22 '22 at 17:14
  • @Disco Thanks alot! I will try all of this :) – nostrad0muz Nov 22 '22 at 17:14
  • 1
    Thanks guys. Turns out, just like @KevinB said, when I removed the form element the issue disappeared – nostrad0muz Nov 22 '22 at 17:25

0 Answers0