0
\$\begingroup\$

I built a simple trivia with React from Vite that reads from an external JS file.

Here is the main code for the game:

import { useState } from "react";
import "./App.css";
import { questions } from "./assets/newquestions";

const App = () => {
  const [answer, setAnswer] = useState("");
  const [count, setCount] = useState(0);

  const styler = (choice) => {
    if (answer) {
      if (choice === questions[count].answer) {
        return { backgroundColor: "#00FF00", color: "#000000" };
      } else {
        return { backgroundColor: "#FF0000", color: "#000000" };
      }
    }
  };

  return (
    <>
      <h1>
        {count}) {questions[count].question}
      </h1>
      <div className="card">
        <button
          style={styler("A")}
          onClick={() => setAnswer("A")}
          disabled={answer !== ""}
        >
          <h2>A) {questions[count].A}</h2>
        </button>
        <button
          style={styler("B")}
          onClick={() => setAnswer("B")}
          disabled={answer !== ""}
        >
          <h2>B) {questions[count].B}</h2>
        </button>
      </div>
      <div className="card">
        <button
          style={styler("C")}
          onClick={() => setAnswer("C")}
          disabled={answer !== ""}
        >
          <h2>C) {questions[count].C}</h2>
        </button>
        <button
          style={styler("D")}
          onClick={() => setAnswer("D")}
          disabled={answer !== ""}
        >
          <h2>D) {questions[count].D}</h2>
        </button>
      </div>
      {answer ? (
        <button
          onClick={() => {
            setAnswer("");
            setCount(count + 1);
          }}
        >
          Next Question
        </button>
      ) : null}
    </>
  );
};

export default App;

Here is an small snippet of the question code:

export const questions = [
  {
    difficulty: "0",
    question: "Are you ready to start?",
    A: "Yes",
    B: "No",
    C: "No",
    D: "No",
    answer: "A",
  },
  {
    difficulty: "1",
    question: "Which artist painted the Mona Lisa?",
    A: "Picasso",
    B: "Leonardo Da Vinci",
    C: "Andy Warhol",
    D: "Aaron Van Kampen",
    answer: "B",
  },
...
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

With React, it's important to identify and separate what requires and what doesn't require state. In this scenario, the presentation of the questions and answers is mainly stateless while the selected question, and assessment of the answer are stateful. The one edge-case is indicating whether they answered correctly vs incorrectly.

My recommendations are:

  1. Redefine the data model to specify options as an Array instead of a through d, and the selected answer as the index from 0 to 3. This allows you to use a loop to render the options, which are identical and don't need to be repeated. This also allows you to generalize to more answers, for some questions, and potentially multiple answers in the future.
  2. Extract a presentational component that is stateless that displays the options. Bubble up an event for when an option is selected, pass in an optional selected attribute, and pass in additional selectedStyles attribute for showing the highlight when the answer is assessed.
  3. Consider using more semantic HTML elements such as input type="radio" to present the cards so that its more accessible.

I also noticed that you are using difficulty in the model but are not presenting it or using it in your assessment as well. I'd recommend removing that if its not being used, and if it is, consider changing it to a number.

\$\endgroup\$
2
\$\begingroup\$

Some suggestions after reviewing your code:

  1. Use Enums for Choices: Replace hardcoded "A", "B", "C", "D" with an enum for readability.

  2. DRY (Don't Repeat Yourself): Use a map function to generate button elements and make your code DRYer.

  3. Reset State: Reset the answer state when moving to the next question to avoid carrying over styles.

  4. Boundary Check: Add a condition to handle the end of the questions array.

  5. Semantic HTML: Replace <h2> inside buttons with span or div for semantic correctness.

  6. Simplify Styling Function: Move common styles like color: "#000000" to CSS to simplify the styler function.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.