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

React JS中如何获取动态生成输入框的独立数据?

解决动态生成学期输入框的独立状态存储问题

核心问题分析

你当前的状态结构里,credit和sgpa是单个值,所有动态输入框都绑定这两个值,自然会出现共享状态的问题。要实现每个学期数据独立,需要把状态改成数组结构,每个数组元素对应一个学期的credit和sgpa。

具体修改方案

1. 调整状态结构

把原来的单个credit、sgpa替换为数组semesters,每个元素是存储对应学期数据的对象:

const [state, setState] = useState({
  semester: "",
  semesters: [] // 每个元素格式:{ credit: '', sgpa: '' }
});

2. 修改学期提交逻辑

用户输入学期数后,初始化对应数量的空学期数据对象到数组中,同时可以去掉原来单独维护的noOfSem状态,直接用semesters.length判断渲染:

const handleClick = () => {
  const semesterCount = parseInt(state.semester, 10);
  if (isNaN(semesterCount) || semesterCount <= 0) return;
  // 生成对应数量的空学期数据
  const initialSemesters = Array.from({ length: semesterCount }, () => ({
    credit: "",
    sgpa: ""
  }));
  setState(prev => ({ ...prev, semesters: initialSemesters }));
};

3. 更新输入框 onChange 逻辑

给每个动态输入框添加data-index属性标识学期索引,区分总学期数输入和单个学期的字段输入:

const handleChange = (e) => {
  const { name, value } = e.target;
  // 处理总学期数输入
  if (name === "semester") {
    setState(prev => ({ ...prev, semester: value }));
    return;
  }

  // 处理单个学期的学分/绩点输入
  const index = parseInt(e.target.dataset.index, 10);
  setState(prev => {
    const updatedSemesters = [...prev.semesters];
    // 更新对应学期的指定字段
    updatedSemesters[index] = {
      ...updatedSemesters[index],
      [name]: value
    };
    return { ...prev, semesters: updatedSemesters };
  });
};

4. 调整渲染逻辑

动态生成输入框时,绑定对应学期的value和data-index属性:

{state.semesters.length > 0 && (
  <div className="col form2">
    {state.semesters.map((sem, index) => (
      <div key={index} className="col-md seminpt">
        <label>Semester {index + 1}</label>
        <input
          type="Number"
          name="credit"
          data-index={index}
          value={sem.credit}
          onChange={handleChange}
          placeholder="Total Credit"
        />
        <input
          type="Number"
          name="sgpa"
          data-index={index}
          value={sem.sgpa}
          onChange={handleChange}
          placeholder={`SGPA sem${index + 1}`}
        />
      </div>
    ))}
    <button
      type="button"
      className="btn btn-success btn3334"
      onClick={handleCgpaSubmit}
    >
      Submit
    </button>
  </div>
)}

5. 重置与提交逻辑更新

  • 重置按钮直接清空semesters数组和semester值:
const emptySemester = () => {
  setState({ semester: "", semesters: [] });
};
  • 提交时直接获取所有学期的独立数据:
const handleCgpaSubmit = () => {
  console.log("所有学期数据:", state.semesters);
  // 可选:添加CGPA计算逻辑
  const totalPoints = state.semesters.reduce((sum, sem) => {
    const credit = parseFloat(sem.credit);
    const sgpa = parseFloat(sem.sgpa);
    return sum + (credit * sgpa || 0);
  }, 0);
  const totalCredits = state.semesters.reduce((sum, sem) => {
    return sum + (parseFloat(sem.credit) || 0);
  }, 0);
  const cgpa = totalCredits > 0 ? (totalPoints / totalCredits).toFixed(2) : 0;
  console.log("计算出的CGPA:", cgpa);
};

修改后的完整代码

import React, { useState } from "react";
import cal from "./image/bgimg.jpg";

function Home() {
  const [state, setState] = useState({
    semester: "",
    semesters: []
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    if (name === "semester") {
      setState(prev => ({ ...prev, semester: value }));
      return;
    }

    const index = parseInt(e.target.dataset.index, 10);
    setState(prev => {
      const updatedSemesters = [...prev.semesters];
      updatedSemesters[index] = {
        ...updatedSemesters[index],
        [name]: value
      };
      return { ...prev, semesters: updatedSemesters };
    });
  };

  const handleClick = () => {
    const semesterCount = parseInt(state.semester, 10);
    if (isNaN(semesterCount) || semesterCount <= 0) return;
    const initialSemesters = Array.from({ length: semesterCount }, () => ({
      credit: "",
      sgpa: ""
    }));
    setState(prev => ({ ...prev, semesters: initialSemesters }));
  };

  const emptySemester = () => {
    setState({ semester: "", semesters: [] });
  };

  const handleCgpaSubmit = () => {
    console.log("所有学期数据:", state.semesters);
    const totalPoints = state.semesters.reduce((sum, sem) => {
      const credit = parseFloat(sem.credit);
      const sgpa = parseFloat(sem.sgpa);
      return sum + (credit * sgpa || 0);
    }, 0);
    const totalCredits = state.semesters.reduce((sum, sem) => {
      return sum + (parseFloat(sem.credit) || 0);
    }, 0);
    const cgpa = totalCredits > 0 ? (totalPoints / totalCredits).toFixed(2) : 0;
    console.log("计算出的CGPA:", cgpa);
  };

  return (
    <div className="container">
      <div className="row">
        <div className="col-md-6">
          <img src={cal} alt="Calculator background" className="imgcal img-fluid" />
        </div>
        <div className="col-md-6">
          <div className="col-md">
            <div className="form1">
              <div className="col-md formmain">
                <input
                  type="number"
                  value={state.semester}
                  name="semester"
                  onChange={handleChange}
                  placeholder="Enter Total Semester"
                  min="1"
                />
                {state.semesters.length === 0 ? (
                  <button
                    type="button"
                    className="btn btn-success btn333"
                    onClick={handleClick}
                  >
                    Submit
                  </button>
                ) : (
                  <button
                    type="button"
                    className="btn btn-success btn333"
                    onClick={emptySemester}
                  >
                    Reset Semester
                  </button>
                )}
              </div>
              {state.semesters.length > 0 && (
                <div className="col form2">
                  {state.semesters.map((sem, index) => (
                    <div key={index} className="col-md seminpt">
                      <label>Semester {index + 1}</label>
                      <input
                        type="Number"
                        name="credit"
                        data-index={index}
                        value={sem.credit}
                        onChange={handleChange}
                        placeholder="Total Credit"
                        min="0"
                      />
                      <input
                        type="Number"
                        name="sgpa"
                        data-index={index}
                        value={sem.sgpa}
                        onChange={handleChange}
                        placeholder={`SGPA sem${index + 1}`}
                        min="0"
                        max="10"
                      />
                    </div>
                  ))}
                  <button
                    type="button"
                    className="btn btn-success btn3334"
                    onClick={handleCgpaSubmit}
                  >
                    Submit
                  </button>
                </div>
              )}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

export default Home;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:01:04