Reactで3択クイズの作り方

英語コラム

<script>” title=”<script>

<script>

まずは完成形を確認します。

3択クイズをアラートで正解/不正解を表示させ、最後に何問正解したかを表示させます。

1.下準備

まずは3択クイズの見た目部分を整えていきます。

jsxの中はmap関数でループ処理しますが、一旦テキストで表示させ見た目を整えていきます。

import "./styles.css";

export default function App() {
  return (
    <div className="quiz_wrap">
      <p>第1問</p>
      <p>日本で一番高い山は?</p>
      <ul>
        <li>富士山</li>
        <li>阿蘇山</li>
        <li>高尾山</li>
      </ul>
    </div>
  );
}
.quiz_wrap {
  text-align: center;
}

ul {
  list-style: none;
  display: flex;
  justify-content: center;
}

li {
  margin: 0 20px;
  cursor: pointer;
}

2.出題するクイズの準備

今回は3問出題しようと思います。

questions という定数の中に出題するクイズを配列で入れていきます。

配列ができたら先ほどテキストで入れていたjsxの中身を配列から引っ張ってくるようにします。

import "./styles.css";

export default function App() {
  const questions =[
    {
      questionText:"日本で一番高い山は?",
      answerOptions:[
        {answerText:"富士山",isCorrect:true},
        {answerText:"阿蘇山",isCorrect:false},
        {answerText:"高尾山",isCorrect:false}
      ]
    },
    {
      questionText:"世界で一番高い山は?",
      answerOptions:[
        {answerText:"モンブラン",isCorrect:false},
        {answerText:"エベレスト",isCorrect:true},
        {answerText:"ティラミス",isCorrect:false}
      ]
    },
    {
      questionText:"日本で一番小さい都道府県は?",
      answerOptions:[
        {answerText:"東京都",isCorrect:false},
        {answerText:"大阪府",isCorrect:false},
        {answerText:"香川県",isCorrect:true}
      ]
    }
  ]
  return (
    <div className="quiz_wrap">
      <p>第1問</p>
      <p>{questions[0].questionText}</p>
      <ul>{questions[0].answerOptions.map((answer,key) => (
        <li key={key}>{answer.answerText}</li>
      ))}</ul>
    </div>
  );
}

3.クリックした時の正解/不正解処理

次にクリックしたら正解/不正解をアラートで表示する処理を追加します。

リストタグにonClickイベントを追加し、isCorrecttrueなら正解、falseなら不正解になります。

import "./styles.css";

export default function App() {
  const questions = [
    {
      questionText: "日本で一番高い山は?",
      answerOptions: [
        { answerText: "富士山", isCorrect: true },
        { answerText: "阿蘇山", isCorrect: false },
        { answerText: "高尾山", isCorrect: false }
      ]
    },
    {
      questionText: "世界で一番高い山は?",
      answerOptions: [
        { answerText: "モンブラン", isCorrect: false },
        { answerText: "エベレスト", isCorrect: true },
        { answerText: "ティラミス", isCorrect: false }
      ]
    },
    {
      questionText: "日本で一番小さい都道府県は?",
      answerOptions: [
        { answerText: "東京都", isCorrect: false },
        { answerText: "大阪府", isCorrect: false },
        { answerText: "香川県", isCorrect: true }
      ]
    }
  ];

  const check = (isCorrect) => {
    if (isCorrect === true) {
      alert("正解");
    } else {
      alert("不正解");
    }
  };
  return (
    <div className="quiz_wrap">
      <p>第1問</p>
      <p>{questions[0].questionText}</p>
      <ul>
        {questions[0].answerOptions.map((answer, key) => (
          <li key={key} onClick={() => check(answer.isCorrect)}>
            {answer.answerText}
          </li>
        ))}
      </ul>
    </div>
  );
}

4. map関数を動かし、全問解いたあと「終わり」と表示する

ここまでではまだリストをクリックした時にアラートで正解/不正解が表示されるだけで、次の問題は表示されません。

なのでReactのStateを使ってmap関数を動かします。

const [current, setCurrent] = useState(0);

