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

React组件数据提交异常:数据库存储当前cargo与历史计算值问题求助

React组件数据存储问题解决方案

问题描述

以下是开发的React组件代码:

import './App.css';
import OutputBox from './OutputBox';
import React, { useState } from 'react';
import * as functions from "./functions.js"
import axios from 'axios'

function App() {
  //define state variables
  const [cargo, setCargo] = useState('');
  const [acceleration, setAcceleration] = useState('');
  const [takeoff_time, setTakeOffTime] = useState('');
  const [takeoff_distance, setTakeOffDistance] = useState('');
  const [excess_cargo, setExcessCargo] = useState('');
  const [date, setDate] = useState();
  const [message, setMessage] = useState('');


  //send the data to /insert-data in order to store it in the db
  const insertData = () => {
    axios.post("http://localhost:3001/insert-data", {
      takeoff_time: takeoff_time.toString(),
      takeoff_distance: takeoff_distance.toString(),
      excess_cargo: excess_cargo.toString(),
      cargo: cargo.toString()
  }).then(()=> {
  console.log("success");
  }).catch((error) => {
    console.error(error);
  });

  console.log(takeoff_time +" | "+ takeoff_distance+" | "+excess_cargo+" | "+cargo);
};




  //get the cargo data
  //return if the input is valid 
  const validInput = (cargo) => {
    
    if (cargo < 0 || isNaN(cargo)) {
      alert("invalid input!");
      return false;
    }
    else {
      return true;
    }

  }
  
  //A function that centralizes the actions
  const handleData = () => {
    if(validInput(cargo)){

      //update the variables every time it change
      setAcceleration(functions.getAcceleration(cargo));
      setTakeOffTime(functions.getTakeOffTime(cargo));
      setTakeOffDistance(functions.getTakeOffDistance(cargo));
      setExcessCargo(functions.getExcessCargo(cargo));

      //call the insert function
      insertData();
    }

  }

 //asynchronous func to handle the date data
const handleDate = async () => {
  try { //make a post request to send date data to the back-end
    const response = await axios.post("http://localhost:3001/date-picker", { date });
    setMessage(response.data); //set the changed value to the current variable
  }catch(error){ //trying to catch errors
    console.log(error);
  }
  
}


//prints to the web the data
  return (
    <div className='App'>
      <div className='data'>

    <h1>Shimshon physics calculator</h1>
    <label>Enter cargo weight:</label>
    <input type="number" onChange={ (event) => {setCargo(event.target.valueAsNumber)}}/>

    <button onClick={handleData}>Send data</button>

    <OutputBox text={`Acceleration: ${acceleration}`} />
    <OutputBox text={`Takeoff Time: ${takeoff_time}`} />
    <OutputBox text={`Takeoff Distance: ${takeoff_distance}`} />
    <OutputBox text={`Excess Cargo: ${excess_cargo}`} />
    

    
    <br />
    <label>Enter flight date:</label>
    <input type= "date" onChange={(event) => { setDate(event.target.value) }} />
    <button onClick={handleDate}>Send date</button>

    <OutputBox text={`you ${ message } able to filght`} />
      </div>
    </div>
  );
}

export default App;

运行时遇到的问题:

  • 输入货运重量并点击「Send data」按钮,数据库表中仅能接收到cargo值,takeoff_time、takeoff_distance、excess_cargo字段为空;
  • 再次输入货运重量并点击按钮,数据库中存储的是当前cargo值与上一次计算得到的takeoff_time、takeoff_distance、excess_cargo值。

原因分析

React中useState的更新是异步批量处理的,在handleData函数中,调用setTakeOffTime、setTakeOffDistance等更新state后,立刻执行insertData,此时组件的state还未完成更新,insertData读取到的是更新前的旧值(第一次点击时为空状态)。第二次点击时,state已经更新为第一次的计算结果,所以会带上上次的值。

解决方案

方案一:直接使用计算后的值发送请求(推荐)

先计算出所有需要的结果,将其存入变量,同时用这些变量更新state和发送请求,跳过依赖state异步更新的环节:

// 修改handleData函数
const handleData = () => {
  if(validInput(cargo)){
    // 先计算所有结果,存入变量
    const newAcceleration = functions.getAcceleration(cargo);
    const newTakeoffTime = functions.getTakeOffTime(cargo);
    const newTakeoffDistance = functions.getTakeOffDistance(cargo);
    const newExcessCargo = functions.getExcessCargo(cargo);

    // 更新state
    setAcceleration(newAcceleration);
    setTakeOffTime(newTakeoffTime);
    setTakeOffDistance(newTakeoffDistance);
    setExcessCargo(newExcessCargo);

    // 直接传入计算后的值调用insertData
    insertData(newTakeoffTime, newTakeoffDistance, newExcessCargo, cargo);
  }
}

// 修改insertData函数,接收参数
const insertData = (takeoff_time, takeoff_distance, excess_cargo, cargo) => {
  axios.post("http://localhost:3001/insert-data", {
    takeoff_time: takeoff_time.toString(),
    takeoff_distance: takeoff_distance.toString(),
    excess_cargo: excess_cargo.toString(),
    cargo: cargo.toString()
  }).then(()=> {
    console.log("success");
  }).catch((error) => {
    console.error(error);
  });

  console.log(takeoff_time +" | "+ takeoff_distance+" | "+excess_cargo+" | "+cargo);
};

方案二:使用useEffect监听state变化发送请求

通过useEffect监听计算后state的变化,当值更新完成后再执行insertData:

// 首先引入useEffect
import React, { useState, useEffect } from 'react';

// 在组件内部添加useEffect
useEffect(() => {
  // 仅当所有计算字段和cargo都有有效值时发送请求
  if(takeoff_time && takeoff_distance && excess_cargo && cargo){
    insertData();
  }
}, [takeoff_time, takeoff_distance, excess_cargo, cargo]); // 依赖项为需要监听的state

// 修改handleData函数,移除内部的insertData调用
const handleData = () => {
  if(validInput(cargo)){
    setAcceleration(functions.getAcceleration(cargo));
    setTakeOffTime(functions.getTakeOffTime(cargo));
    setTakeOffDistance(functions.getTakeOffDistance(cargo));
    setExcessCargo(functions.getExcessCargo(cargo));
  }
}

注意:方案二需要避免初始渲染时的空值触发请求,因此添加了判断条件;如果用户快速多次点击,可能会触发多次请求,可根据需求添加防抖逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:05:47