React強化月間 5日目
余談
自分はゲームやアニメ以外に興味がなく、友人も限られていましたが共通の話題で話をするって楽しいですね。
社会人の時に仕事について話すことはあっても立場や熱量、知識の違いから会話がかみ合わず楽しいと思ったことはありませんでした。
スクールの交流会やdisco、note、X等で夢に向かってる前向きな知り合いが増えていくのがすごく楽しいです。
早く先輩達と同じレベルで会話が出来るようになるぞ😉
今日の課題
昨日の問題数が減らない問題の見直しから。
問題数を少なくして挙動を見ていく。

randomにする関数を一度削除して、0から順番に削除していく。

うまくいってる。
randomの指定が原因。

これを・・・こうじゃ!

spliceの第一引数(削除する場所)は単純にrandomでした。
変更前は引数が初期値questionになってます。
randomは2行後の setRandom で新しい配列の長さからランダムな数字に更新されているので、randomを指定すればrandomの問題が削除されます。
ここで一つ沼にハマりました。


newRestQuestionsをrestQuestionsに変えたらエラーが出ました。
一つ前の行でrestQuestionsをnewRestQuestionsに更新してるのに何で結果が変わるの!?
と悩んでいましたが、GPTに聞いたところ以下の回答でした。
setRestQuestions(newRestQuestions);を呼び出した直後にrestQuestionsの長さをログに記録しても、restQuestionsはまだ更新されていません。setRestQuestionsは非同期に実行されるため、ステートが即座に更新されるわけではありません。したがって、console.log(restQuestions.length);を実行した時点では古い値が表示されます。
ステートの更新が反映されるのは次のレンダリングサイクルのタイミングです。そのため、更新後の値を確認するにはuseEffectフックを使うなど、ステートが更新されたことを検知する別の手段を用いる必要があります。
修正するために、restQuestionsの長さを直接使用する代わりにnewRestQuestionsの長さを使用します。
ということで、「非同期」というワードでピンときましたがuseEffect内だからまだrestQuestionsが更新されていない、ということですね。
いやぁーたぶん「React初心者あるある」なんでしょうね。
初心者が成長している感じがして嬉しいですね。
import React, { useState, useEffect } from 'react';
import { QuestionList } from './QuestionList';
const questions = QuestionList();
console.log(questions[3].answers[0]);
function getRandomInt(max: number) {
return Math.floor(Math.random() * max);
}
const shuffleArray = array => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * i);
[array[i], array[j]] = [array[j], array[i]];
}
return array;
};
const Question = () => {
const [random, setRandom] = useState(getRandomInt(questions.length));
const [restQuestions, setRestQuestions] = useState(questions);
const [selectQuestions, setSelectQuestions] = useState('');
const [selectAnswer, setSelectAnswer] = useState('');
const [flag, setFlag] = useState(false);
const [message, setMessage] = useState('');
useEffect(() => {
if (restQuestions.length > 0) {
const newRestQuestions = [...restQuestions];
newRestQuestions.splice(random, 1);
setRestQuestions(newRestQuestions);
setSelectAnswer(shuffleArray(restQuestions[random].answers));
setSelectQuestions(restQuestions[random].question);
} else {
setSelectQuestions('これ以上質問はありません');
}
}, []);
console.log(questions[random].answers[0]);
const handleAnswerClick = answer => {
const currentQuestion = restQuestions[random];
console.log(answer);
console.log(currentQuestion.answers[0]);
if (answer == currentQuestion.answers[0]) {
setMessage('正解');
console.log(`正解`);
}else{
setMessage('不正解');
console.log(`不正解`);
}
};
return (
<>
<div className=" flex flex-col justify-center items-center h-96 pt-10">
<div className="w-5/6 h-80">{selectQuestions}</div>
<button
className="w-60 border-4 border-current text-center mb-2"
onClick={() => {
setFlag(!flag);
handleAnswerClick(selectAnswer[0]);
}}
>
{selectAnswer[0]}
</button>
<button
className="w-60 border-4 border-current text-center mb-2"
onClick={() => {
setFlag(!flag);
handleAnswerClick(selectAnswer[1]);
}}
>
{selectAnswer[1]}
</button>
<button
className="w-60 border-4 border-current text-center mb-2"
onClick={() => {
setFlag(!flag);
handleAnswerClick(selectAnswer[2]);
}}
>
{selectAnswer[2]}
</button>
<button
className="w-60 border-4 border-current text-center mb-2"
onClick={() => {
setFlag(!flag);
handleAnswerClick(selectAnswer[3]);
}}
>
{selectAnswer[3]}
</button>
<div>{message}</div>
</div>
</>
);
};
export default Question;
それからなんやかんやでこんな感じに

今日できたこと
問題数を減らしていく
選択肢をランダムにして問題にセットする
出来なかった
正解を選んでも正解にならない
正解は問題のanswers[0]に入っているけど、randomでシャッフルしてしまうので正解が指定できない。
指定しても次の問題が選ばれてしまって次の問題の解答が条件になってしまう。
何か手があるんだろうけど色々やってもうまくいかない。
明日はもう一度分解しながら考える・・・解決出来るといいな。