目前我正在做一个由多个类别组成的测试,可以由用户选择,我想检查用户是否回答了所有问题。为了做到这一点,我将他回答的问题数量与api回复给出的问题数量进行了比较。问题是我有一个"提交答案"。按钮,使用onClick函数:
const sendAnswers = (e, currentQuiz) => {
setQuizzes({...quizzes, [currentQuiz]:answers});
setAnswers([])
var answeredToAllQuestions = true
DataState.map(function (quiz) {
if(quiz.category in quizzes){
if(Object.keys(quiz.questions).length !== Object.keys(quizzes[quiz.category]).length){
answeredToAllQuestions=false;
}
}
});
if(answeredToAllQuestions === false){
setAlertTrigger(1);
}
else{
setNumber(number+1);
}
}
在这个函数中,我在这行:setQuizzes({...quizzes, [currentQuiz]:answers});
上使用setState来上传他在最后一个问题上检查的答案,然后检查他是否回答了所有问题。问题是,quizzes的状态不会立即更新,也不会被if条件看到。
我真的不知道我应该如何在设置后立即更新状态,因为,据我所知,react useState在下一次重新渲染时更新状态,这会给我带来麻烦。
考虑到quizzes
将等于{...quizzes, [currentQuiz]:answers}
(在setQuizzes
将其设置之后),在此条件下没有理由使用quizzes
。用本地变量替换它,问题就解决了。
const sendAnswers = (e, currentQuiz) => {
let futureValueOfQuizzes = {...quizzes, [currentQuiz]:answers}
setQuizzes(futureValueOfQuizzes);
setAnswers([])
var answeredToAllQuestions = true
DataState.map(function (quiz) {
if(quiz.category in futureValueOfQuizzes){
if(Object.keys(quiz.questions).length !== Object.keys(quizzes[quiz.category]).length){
answeredToAllQuestions=false;
}
}
});
if(answeredToAllQuestions === false){
setAlertTrigger(1);
}
else{
setNumber(number+1);
}
}
我想借此机会说,当你使用React状态的BI逻辑时,这些类型的问题就会出现。别这样!最好使用在组件体中定义的局部变量:
const Component = () => {
const [myVar , setMyVar] = useState();
let myVar = 0;
...
}
如果myVar
仅用于BI逻辑,则使用第二个初始化,而不是第一个!
当然有时候你需要一个在BI逻辑和渲染中的变量(所以状态是唯一的方法)。在这种情况下,适当地设置状态,但对于脚本逻辑使用本地变量。
您必须将useState
钩子与useEffect
结合起来,或者更新您的sendAnswers
方法以通过中间变量执行控制流:
-
使用临时变量存储下一个状态:
const sendAnswers = (e, currentQuiz) => { const newQuizzes = {...quizzes, [currentQuiz]:answers}; let answeredToAllQuestions = true DataState.map(function (quiz) { if(quiz.category in newQuizzes){ if (Object.keys(quiz.questions).length !== Object.keys(newQuizzes[quiz.category]).length){ answeredToAllQuestions = false; } } }); setQuizzes(newQuizzes); setAnswers([]); if (answeredToAllQuestions === false) { setAlertTrigger(1); } else { setNumber(number+1); } }
-
使用
useEffect
钩子:const sendAnswers = (e, currentQuiz) => { setQuizzes({...quizzes, [currentQuiz]:answers}); setAnswers([]); } useEffect(() => { let answeredToAllQuestions = true DataState.map(function (quiz) { if(quiz.category in quizzes){ if (Object.keys(quiz.questions).length !== Object.keys(quizzes[quiz.category]).length){ answeredToAllQuestions = false; } } }); if (answeredToAllQuestions === false) { setAlertTrigger(1); } else { setNumber(number+1); } }, [quizzes]);