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

React组件Props传递异常:编辑学生时多ID输出问题求助

你遇到的问题本质是每个EditStudent组件在挂载时都会执行useEffect里的学生数据请求,哪怕模态框没打开。所以当页面渲染整个年级的学生列表时,所有学生的EditStudent组件都会触发getStudentData,导致控制台打印多个ID,还会发起一堆无效请求。

解决方案1:仅在模态框打开时获取学生数据

把获取数据的逻辑从组件挂载的useEffect,移到点击编辑按钮打开模态框的事件里,这样只有被点击的那个学生才会发起请求。

修改EditStudent组件:

import React, { useState } from 'react';
import axios from 'axios';
import { Modal } from 'flowbite-react';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

const EditStudent = ({ id, handleEdit }) => {
  const [openModal, setOpenModal] = useState(false);
  const [studentname, setStudentname] = useState('');
  const [standard, setStandard] = useState('');
  const [rollnumber, setRollnumber] = useState('');
  const [birthdate, setBirthdate] = useState('');
  const [address, setAddress] = useState('');
  const [phonenumber, setPhonenumber] = useState('');
  const [uid, setUid] = useState('');

  // 点击编辑按钮时打开模态框并获取学生数据
  const handleOpenModal = async () => {
    setOpenModal(true);
    try {
      const { data } = await axios.get(`http://localhost:4000/students/one/${id}`);
      setStudentname(data.studentname);
      setStandard(data.standard);
      setRollnumber(data.rollnumber);
      setBirthdate(data.birthdate);
      setPhonenumber(data.phonenumber);
      setUid(data.uid);
      setAddress(data.address);
      console.log(id); // 现在只会打印当前被点击的学生ID
    } catch (error) {
      console.error('Error fetching student data', error);
      toast.error('加载学生数据失败');
    }
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      await axios.put(`http://localhost:4000/students/edit/${id}`, {
        studentname,
        standard,
        rollnumber,
        birthdate,
        address,
        phonenumber,
        uid,
      });

      const message = '学生信息更新成功';
      console.log(message);
      toast.success(message, {
        position: 'bottom-right',
        autoClose: 4000,
        hideProgressBar: false,
        closeOnClick: true,
        pauseOnHover: true,
      });
      handleEdit?.(id); // 用可选链避免未传props时报错
      setOpenModal(false);
    } catch (error) {
      if (error.response) {
        toast.error(error.response.data.message);
      } else if (error.request) {
        console.error(error.request);
        toast.error('请求错误,请稍后重试');
      } else {
        console.error('Error', error.message);
        toast.error('发生未知错误');
      }
    }
  };

  return (
    <>
      <button
        className="rounded-md px-3 py-2 bg-blue-800 text-sm font-bold text-gray-200 hover:bg-gray-700"
        onClick={handleOpenModal} // 绑定新的打开事件
      >
        编辑
      </button>
      <Modal dismissible show={openModal} onClose={() => setOpenModal(false)}>
        <Modal.Header className="bg-red-100">编辑学生信息</Modal.Header>
        <Modal.Body>
          <form onSubmit={handleSubmit} className="w-full max-w-lg ">
            {/* 表单部分保持不变 */}
            <div className="flex flex-wrap -mx-3 mb-6">
              <div className="w-full md:w-1/2 px-3 mb-6 md:mb-0">
                <label
                  className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
                  htmlFor="name"
                >
                  姓名
                </label>
                <input
                  className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
                  id="name"
                  name="name"
                  type="text"
                  value={studentname}
                  onChange={(e) => setStudentname(e.target.value)}
                />
              </div>
              <div className="w-full md:w-1/2 px-3">
                <label
                  className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
                  htmlFor="standard"
                >
                  年级
                </label>
                <input
                  className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
                  id="standard"
                  name="standard"
                  type="number"
                  value={standard}
                  onChange={(e) => setStandard(e.target.value)}
                />
              </div>
            </div>
            <div className="flex flex-wrap -mx-3 mb-6">
              <div className="w-full md:w-1/2 px-3 mb-6 md:mb-0">
                <label
                  className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
                  htmlFor="rollnumber"
                >
                  学号
                </label>
                <input
                  className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
                  id="rollnumber"
                  name="rollnumber"
                  type="text"
                  value={rollnumber}
                  onChange={(e)=> setRollnumber(e.target.value)}
                />
              </div>
              <div className="w-full md:w-1/2 px-3">
                <label
                  className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
                  htmlFor="birthdate"
                >
                  出生日期
                </label>
                <input
                  className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
                  id="birthdate"
                  name="birthdate"
                  type="date"
                  value={birthdate}
                  onChange={(e) => setBirthdate(e.target.value)}
                />
              </div>
            </div>
            <div className="flex flex-wrap -mx-3 mb-6">
              <div className="w-full md:w-1/2 px-3 mb-6 md:mb-0">
                <label
                  className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
                  htmlFor="uid"
                >
                  UID
                </label>
                <input
                  className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white"
                  id="uid"
                  name="uid"
                  type="text"
                  value={uid}
                  onChange={(e) => setUid(e.target.value)}
                />
              </div>
              <div className="w-full md:w-1/2 px-3">
                <label
                  className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
                  htmlFor="phonenumber"
                >
                  联系电话
                </label>
                <input
                  className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
                  id="phonenumber"
                  name="phonenumber"
                  type="text"
                  value={phonenumber}
                  onChange={(e) => setPhonenumber(e.target.value)}
                />
              </div>
            </div>
            <div className="flex flex-wrap -mx-3 mb-6">
              <div className="w-full px-3">
                <label
                  className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
                  htmlFor="address"
                >
                  地址
                </label>
                <input
                  className="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
                  id="address"
                  type="text"
                  name="address"
                  value={address}
                  onChange={(e) => setAddress(e.target.value)}
                />
              </div>
            </div>
            <button
              type="submit"
              className="w-full bg-slate-700 text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
            >
              提交
            </button>
            <ToastContainer />
          </form>
        </Modal.Body>
      </Modal>
    </>
  )
}

export default EditStudent;

解决方案2:修复StudentsList组件的传参问题

原StudentsList里给EditStudent传了id但没传handleEdit,导致EditStudent里调用handleEdit(selectedId)时会报错。需要补上:

修改StudentsList中渲染EditStudent的部分:

<EditStudent
  id={student._id}
  handleEdit={handleEdit} // 补上这个props
/>

额外优化:移除不必要的selectedId状态

现在我们直接用传入的id就可以,不需要再维护selectedId状态,减少代码冗余。

这样修改后,点击编辑按钮时只会获取当前学生的数据,控制台只会打印一个ID,GET和PUT请求也能正常发起了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:15:54