nextQuestion で今現在何問目かを制御し、nextQuestion が配列にあるクイズの数より少なければ、setCurrentnextQuestion を記憶させ、大きければ「終わり」と表示させます。

ここは三項演算子を使ってshowFinish がtrueなら終わり、falseなら引き続きクイズを表示させるようにします。


import { useState } from "react";
import "./styles.css";

export default function App() {
  const questions = [
    {
      questionText: "日本で一番高い山は?",
      answerOptions: [
        { answerText: "富士山", isCorrect: true },
        { answerText: "阿蘇山", isCorrect: false },
        { answerText: "高尾山", isCorrect: false }
      ]
    },
    {
      questionText: "世界で一番高い山は?",
      answerOptions: [
        { answerText: "モンブラン", isCorrect: false },
        { answerText: "エベレスト", isCorrect: true },
        { answerText: "ティラミス", isCorrect: false }
      ]
    },
    {
      questionText: "日本で一番小さい都道府県は?",
      answerOptions: [
        { answerText: "東京都", isCorrect: false },
        { answerText: "大阪府", isCorrect: false },
        { answerText: "香川県", isCorrect: true }
      ]
    }
  ];

  const [current, setCurrent] = useState(0);
  const [showFinish, setShowFinish] = useState(false);

  const check = (isCorrect) => {
    if (isCorrect === true) {
      alert("正解");
    } else {
      alert("不正解");
    }

    const nextQuestion = current + 1;
    if (nextQuestion < questions.length) {
      setCurrent(nextQuestion);
    } else {
      setShowFinish(true);
    }
  };
  return showFinish ? (
    <p>終わり</p>
  ) : (
    <div className="quiz_wrap">
      <p>第1問</p>
      <p>{questions[current].questionText}</p>
      <ul>
        {questions[current].answerOptions.map((answer, key) => (
          <li key={key} onClick={() => check(answer.isCorrect)}>
            {answer.answerText}
          </li>
        ))}
      </ul>
    </div>
  );
}

5. 正解数の表示

最後のクイズが終わった後に、何問正解できたかを表示します。

ここもReactを使って制御していきます。

正解したらscoreの中に+1されるようにし、「終わり」ではなく「3問中◯問正解」となるようにします。

import { useState } from "react";
import "./styles.css";

export default function App() {
  const questions = [
    {
      questionText: "日本で一番高い山は?",
      answerOptions: [
        { answerText: "富士山", isCorrect: true },
        { answerText: "阿蘇山", isCorrect: false },
        { answerText: "高尾山", isCorrect: false }
      ]
    },
    {
      questionText: "世界で一番高い山は?",
      answerOptions: [
        { answerText: "モンブラン", isCorrect: false },
        { answerText: "エベレスト", isCorrect: true },
        { answerText: "ティラミス", isCorrect: false }
      ]
    },
    {
      questionText: "日本で一番小さい都道府県は?",
      answerOptions: [
        { answerText: "東京都", isCorrect: false },
        { answerText: "大阪府", isCorrect: false },
        { answerText: "香川県", isCorrect: true }
      ]
    }
  ];

  const [current, setCurrent] = useState(0);
  const [showFinish, setShowFinish] = useState(false);
  const [score, setScore] = useState(0);

  const check = (isCorrect) => {
    if (isCorrect === true) {
      alert("正解");
      setScore(score + 1);
    } else {
      alert("不正解");
    }

    const nextQuestion = current + 1;
    if (nextQuestion < questions.length) {
      setCurrent(nextQuestion);
    } else {
      setShowFinish(true);
    }
  };
  return showFinish ? (
    <p>3問中{score}問正解</p>
  ) : (
    <div className="quiz_wrap">
      <p>第{score + 1}問</p>
      <p>{questions[current].questionText}</p>
      <ul>
        {questions[current].answerOptions.map((answer, key) => (
          <li key={key} onClick={() => check(answer.isCorrect)}>
            {answer.answerText}
          </li>
        ))}
      </ul>
    </div>
  );
}

以上が3択クイズのReactでの実装になります。