我是React的新手,正在做测验。我现在想做的就是在遇到新问题时将类名重置为初始状态。我想我想使用componentDidUpdate,但不确定如何工作。
componentDidUpdate() {
this.setState({
classNames: ["", "", "", ""]
});
}
这是完整的组件代码:
class Answers extends React.Component {
constructor(props) {
super(props);
this.state = {
isAnswered: false,
classNames: ["", "", "", ""]
};
this.checkAnswer = this.checkAnswer.bind(this);
}
checkAnswer(e) {
let { isAnswered } = this.props;
if (!isAnswered) {
let elem = e.currentTarget;
let { correct, increaseScore } = this.props;
let answer = Number(elem.dataset.id);
let updatedClassNames = this.state.classNames;
if (answer === correct) {
updatedClassNames[answer - 1] = "right";
increaseScore();
} else {
updatedClassNames[answer - 1] = "wrong";
}
this.setState({
classNames: updatedClassNames
});
this.props.showButton();
}
}
componentDidUpdate() {
this.setState({
classNames: ["", "", "", ""]
});
}
render() {
let { answers } = this.props;
let { classNames } = this.state;
return (
<div id="answers">
<ul>
<li onClick={this.checkAnswer} className={classNames[0]} data-id="1">
<p>{answers[0]}</p>
</li>
<li onClick={this.checkAnswer} className={classNames[1]} data-id="2">
<p>{answers[1]}</p>
</li>
<li onClick={this.checkAnswer} className={classNames[2]} data-id="3">
<p>{answers[2]}</p>
</li>
<li onClick={this.checkAnswer} className={classNames[3]} data-id="4">
<p>{answers[3]}</p>
</li>
</ul>
</div>
);
}
}
export default Answers;
感谢您的帮助!自从我正在学习以来,对整个代码项目的反馈也非常感谢。
下面是整个项目的链接:
答案 0 :(得分:1)
对此有一个简单的解决方法(建议作为React最佳实践),如果您更改答案的key
,则可以进行演示:https://codesandbox.io/s/another-quiz-wgycs
<Answers
key={question} // <-- oh hi
answers={answers}
correct={correct}
...
理想情况下,您应该使用id
,并且由于大多数现代数据结构都具有id,因此使用key={question_id}
是理想的,因为密钥必须是唯一的:
{
id: 1
question: 'What does CSS stand for?',
answers: [...],
correct: 3
},
{
id: 2,
....
}
如果没有,则必须使用prevProps
:
componentDidUpdate(prevProps) {
if (this.props.question !== prevProps.question) {
this.setState(....)
}
}
我真的建议使用key
方法,因为这将强制创建新的组件,实际上,如果您需要不断检查更改道具的情况,那么跟踪变得有些困难。
请记住,理想情况下应该有一个id
,因为如果问题文本相同,则将导致令人讨厌的难以发现的错误。
此外,最好保存selected
作为索引并在render方法上选择正确的类名,而不是保存类名。
答案 1 :(得分:0)
首先,您必须添加一个按钮来重置类名称,并且该按钮将调用用于重置它们的函数,例如:
import React from "react";
class Answers extends React.Component {
constructor(props) {
super(props);
this.state = {
isAnswered: false,
classNames: ["", "", "", ""]
};
}
checkAnswer = e => {
let { isAnswered } = this.props;
if (!isAnswered) {
let elem = e.currentTarget;
let { correct, increaseScore } = this.props;
let answer = Number(elem.dataset.id);
let updatedClassNames = this.state.classNames;
if (answer === correct) {
updatedClassNames[answer - 1] = "right";
increaseScore();
} else {
updatedClassNames[answer - 1] = "wrong";
}
this.setState({
classNames: updatedClassNames
});
this.props.showButton();
}
};
reset = () => {
this.setState({
isAnswered: false,
classNames: ["", "", "", ""]
});
};
render() {
let { answers } = this.props;
let { classNames } = this.state;
return (
<div id="answers">
<button onClick={this.reset}>RESET</button>
<ul>
<li onClick={this.checkAnswer} className={classNames[0]} data-id="1">
<p>{answers[0]}</p>
</li>
<li onClick={this.checkAnswer} className={classNames[1]} data-id="2">
<p>{answers[1]}</p>
</li>
<li onClick={this.checkAnswer} className={classNames[2]} data-id="3">
<p>{answers[2]}</p>
</li>
<li onClick={this.checkAnswer} className={classNames[3]} data-id="4">
<p>{answers[3]}</p>
</li>
</ul>
</div>
);
}
}
export default Answers;
答案 2 :(得分:0)
componentDidUpdate()
在更新发生后立即被调用。初始渲染不调用此方法。
我最近遇到过这种情况。您必须使用componentDidUpdate() {}
中的相同代码。这就是我所做的。
componentDidUpdate(prevProps) {
if (this.props.questions !== prevProps.questions) {
const shuffledAnswerOptions = this.props.questions.map(question =>
question.answer_options &&
this.shuffleArray(question.answer_options)
);
this.setState({
current_question:this.props.questions &&
this.props.questions[0],
question_image_url: this.props.questions &&
this.props.questions[0] &&
this.props.questions[0].question_image_url,
answerOptions: shuffledAnswerOptions[0],
numberOfQuestions: this.props.questions &&
this.props.questions.length
});
}
}
您也可以prevSate
参数。
这是一个示例实现:
componentDidUpdate(prevProps, prevState) {
if(this.state.assignment !== prevState.assignment){
document.getElementById(prevState.assignment.id) && document.getElementById(prevState.assignment.id).classList.remove("headactiveperf");
}
if(this.state.assessment !== prevState.assessment){
document.getElementById(prevState.assessment.id) && document.getElementById(prevState.assessment.id).classList.remove("headactiveperf");
}
if(this.state.study_group_id !== prevState.study_group_id){
document.getElementById(prevState.study_group_id) && document.getElementById(prevState.study_group_id).classList.remove("klassactiveperf");
}
}
答案 3 :(得分:-1)
问题在于,如果您在componentDidUpdate
中更改状态,则会立即触发另一个更新,因此再次运行componentDidUpdate
并导致无限循环。因此,您应该将setState
移动到其他位置,或将其置于条件之后。例如:
componentDidUpdate() {
if (!this.state.classNames.every(className => className === "") { // Check if there is an item in the array which doesn't match an empty string ("")
this.setState({ // Only update state if it's necessary
classNames: ["", "", "", ""]
});
}
}
您可以找到更新的CodeSandbox here