You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJs问答应用提交分数至API时userScore始终为0解决方案

React问答应用提交userScore始终为0问题修复

核心问题定位

分数提交始终为0是React状态异步更新+函数返回值缺失+执行时序错误三个问题叠加导致的:

  • React的useState状态更新不是同步生效的,调用setScoreAfterQuiz后,当前函数执行栈内读到的scoreAfterQuiz还是更新前的初始值0,新值要等组件下一次重渲染才会生效。在调用handleScore后立刻执行addScore时,addScore读到的scoreAfterQuiz必然是0。
  • 现有handleScore只做了内部计数和状态更新,没有返回计算结果,const scoreResult = handleScore()拿到的实际是undefined,后续setScore、addScore传这个值本身就不符合逻辑。
  • 提交函数里重复调用了两次handleScore,做无意义的重复计算,还可能触发重复的状态更新。
  • 附带问题:百分比计算逻辑写的过于绕,((s*10)/questions.length)*10完全可以简化为s/questions.length * 100,可读性更高,不容易出计算偏差。

分步修复方案

1. 改造计分函数,直接返回计算结果

修改handleScore,保证计算逻辑正确的同时,把最终得分作为返回值传出,不需要等状态更新就能拿到结果:

const handleScore = () => {
  let correctCount = 0
  for(let i = 0; i < questions.length; i++){
    // 替换==为===做严格相等判断,避免隐式类型转换导致的判题错误
    if(questions[i].answer === myAnswers[i]){
      correctCount++
    }
  }
  // 简化百分比计算逻辑,直接得到百分制得分
  const finalScore = Math.round(correctCount / questions.length * 100)
  // 更新页面展示用的状态
  setScoreAfterQuiz(finalScore)
  // 关键:返回计算好的分数,供提交逻辑直接使用
  return finalScore
}

2. 调整提交函数逻辑,去掉重复调用

修改handleSubmitScoreAndName,只执行一次计分逻辑,直接拿到分数结果用于后续操作,不要依赖状态更新:

const handleSubmitScoreAndName = (event) => {
  event.preventDefault();
  handleChange(event);
  setDisplayName(event.target.value);
  // 仅执行一次计分,直接拿到最终得分
  const scoreResult = handleScore();
  setScore(scoreResult)
  // 把分数作为参数传入提交方法,不依赖组件状态
  addScore(scoreResult)
  handleSubmit(event);
}

3. 改造接口提交函数,接收外部传入的分数

修改addScore接收分数参数,直接用传入的正确分数组装请求参数,彻底避免读取旧状态的问题:

// 增加入参接收计算好的分数
const addScore = (userScore) => {
   const newScore = {
    displayName:displayName,
    userScore: userScore, // 直接使用传入的正确分数
    quizId, 
    appUserId:auth.user.appUserId
  };
  console.log(newScore)
  const init = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${auth.user.token}`
    },
    body: JSON.stringify(newScore)
  };

  fetch('http://localhost:8080/api/score', init)
    .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(`/finalscore`); 
      } else {
        setErrors(data);
      }
    })
    .catch(console.log);
};

补充说明

如果后续有逻辑必须依赖状态更新后的值执行,可以用useEffect监听对应状态的变化再触发逻辑,但当前提交场景下,直接使用函数返回值是时序最稳定、代码最简洁的方案,完全可以避开React状态异步更新带来的坑。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 13:06:30