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

TypeScript+React中如何计算多个输入框的数值总和?

Calculating Sum of 8 Number Inputs in React + TypeScript (Better Alternatives to ID-Based Approach)

Hey there! I totally get wanting to move away from the ID-based approach for calculating your form's total duration—it's not the most idiomatic way to handle state in React. Let's walk through a few cleaner, more React/TypeScript-friendly methods, along with proper ES6/TS syntax.


Instead of managing 8 separate state variables or querying elements by ID, store all input values in a single array state. This keeps your code DRY and easy to scale if you ever add more inputs.

Example Code:

import { useState } from 'react';

const DurationForm = () => {
  // Initialize state with an array of 8 zeros (one for each input)
  const [inputValues, setInputValues] = useState<number[]>(new Array(8).fill(0));

  // Handle input change by updating the corresponding index in the array
  const handleInputChange = (index: number, e: React.ChangeEvent<HTMLInputElement>) => {
    // Parse the input value to number, default to 0 if invalid
    const value = parseFloat(e.target.value) || 0;
    // Create a copy of the array to avoid mutating state directly
    const newValues = [...inputValues];
    newValues[index] = value;
    setInputValues(newValues);
  };

  // Calculate total sum using Array.reduce (clean ES6 syntax)
  const totalDuration = inputValues.reduce((acc, curr) => acc + curr, 0);

  return (
    <div>
      {/* Render 8 input fields dynamically */}
      {inputValues.map((value, index) => (
        <input
          key={index}
          type="number"
          value={value}
          onChange={(e) => handleInputChange(index, e)}
          min="0"
          step="0.5" // Adjust step based on your needs (e.g., half-hour increments)
        />
      ))}
      <p>Total Duration: {totalDuration}</p>
    </div>
  );
};

export default DurationForm;

Key ES6/TS Notes:

  • We use useState<number[]> to explicitly type our state array as numbers—critical for TypeScript type safety.
  • The spread operator ([...inputValues]) creates a shallow copy of the array—never mutate state directly in React!
  • parseFloat(e.target.value) || 0 handles empty inputs or non-numeric values, ensuring we don't get NaN in our sum.
  • Array.reduce is a concise ES6 method to compute the sum of an array without manual looping.

2. Controlled Components with Individual State Variables (For Small Fixed Counts)

If you prefer explicit state variables (since you have exactly 8 inputs), you can manage each one separately. This is less scalable but might feel more straightforward for a fixed number of fields.

Example Code:

import { useState } from 'react';

const DurationForm = () => {
  const [val1, setVal1] = useState<number>(0);
  const [val2, setVal2] = useState<number>(0);
  const [val3, setVal3] = useState<number>(0);
  const [val4, setVal4] = useState<number>(0);
  const [val5, setVal5] = useState<number>(0);
  const [val6, setVal6] = useState<number>(0);
  const [val7, setVal7] = useState<number>(0);
  const [val8, setVal8] = useState<number>(0);

  // Helper function to avoid repeating change handler logic
  const handleNumberChange = (setter: React.Dispatch<React.SetStateAction<number>>) => {
    return (e: React.ChangeEvent<HTMLInputElement>) => {
      setter(parseFloat(e.target.value) || 0);
    };
  };

  // Calculate total by adding all state variables
  const totalDuration = val1 + val2 + val3 + val4 + val5 + val6 + val7 + val8;

  return (
    <div>
      <input type="number" value={val1} onChange={handleNumberChange(setVal1)} />
      <input type="number" value={val2} onChange={handleNumberChange(setVal2)} />
      {/* Repeat for val3 to val8 */}
      <input type="number" value={val8} onChange={handleNumberChange(setVal8)} />
      <p>Total Duration: {totalDuration}</p>
    </div>
  );
};

export default DurationForm;

3. Uncontrolled Components with Refs (Less Ideal, But Useful in Edge Cases)

If you really don't want to use controlled components, you can use useRef to access each input's DOM element directly. Note that this bypasses React's state management, so it's not the recommended approach for most cases—but it's an alternative to querying by ID.

Example Code:

import { useRef, useState } from 'react';

const DurationForm = () => {
  // Create refs for each input
  const inputRefs = useRef<(HTMLInputElement | null)[]>(new Array(8).fill(null));
  const [totalDuration, setTotalDuration] = useState<number>(0);

  // Calculate sum when needed (e.g., on button click)
  const calculateTotal = () => {
    let sum = 0;
    inputRefs.current.forEach(ref => {
      if (ref) {
        sum += parseFloat(ref.value) || 0;
      }
    });
    setTotalDuration(sum);
  };

  return (
    <div>
      {Array.from({ length: 8 }).map((_, index) => (
        <input
          key={index}
          type="number"
          ref={(el) => (inputRefs.current[index] = el)}
          defaultValue={0}
          min="0"
        />
      ))}
      <button onClick={calculateTotal}>Calculate Total</button>
      <p>Total Duration: {totalDuration}</p>
    </div>
  );
};

export default DurationForm;

Final Recommendations

  • Go with the array state approach (method 1) if you want clean, scalable code that aligns with React's best practices.
  • Always handle non-numeric inputs to avoid NaN in your sum—using parseFloat(...) || 0 is a simple, reliable way to do this.
  • Avoid ID-based DOM queries in React whenever possible; state management is the React-native way to handle form data!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 06:55:06