我正在创建一个测试页面,该页面使用
useEffect
钩提取的数据包括问题和选项,这些选项是多选的。我有一个
Check Answer
按钮,单击时显示用户的最终分数。我还有一个
Play Again
按钮,该按钮在呈现用户的分数后显示。
当用户点击
再次播放
按钮,本应获取另一个测验数据,但当
检查答案
按钮被按下。我的意思是,当用户点击
检查答案
按钮,它会显示分数(好),但随后整个页面会过早地重新呈现,因此用户看不到他们错了和对了的选项。单击
再次播放
按钮还重新呈现测试页面,这是预期的行为。我有
playAgain
state设置为useEffect的依赖数组,以便在状态更改时可以重新呈现测验。但我认为这就是问题的原因。
另一件事——不知道我是否应该把它作为一个不同的问题来问,但我会把它包括在这里——是当用户点击每个问题的正确选项时,选项会被重新排列。这可能不是什么大不了的事,但我认为我需要修复它来提高用户体验。我猜这和
checkEachAnswer
功能,但我不知道它出了什么问题。
任何可能出错的想法。谢谢
下面测验组件的代码。
export default function Quiz() {
const [quiz, setQuiz] = useState(null);
const [playAgain, setPlayAgain] = useState(false);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
const [userAnswer, setUserAnswer] = useState(() => []);
const [showAnswer, setShowAnswer] = useState(false);
const [showAnswerBtn, setShowAnswerBtn] = useState(true);
// This hook fetches data once
// Added error handling to prevent errors filling up the UI
useEffect(() => {
fetch("https://opentdb.com/api.php?amount=5&category=18&difficulty=hard&type=multiple")
.then(result => {
if (!result.ok) {
throw new Error("This is an HTTP error", result.status);
}
else {
return result.json();
}
})
.then(data => {
setQuiz(data.results);
console.log("Quiz data stored", data);
console.log(quiz);
return quiz && console.log("This is quiz data", quiz);
})
.catch(error => {
console.error("An error occurred!", error);
setQuiz(null);
setError(true);
})
.finally(() => {
setLoading(false);
});
}, [playAgain])
const quizElements = quiz && quiz.map(eachQuiz => {
const incorrectOptions = eachQuiz.incorrect_answers;
const correctOption = quiz && eachQuiz.correct_answer;
let options = [];
options = incorrectOptions.concat(correctOption);
function createRandomOptions(arr) {
let copyOptions = [...arr];
let randomOptionsArr = [];
while (copyOptions.length > 0) {
let randomIndex = Math.floor(Math.random() * copyOptions.length);
randomOptionsArr.push(copyOptions[randomIndex]);
copyOptions.splice(randomIndex, 1);
}
return randomOptionsArr;
}
let randomOptions = createRandomOptions(options);
return (
<>
<div className="quiz-wrapper">
<p className="question">{eachQuiz.question}</p>
<ul>
{quiz && randomOptions.map((option, index) =>
{
// Checks if the clicked option is the correct one and also checks if it was already picked before and prevents it from being added to the userAnswer array
function checkEachAnswer() {
if (option === correctOption) {
console.log("Correct");
if (userAnswer.includes(option)) {
let userAnsArrCopy = [...userAnswer];
let index = userAnsArrCopy.findIndex(elem => elem);
userAnsArrCopy[index] = option;
setUserAnswer(prevValue => {
return userAnsArrCopy;
});
}
else {
setUserAnswer(prevValue => {
return [...prevValue, option];
});
}
}
else {
console.log(option, "Is incorrect", );
}
}
return (
<li
key={option}
className="option"
onClick={() => checkEachAnswer()}
>
{option}
</li>
)
})
}
</ul>
</div>
</>
)
});
console.log(userAnswer);
function displayAnswer() {
setShowAnswer(true);
setPlayAgain(true);
setShowAnswerBtn(false);
}
function updatePlayAgain() {
setPlayAgain(false);
setShowAnswer(false);
setShowAnswerBtn(true);
setUserAnswer([]);
}
return (
<>
{loading && <h3>Currently loading...</h3>}
{error && <h3>An error occurred while fetching data!</h3>}
{quiz && <h1 className="topic">Topic: Computer Science</h1>}
{quiz && quizElements}
{showAnswer && <p>You scored {userAnswer.length} / {quiz.length}</p>}
{quiz && showAnswerBtn &&
<button
onClick={() => displayAnswer()}
className="main-btn"
>
Check Answer
</button>
}
{quiz && playAgain &&
<button
onClick={() => updatePlayAgain()}
className="main-btn"
>
Play Again
</button>
}
</>
)
}
如果问题不是我的测验组件,我也会包括应用程序组件。
import { useState } from "react";
import Quiz from "./components/Quiz";
const quizId = [
{"id": 0},
{"id": 1},
{"id": 2},
{"id": 3},
{"id": 4},
]
export default function App() {
const [startQuiz, setStartQuiz] = useState(false);
function loadQuiz() {
console.log(startQuiz);
setStartQuiz(true);
}
return (
<>
{!startQuiz &&
<div className="intro-container">
<div className="intro-screen">
<h1>Quiz My Heart</h1>
<button className="start-btn" onClick={loadQuiz}>
Go to Quiz
</button>
</div>
</div>}
{startQuiz &&
<main>
<Quiz key={quizId.map(myId => myId.id)}/>
</main>
}
</>
);
}