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
相关产品推荐
相关产品推荐

