React表单更新时如何保留点击元素的当前数据状态?
解决React更新表单预填数据问题
你的核心问题是打开编辑模态框时没有加载对应服务的现有数据,导致表单为空。以下是两种可行的解决方案:
方案一:从父组件传入现有数据(推荐)
如果父组件已经持有服务列表数据,直接将当前要编辑的服务对象传入组件,避免重复请求接口:
- 修改组件接收的props,新增
serviceData:
export default function UpdateService({ fetchData, id, serviceData }) { // ... 原有代码 }
- 修改
handleShow方法,打开模态框时用传入的数据填充表单状态:
const handleShow = () => { setName(serviceData.name); setDesc(serviceData.description); setShow(true); };
方案二:打开模态框时通过ID请求数据
如果父组件没有现成数据,就在打开模态框时主动请求接口获取:
- 修改
handleShow为异步方法,添加数据获取逻辑:
const handleShow = async () => { try { const JWT = await getCookie("auth"); const { data } = await axios(`/api/serviceType/${id}`, { headers: { Authorization: JWT, }, }); // 填充表单状态 setName(data.name); setDesc(data.description); setShow(true); } catch (e) { alert("加载数据失败"); } };
额外修复点
原代码还有两处小问题需要修正:
- 表单的
onSubmit没有阻止默认行为,会导致页面刷新:
<Form onSubmit={(e) => { e.preventDefault(); updateService(id); }}>
- 提交按钮应该放在
<Form>标签内部,否则type="submit"不会触发表单的onSubmit事件
修改后的完整组件示例(以方案一为例):
import React, { useState, useEffect } from 'react'; import { getCookie } from "../../../utils/cookies"; import axios from "axios"; import Button from 'react-bootstrap/Button'; import Form from 'react-bootstrap/Form'; import Modal from 'react-bootstrap/Modal'; import { PencilSquare } from 'react-bootstrap-icons'; export default function UpdateService({ fetchData, id, serviceData }) { const [show, setShow] = useState(false); const [name, setName] = useState(""); const [desc, setDesc] = useState(""); const [isLoading, setIsLoading] = useState(true); const [data, setData] = useState([]); const isEnabled = name.length > 0 && desc.length > 0; const handleClose = () => setShow(false); const handleShow = () => { setName(serviceData.name); setDesc(serviceData.description); setShow(true); }; const updateService = async (id) => { try { setIsLoading(true); const JWT = await getCookie("auth"); const { data } = await axios( `/api/serviceType/${id}`, { method: "PATCH", data: { name: name, description: desc, }, headers: { "Content-Type": "application/json", Authorization: JWT, }, } ); setData(data); setShow(false); alert("更新成功"); } catch (e) { alert("error updating data"); } finally { setIsLoading(false); } }; useEffect(() => { if (data.length > 0) { fetchData(data); } }, [data, fetchData]); return ( <> <PencilSquare onClick={handleShow}/> <Modal show={show} backdrop="static" onHide={handleClose}> <Modal.Header closeButton> <Modal.Title>Update Service</Modal.Title> </Modal.Header> <Modal.Body> <Form onSubmit={(e) => { e.preventDefault(); updateService(id); }}> <Form.Group className="mb-3" controlId="exampleForm.ControlInput1"> <Form.Label>Service Name</Form.Label> <Form.Control type="text" value={name} placeholder="Service Name" autoFocus onChange={(e) => setName(e.target.value)} /> </Form.Group> <Form.Group className="mb-3" controlId="exampleForm.ControlTextarea1" > <Form.Label>Description</Form.Label> <Form.Control as="textarea" rows={3} placeholder="Please describe this service" value={desc} onChange={(e) => setDesc(e.target.value)} /> </Form.Group> <Modal.Footer> <Button variant="outline-dark" onClick={handleClose}> Cancel </Button> <Button type="submit" variant="dark" disabled={!isEnabled || isLoading}> {isLoading ? "Updating..." : "Update"} </Button> </Modal.Footer> </Form> </Modal.Body> </Modal> </> ); }
内容的提问来源于stack exchange,提问作者melly18
相关产品推荐
相关产品推荐

