MENU

Reactでクイズアプリを作る

目次

今回作るアプリ

Reactの環境構築

React プロジェクトの環境を構築するためには node.js がインストールされている必要があります。node -v コマンドを実行してバージョンが表示されない場合は node.js のインストールを行ってから React 環境の構築を行ってください。

以下のコマンドでReactプロジェクト作成 (コマンドプロンプト(windows)、またはターミナル(Mac)で入力)

quize-appがアプリ名です。お好き名前を付けてください

npx create-react-app quize-app

プロジェクト作成後、プロジェクトフォルダに移動して、ReactプロジェクトをVscodeで開きます

  cd quize-app
  code .

vsCodeが開きます。
その後、windowsの場合はCtr + J、Macの場合はCmd+ JでVscode上でターミナルを開きます

ターミナル上で以下のコマンドを入力し、Reactのサーバーを立ち上げます

npm start

ブラウザが自動で起動し下記の画面が表示されます。

画像に alt 属性が指定されていません。ファイル名: react_start-1024x497.png

アプリ作成の準備

App.jsファイルを開いて、中身をすべて消します。(App.jsはsrcフォルダの中にあります)
Reactのひな型を記述します。

import React from 'react'

const App = () => {
  return (
    <div>おはようございます!</div>
  )
}

export default App

ブラウザで確認するとdivタグの中身が表示される。文字は拡大しているので大きく見ています

クイズデータの準備

クイズの問題選択肢正解を含むデータ構造を作成します。この例では、配列にオブジェクトとして保存します。

import React from 'react'

const App = () => {
  return (
    <div>おはようございます</div>
  )
}
// 以下の行を追加
  const quizData = [
    {
      question: 'Reactはどの会社によって開発されましたか?',
      options: ['Facebook', 'Google', 'Microsoft', 'Amazon',"昭和","昭和","昭和",],
      correct: 'Facebook',
    },
    {
      question: 'ラーメンの消費量日本1位の都道府県は?',
      options: ['静岡県', '山形県', '新潟県', '北海道','埼玉県','沖縄県'],
      correct: '山形県',
    },
    {
      question: '世界幸福度ランキング1位の国は?',
      options: ['フィンランド', 'ベルギー', 'オーストラリア', 'スウェーデン'],
      correct: 'フィンランド',
    },
    {
      question: '最も長く続いた時代は',
      options: ['江戸', '安土・桃山', '奈良', '平安','昭和'],
      correct: '平安',
    },
    // 他の問題を追加
  ];
export default App

クイズロジックの実装

stateを定義する

まずstateで管理すべきものを洗い出します。stateとは【状態】という意味でアプリの中で状態が変わってい行くものをstateで管理します。

今回の場合stateで管理すべき項目は次の通りです。

  • 今現在何問目か管理するstate
  • スコアを管理するstate
  • スコアが表示される画面か判断するstate
  • 解答の合否を出力するstate(●か×か)
  • 各問題の質問文、選択肢、解答の合否を管理するstate
  • 回答画面か合否画面か判断するstate

ファイル上部でuseStateもインポートしているので注意してください

import React from 'react'
import React, { useState } from 'react'; // この行も追加
const App = () => {

    #今現在何問目か管理するstate
    const [currentQuestion, setCurrentQuestion] = useState(0);

    #スコアを管理するstate
    const [score, setScore] = useState(0);
    
    #スコアが表示される画面か判断するstate
    const [showScore, setShowScore] = useState(false);

    #解答の合否を出力するstate(●か×か)
    const [feedback, setFeedback] = useState(null);

    #各問題の質問文、選択肢、解答の合否を管理するstate
    const [answers, setAnswers] = useState([]);

    #回答画面か合否画面か判断するstate
    const [next, setNext] = useState(false);

  return (
    <div>おはようございます</div>
  )
}
//既存のコード

export default QuizApp;

stateの見方
const [score, setScore] = useState(0)

上記のstateの見方としては以下の通り
・score (stateの名前)
・setScore (stateの値を更新するときに使う)
・useState(0) (stateの値の初期値。この例では初期値は0)

Stateの更新方法
・setScore(1)

上記のようにstateを更新するとscoreの値が初期値の0から1に変わる。

アプリを操作したときのロジックを実装

アプリを操作処理としては2つあります

  • ユーザーが選択肢から解答したときの処理
  • 解答後に表示される【次の問題へ】ボタンを押したときの処理
import React from 'react'
import React, { useState } from 'react';
const App = () => {
    
    //既存のstateを定義したコード
  
  //ユーザーが選択肢から解答したときの処理
    const handleAnswer = (answer) => {

      let newAnswers;
    
      //現在の問題の答えを定数に格納
      const correctAnswer = quizData[currentQuestion].correct;
    
      //ユーザーの解答と実際の答えが一致していた場合の処理
      if (answer === correctAnswer) {
        setScore(score + 1);
        setFeedback('〇');
        newAnswers = { question: quizData[currentQuestion].question, answer, correct: true };
        
      } else {
        setFeedback('✕');
        newAnswers = { question: quizData[currentQuestion].question, answer, correct: false };
      }
      //answersというstateで定義した配列にnewanAnswersというオブジェクトをセットしている。
      setAnswers([...answers, newAnswers]);
    
      //合否画面にする(●か✕か出る画面)
      setNext(true);
    };
    
    // 【次の問題へ】ボタンを押したときの処理
    const goToNextQuestion = () => {
      const nextQuestion = currentQuestion + 1;
    
      if (nextQuestion < quizData.length) {
        setCurrentQuestion(nextQuestion);
      } else {
        setShowScore(true);
      }
    
      setFeedback(null);
      setNext(false);
    };

  return (
    <div>おはようございます</div>
  )

}

  // 既存のクイズデータコード

