React.js问答游戏如何通过REST API提交计算后的分数至MySQL
问答游戏REST API分数提交方案
你不需要生硬绑定两个独立函数到onClick事件,这里有个很容易踩的坑:React的setScore是异步更新状态的,如果点击时先调handleScore再立刻调addScore,addScore里读取到的score还是更新前的旧值,直接提交会存错分数。
推荐直接合并逻辑,把计算和提交串成完整的提交流程,也可以用状态监听的方式拆分逻辑,两种实现如下:
- 方案1:直接合并函数(逻辑最清晰,优先选)
计算完分数后,直接用计算得到的最终值更新状态、发起请求,完全避开状态异步的问题:
把按钮的onClick直接绑定这个合并后的函数即可:const handleSubmit = () => { // 计算最终得分 let correctCount = 0 for(let i = 0; i < questions.length; i++){ if(questions[i].answer == myAnswers[i]){ correctCount++ } } const finalScore = ((correctCount * 10) / questions.length) * 10 // 更新本地状态供页面展示 setScore(finalScore) // 直接拿计算好的分数发请求,不等状态异步更新 const requestConfig = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${auth.user.token}` }, body: JSON.stringify(finalScore) }; fetch(`http://localhost:8080/api/score/${scoreId}`, requestConfig) .then(response => { if (response.status === 201 || response.status === 400) { return response.json(); } else { return Promise.reject(`Unexpected status code: ${response.status}`); } }) .then(data => { if (data.scoreId) { history.push({pathname: `/score/${scoreId}`, state: { scoreId: scoreId }}); } else { setErrors(data); } }) .catch(console.log); };<button onClick={handleSubmit}>Submit</button> - 方案2:拆分逻辑+状态监听(适合需要复用计算逻辑的场景)
如果你一定要把计算和提交拆成两个独立函数,不要在点击事件里顺序调用两个函数,而是用useEffect监听分数状态的更新,等分数确实更新到state里之后再触发提交:
这种写法按钮依然可以绑定原来的// 新增提交状态标记,避免重复触发请求 const [isSubmitting, setIsSubmitting] = useState(false) const handleScore = () => { let correctCount = 0 for(let i = 0; i < questions.length; i++){ if(questions[i].answer == myAnswers[i]){ correctCount++ } } setScore(((correctCount*10)/questions.length)*10) setIsSubmitting(true) } // 监听分数和提交标记变化,满足条件再发请求 useEffect(() => { if (!isSubmitting || score === undefined) return const requestConfig = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${auth.user.token}` }, body: JSON.stringify(score) }; fetch(`http://localhost:8080/api/score/${scoreId}`, requestConfig) .then(response => { if (response.status === 201 || response.status === 400) { return response.json(); } else { return Promise.reject(`Unexpected status code: ${response.status}`); } }) .then(data => { setIsSubmitting(false) if (data.scoreId) { history.push({pathname: `/score/${scoreId}`, state: { scoreId: scoreId }}); } else { setErrors(data); } }) .catch(err => { setIsSubmitting(false) console.log(err) }); }, [score, isSubmitting])handleScore,但逻辑链路更长,没有特殊需求优先选第一种合并的写法。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

