まずは完成形を確認します。
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イベントを追加し、isCorrect
がtrue
なら正解、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
が配列にあるクイズの数より少なければ、setCurrent
に nextQuestion
を記憶させ、大きければ「終わり」と表示させます。
ここは三項演算子を使って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での実装になります。