2

I'm practicing JavaScript and React by creating a quiz that will go through 5 questions, show your total score at the end, and show the high scores of those taking the quiz. I'm in the process of getting the "start quiz" button to show the first question when you click on it, but it won't unless the start screen is rendered twice. My problem is kind of hard to describe so bear with me.

This is my app.js file

import React, { useState } from 'react'
import "./style.css";
import Home from "./components/Home";
import QuestionOne from './components/QuestionOne';
import End from "./components/End";
import HighScores from "./components/HighScores";

// this is the home screen before you start the quiz
const App = () => {
    // default page is Home and we change the page when the start button is clicked
    const [currentPage, setCurrentPage] = useState("Home");

    // this checks which page it is and returns the proper page
    const renderPage = () => {
      switch (currentPage) {
        case "Home":
          return <Home />;
        case "QuestionOne":
          return <QuestionOne />;
        case "End":
          return <End />;
        case "HighScores":
          return <HighScores />;
        default:
          return <Home />;
      }
    }

    // home page
    return (
        <div>
            {/* change this to see whichever page until I can get the onClick down correctly*/}
            <Home currentPage={currentPage} setCurrentPage={setCurrentPage}/>
            {renderPage()}
        </div>
    );
}

export default App;

This is my Home.js file

import React from 'react'

const Home = ({ setCurrentPage }) => {

  return (
    <section className="section" id="start">
            <div className="container-fluid text-center">
                <div className="row row-cols-2">
                    <div className="col text-start" id="highScores">View High Scores</div>
                    <div className="col text-end">Time</div>
                </div>
                <div className="col text-center align-self-center" id="quizTitle"><strong>Coding Quiz Challenge</strong></div>
                <div className="col text-center align-self-center" id="quizExplain">Try to answer the following code-related questions within the time limit. <br></br>
                    Keep in mind that incorrect answers will penalize your score/time <br></br>
                    by ten seconds</div>
                <button
                    href="#home"
                    type="button"
                    onClick={() => setCurrentPage("QuestionOne")}
                    id="startQuiz">Start Quiz
                </button>
            </div>
        </section>
  )
}

export default Home

I'm stuck with these 2 lines in particular

<Home currentPage={currentPage} setCurrentPage={setCurrentPage}/>
{renderPage()}

The start page will currently show up twice, with 2 "start quiz" buttons. When I click the first "start quiz" button rendered with , the SECOND "start quiz" button rendered with {renderPage()} will change to the first question, but the first "start quiz" button and info will stay the same. Here is an imgur album showing what I mean: https://i.sstatic.net/7R3Wx.jpg

If I take out {renderPage()} and just leave it will only show one "start quiz" screen, but the "start quiz" button will not do anything. No errors or anything. If I take out , it tells me that "setCurrentPage" is not a function. I know it isn't a function because it doesn't know where "setCurrentPage" is coming from. There are no props being passed to it.

I've been stuck on this for weeks. Someone please help lol

2
  • 2
    renderPage returns <Home /> so you're effectively running <Home currentPage={currentPage} setCurrentPage={setCurrentPage}/> <Home />, thus showing it twice. Commented Nov 17, 2022 at 4:43
  • 2
    To add, when you click on the button in the first rendering of <Home />, you're updating the currentPage value to QuestionOne which causes a re-render. So now renderPage() will go through it's switch statement and see the new value for currentPage, and thus rendering <QuestionOne />. This is why you see the second rendering update, but not the first, as the first render of the <Home /> component is just, well, the Home page. Commented Nov 17, 2022 at 4:48

1 Answer 1

1

You're seeing the start page twice because you're rendering Home twice here:

<Home currentPage={currentPage} setCurrentPage={setCurrentPage}/>
{renderPage()}

The renderPage() call returns <Home /> so you're effectively doing this:

<Home currentPage={currentPage} setCurrentPage={setCurrentPage}/>
<Home />

And because <Home /> doesn't have a setCurrentPage prop, you get an error when clicking the button in that instance.

When you click the button in the first instance, currentPage gets set to "QuestionOne" and the re-render returns:

<Home currentPage={currentPage} setCurrentPage={setCurrentPage}/>
<QuestionOne />

As before, <QuestionOne /> doesn't have a setCurrentPage prop so the button doesn't work.

One simple adjustment would be to replace your named current page with a numeric index, increment the index on each button click, and render the component at that index in an array:

const steps = [Home, QuestionOne, End, HighScores];

const App = () => {
  const [currentPage, setCurrentPage] = useState(0);
  const Component = steps[currentPage];

  return Component
    ? <Component onNext={() => setCurrentPage( currentPage + 1 )} />
    : <button onClick={() => setCurrentPage(0)}>Reset</button>
}

This way instead of having to add a new switch case for every step you can just plop additional components into the array and the rest will take care of itself.

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

2 Comments

thank you so much! I'll definitely use this! Do you think I could also create a back button and just add another index with currentPage - 1? This is more of a hypothetical question, because I have to get the quiz itself working first.
To do a back button you'd just subtract instead of adding. <button onClick={() => setCurrentPage( currentPage - 1 )}>Back</button>. You'd have to make sure it doesn't go past zero, but that's the basic idea.

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.