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

React多行表格单行Transfer字段独立计算Total及实现Grand Total的技术问询

解决React Row Details组件的行独立计算与汇总问题

嘿,我看了你代码里的问题,核心是全局状态共享导致所有行联动,还有初始值处理不当引发的NaN,咱们一步步搞定它!

问题根源拆解

  1. 你用了全局的transfer和total状态,所有行都绑定同一个值,改一行当然全变
  2. 初始值没做数值转换,输入空值或非数字时会出现NaN
  3. Grand Total直接用全局total,没法汇总各行的独立计算结果

完整解决方案代码

import React, { useState, useMemo } from 'react';
import Dialog from '@mui/material/Dialog';
import Transition from '@mui/material/Transition';

export default function RowDetails({ open, handleClose, data }) { 
  const { Rate, Stock } = data; 

  // 把每行数据作为独立状态,每行自己管理Transfer和Total
  const [rows, setRows] = useState([ 
    { id: 1, Lot: "2101000134", Bill: "M0000013092", Shelf: "W13-A1", Bin: "B01", Rate, Stock, Transfer: 0, Total: 0 }, 
    { id: 2, Lot: "2101000134", Bill: "M0000013092", Shelf: "W13-A1", Bin: "B01", Rate, Stock, Transfer: 0, Total: 0 }, 
  ]); 

  // 计算Grand Total,用useMemo优化性能,只在rows变化时重新计算
  const grandTotal = useMemo(() => {
    return rows.reduce((sum, row) => sum + row.Total, 0);
  }, [rows]);

  // 精准更新单行数据,避免全局联动
  const handleTransferChange = (e, rowId) => {
    // 把输入值转成数字,空值或非数字时设为0,避免NaN
    const transferValue = Number(e.target.value) || 0;
    setRows(prevRows => 
      prevRows.map(row => {
        if (row.id === rowId) {
          // 只更新当前行的Transfer和计算Total
          return { ...row, Transfer: transferValue, Total: row.Rate * transferValue };
        }
        return row;
      })
    );
  }; 

  const columns = [ 
    { field: "Lot", headerName: "Lot#", width: 200, editable: false }, 
    { field: "Bill", headerName: "Bill#", width: 130, editable: false }, 
    { field: "Shelf", headerName: "Shelf", width: 200, editable: false }, 
    { field: "Bin", headerName: "Bin", width: 200, editable: false }, 
    { field: "Rate", headerName: "Rate", width: 200, editable: false }, 
    { field: "Stock", headerName: "Stock Balance Qty.", width: 200, editable: false }, 
    { field: "Transfer", headerName: "Transfer Qty.", width: 200, editable: true }, 
    { field: "Total", headerName: "Total", width: 200, editable: false }, 
  ]; 

  return ( 
    <div> 
      <Dialog fullScreen open={open} onClose={handleClose} TransitionComponent={Transition}> 
        <div style={{ height: 400, width: "100%" }}> 
          <table className="dataTable"> 
            <thead> 
              <tr> 
                {columns.map((column) => ( 
                  <th key={column.headerName}>{column.headerName}</th> 
                ))} 
              </tr> 
            </thead> 
            <tbody> 
              {rows.map((row) => ( 
                <tr key={row.id}> 
                  <td>{row.Lot}</td> 
                  <td>{row.Bill}</td> 
                  <td>{row.Shelf}</td> 
                  <td>{row.Bin}</td> 
                  <td>{row.Rate}</td> 
                  <td>{row.Stock}</td> 
                  <td> 
                    {/* 绑定当前行的Transfer值,而非全局状态 */}
                    <input 
                      type="number" 
                      onChange={(e) => handleTransferChange(e, row.id)} 
                      value={row.Transfer} 
                    /> 
                  </td> 
                  {/* 显示当前行的Total,而非全局total */}
                  <td>{row.Total}</td> 
                </tr> 
              ))} 
            </tbody> 
          </table> 
        </div> 
        <table className="totalTable"> 
          <thead> 
            <tr> 
              <th>Grand Total</th> 
              {/* 显示汇总后的Grand Total */}
              <th>{grandTotal}</th> 
            </tr> 
          </thead> 
        </table> 
      </Dialog> 
    </div> 
  ); 
}

关键优化点说明

  1. 行数据独立管理:把每行的Transfer和Total都放进rows状态数组,每行数据完全独立,修改某一行不会影响其他行
  2. 数值转换防NaN:在handleTransferChange里把输入值转成数字,空值或非数字时设为0,彻底避免NaN问题
  3. Grand Total实时汇总:用useMemo监听rows变化,实时计算所有行Total的总和,既保证准确性又优化性能
  4. 移除冗余全局状态:删掉了原来的transfer和total全局变量,不再需要多余的useEffect

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:54:07