export default App
ユーザーが選択肢から解答したときの処理

大まかに以下の内容を行っています

  • 解答の合否によるロジックの実装
  • 画面を合否画面にする(●か✕か表示する画面)
解答後に表示される【次の問題へ】ボタンを押したときの処理
  • すべての問題を終えたかそうでないかによるロジックの実装
  • すべての問題を終えた場合はスコア画面に飛ぶ

クイズアプリの見た目を実装

return文の中の <div>おはようございます</div> を消して以下のコードに変更
ファイル上部でcssファイルもインポートしているので注意してください

jsx(return文の中のコード)では三項演算子を使って表示の出し分けをしています

  • スコア画面かどうかの判定
  • 選択肢を選んで解答したかの判定

三項演算子とは?

三項演算子は、条件 ? 値1 : 値2 のように書かれます。条件が true の場合には 値1 が、false の場合には 値2 が返されます。

今回のshowScoreの参考演算子で言うと以下のようになります。
{showScore ? (スコア画面の内容) : (クイズ解答画面の内容) }

cssを反映させるためにclassNameをつけていますが、気にしないでください。

import React, { useState } from 'react';
import './QuizApp.css';  

function QuizApp() {
  //既存のコード
 
  return (
    <div className="quiz-container">
       {showScore ? (
      <div className="score-section">
        <h1>Your Score:</h1>
        <h2 className="final-score">{score} / {quizData.length}</h2>
        <table className="answer-table">
          <thead>
            <tr>
              <th>Question</th>
              <th>Your Answer</th>
              <th>Correct?</th>
            </tr>
          </thead>
          <tbody>
            {answers.map((item, index) => (
              <tr key={index} className={item.correct ? 'correct' : 'wrong'}>
                <td className='question'>{item.question}</td>
                <td>{item.answer}</td>
                <td>{item.correct ? '●' : '×'}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      ) : (
        <div className='question-section'>
        <h1>Question {currentQuestion + 1} / {quizData.length}</h1>
        <h2>{quizData[currentQuestion].question}</h2>
        {next ? (
          <div className="feedback-section">
            <h2 className="large-feedback">{feedback}</h2>
            <button onClick={goToNextQuestion}>次の問題へ</button>
          </div>
        ) : (
          <div className="answer-section">
            {quizData[currentQuestion].options.map((option, index) => (
              <button className={`option-button option-${index}`} key={index} onClick={() => handleAnswer(option)}>
                {option}
              </button>
            ))}
          </div>
        )}
      </div>
    )}
  </div>
  );
}
//既存のクイズデータコード
export default QuizApp;

CSSの反映

App.jsと同じ階層にQuizeApp.cssという名前のcssファイルを作成し、以下のコードを張り付けてください。
先ほどのjsxのclassNameと一致していなければcssが反映されないので気を付けてください。

/* 全体を中央に配置するためのスタイル */
.quiz-container {
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;  /* Viewport Height */
    margin: 0 auto;
  }
  
  .question-section {
    padding: 20px;
    background: #f4f4f4;
    border-radius: 10px;
    width: 800px
  }
  
  h1 {
    color: #333;
    font-size: 2em;
  }
  
  .final-score {
    font-size: 3em;
    color: #007bff;
  }
  
  h2 {
    color: #666;
    font-size: 1.5em;
  }
  
  button {
    padding: 10px 20px;
    font-size: 1em;
    margin: 5px;
    cursor: pointer;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
  }
  
  
  .answer-list {
    list-style: none;
    padding: 0;
  }
  
  .answer-list li {
    margin: 10px 0;
    font-size: 1.2em;
  }
  
  .correct {
    color: green;
  }
  
  .wrong {
    color: red;
  }
  

.large-feedback {
    font-size: 2em;
    color: #007bff;
  }
  

  .answer-section {
    display: flex;
    flex-direction: column;
  }
  .option-0 {
    background-color: red;
  }
  
  .option-1 {
    background-color: green;
  }
  
  .option-2 {
    background-color: blue;
  }
  
  .option-3 {
    background-color: blueviolet;
  }
  .option-4 {
    background-color: tomato;
  }
  .option-5 {
    background-color: #ffaa00;
  }
  
  /* ボタンの共通スタイル */
  .option-button {
    padding: 10px 20px;
    font-size: 1em;
    margin: 5px;
    cursor: pointer;
    color: white;
    border: none;
    border-radius: 4px;

    box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
    transition: box-shadow 0.3s ease;
  }
  
  /* ホバーアクション */
  .option-button:hover {
    /* opacity: 0.8; */
    box-shadow: 0px 6px 8px rgba(0, 0, 0, 0.2);
  }


/* スコア画面のスタイル */
.score-section {
  background-color: #f4f4f4;
  padding: 20px;
  border-radius: 10px;
  max-width: 1400px;
  width: 80%;
}

.answer-table {
  width: 100%;
  border-collapse: collapse;
}

.answer-table thead {
  background-color: #007bff;
  color: white;
}

.answer-table th,
.answer-table td {
  border: 1px solid #ddd;
  padding: 12px;
}

.question {
  text-align: left;

}

.correct {
  background-color: #d4edda;
}

.wrong {
  background-color: #f8d7da;
}

これでクイズアプリが完成しました。

まとめ

このクイズアプリを作ることでReactで超重要な要素であるstateについて学びます。初心者の方には説明が難しいと感じたので近々YouTubeに解説動画をアップロードしようと思います。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次