我一直在尝试使用React制作一个测验应用程序,作为课程项目的一部分,我真的很难保存用户选择的答案的状态。
从API返回的数据显示由一组问题和每个问题的一组答案组成的数据。
我对如何在问题中循环答案数组感到困惑,特别是针对每个答案的id和isSelected布尔值,以便我可以针对这些ID并使用条件逻辑,当用户选择答案按钮时,它将触发isSelected布尔值为true并更改按钮的背景颜色。
这显示了我的数据数组,其中包含问题和答案选择的数组,沿着用于触发按钮保持状态的布尔值:
export default function QuizList(props) {
const [quiz, setQuiz] = React.useState([]);
React.useEffect(() => {
/* This function turns HTML element entities into normal words */
function decodeHtml(html) {
const txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
}
fetch(
"https://opentdb.com/api.php?amount=5&category=9&difficulty=medium&type=multiple"
)
.then((res) => res.json())
.then((data) => {
const dataArray = data.results;
const newDataArray = [];
dataArray.map((item) => {
return newDataArray.push({
question: decodeHtml(item.question),
correct: decodeHtml(item.correct_answer),
choices: [
{
choice: decodeHtml(item.correct_answer),
isSelected: false,
id: nanoid(),
},
{
choice: decodeHtml(item.incorrect_answers[0]),
isSelected: false,
id: nanoid(),
},
{
choice: decodeHtml(item.incorrect_answers[1]),
isSelected: false,
id: nanoid(),
},
{
choice: decodeHtml(item.incorrect_answers[2]),
isSelected: false,
id: nanoid(),
},
].sort(() => 0.5 - Math.random()),
id: nanoid(),
});
});
return setQuiz(newDataArray);
});
}, []);
下面是保存所选答案的函数,其中包含要呈现的组件:
function holdAnswer(id) {
setQuiz((oldQuiz) =>
oldQuiz.map((quiz) => {
return quiz.choices.map((choice) => {
return choice.id === id
? { ...choice, isSelected: !choice.isSelected }
: choice;
});
})
);
}
const quizItemComponents = quiz.map((item) => {
return (
<QuizItem
key={item.id}
question={item.question}
choices={item.choices}
holdAnswer={() =>
holdAnswer(item.choices.forEach((choice) => choice.id))
}
/>
);
});
return (
<Card className={classes.quizlist}>
{quizItemComponents}
<Button>Check Answers</Button>
</Card>
);
}
此外,下面的代码显示了各个测验组件将包含的内容以及其中的条件逻辑:
export default function QuizItem(props) {
const isSelected = props.choices.forEach(choice => choice.isSelected)
const styles = {
backgroundColor: isSelected ? "#D6DBF5" : "white",
};
return (
<div>
<div key={props.id} className={classes.quizlist__quizitem}>
<h3 className={classes.quizitem__h3}>{props.question}</h3>
{props.choices.map((choice) => {
return (
<AnswerButton
key={choice.id}
onClick={props.holdAnswer}
style={styles}
>
{choice.choice}
</AnswerButton>
);
})}
</div>
</div>
);
}
下面是自定义应答按钮的代码:
import classes from "./AnswerButton.module.css";
export default function AnswerButton(props) {
return (
<button
className={classes.answerbutton}
type={props.type || "button"}
onClick={props.onClick}
style={props.style}
name={props.name}
>
{props.children}
</button>
);
}
我尝试过使用.forEach或.map()循环遍历答案数组以指向id和isSelected值,但最后都出现了错误。我尝试过很多其他方法,通过移动对象,但都没有效果。我不确定我是否没有正确地循环遍历答案数组,或者我是否需要其他方法来循环遍历它,或者在正确的区域插入适当的循环。
1条答案
按热度按时间g6baxovj1#
在第二个块代码中,
setQuiz
似乎将每个quiz
设置为oldQuiz.map()
中的唯一choices
,可能预期返回值应该是{...quiz, choices}
。另外,
holdAnswer(id)
所需的id
似乎是choice.id
,所以QuizItem
的预期行为可能只是将此函数作为prop传递,并让choice
提供其id
。然后在第三个代码块中,
styles
的预期条件似乎基于每个choice.isSelected
,因此可能可以将其移到props.choices.map()
中。同样在这里,每个
choice
可能应该在它们的onClick
中传递id
,以便holdAnswer
使用,因为AnswerButton
似乎没有访问此id
的权限。可能还有其他需要解决的问题,如果不进行测试,可能很难发现,但希望这仍然有帮助。