如何解决状态在useState的函数之间不存在
我正在练习React useState挂钩以每个问题十秒钟的计时器进行测验。
目前,我能够从API中获得测验问题,将其设置为状态并进行渲染。如果用户单击一个答案,则问题将从处于状态的数组中删除,处于状态的秒数将重置为10,并呈现下一个问题。
我试图让计时器清除状态数组中什么都没剩下的时间。当我在startTimer函数中使用console.log(questions)时,它是一个空数组,尽管同一console.log在userAnswer函数中显示了数据?我在这里想念什么?
我删除了引用的随机播放功能以节省空间
inputElem = browser.find_element_by_xpath('/html/body/ytd-app/div/div/ytd-masthead/div[3]/div[2]/ytd-searchbox/form/div/div[1]/input')
inputElem.send_keys('election')
解决方法
App
的每个渲染都将为其内部函数和变量(如questions
和startTimer
)创建新的绑定。
单击按钮并运行getQuestions
时,getQuestions
然后调用startTimer
函数。在那个时间点,startTimer
函数关闭了在单击按钮时定义的questions
变量-但它为空。在间隔内,尽管函数已重新呈现,但间隔回调仍在旧闭包中引用questions
。
如果填充了setTimeout
数组,我会在渲染时启动useLayoutEffect
(在questions
内部,这样就可以清除超时,而不是依赖于旧的闭包)。
另一个问题是splice
不应该与React一起使用,因为变异现有数组-改用非变异方法,例如slice
。
尝试以下操作:
// Get data,set questions to state,start timer
const getQuestions = async () => {
let trivia = await axios.get("https://opentdb.com/api.php?amount=10&category=9&difficulty=easy&type=multiple")
trivia = trivia.data.results
trivia.forEach(result => {
result.answers = shuffle([...result.incorrect_answers,result.correct_answer])
})
setQuestions(trivia);
setSeconds(10);
}
useLayoutEffect(() => {
if (!questions.length) return;
// Run "timer" if the quiz is active:
const timeoutId = setTimeout(() => {
setSeconds(time => time - 1);
},1000);
return () => clearTimeout(timeoutId);
});
// If quiz is active and time has run out,mark this question as wrong
// and go to next question:
if (questions.length && time < 1) {
setIncorrect(wrong => wrong + 1)
setQuestions(q => q.slice(1));
setSeconds(10);
}
if ((correct || incorrect) && !questions.length) {
// Quiz done
console.log("test")
}
,
这是因为closure。
getQuestions
执行此部分时:
setQuestions(trivia)
startTimer()
两个函数都在相同的渲染周期中运行。在此循环中,questions
仍为[]
(或之前保存的任何值)。因此,当您在console.log(questions)
内调用startTimer
时,将得到一个空数组。
您可以通过在下一个渲染周期中使用startTimer
调用useEffect
来解决此问题
const [ start,setStart ] = useState(false)
const getQuestions = async () => {
let trivia = await axios.get("https://opentdb.com/api.php?amount=10&category=9&difficulty=easy&type=multiple")
trivia = trivia.data.results
trivia.forEach(result => {
result.answers = shuffle([...result.incorrect_answers,result.correct_answer])
})
setQuestions(trivia)
setStart(true)
}
useEffect(()=>{
if (start) {
startTimer();
setStart(false)
}
},[start])
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。