今回作るアプリ
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
ブラウザが自動で起動し下記の画面が表示されます。
アプリ作成の準備
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に解説動画をアップロードしようと思います。
コメント