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

React.js问答游戏如何通过REST API提交计算后的分数至MySQL

问答游戏REST API分数提交方案

你不需要生硬绑定两个独立函数到onClick事件,这里有个很容易踩的坑:React的setScore是异步更新状态的,如果点击时先调handleScore再立刻调addScore,addScore里读取到的score还是更新前的旧值,直接提交会存错分数。
推荐直接合并逻辑,把计算和提交串成完整的提交流程,也可以用状态监听的方式拆分逻辑,两种实现如下:

  • 方案1:直接合并函数(逻辑最清晰,优先选)
    计算完分数后,直接用计算得到的最终值更新状态、发起请求,完全避开状态异步的问题:
    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);
    };
    
    把按钮的onClick直接绑定这个合并后的函数即可:
    <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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 08:57:20