ReactJS:表单提交时如何渲染同级的EmployeeTable组件?
解决方案:状态提升实现表单提交更新右侧表格
要实现提交表单后用新数据更新右侧的EmployeeTable组件,核心是状态提升——把员工列表的状态放在父组件中,让表单组件和表格组件共享这个状态。表单负责收集数据并通知父组件更新列表,表格组件根据父组件传入的列表数据渲染,这样列表更新时表格会自动重新渲染。
步骤1:创建父组件(如App.jsx)
将员工列表的状态维护在父组件,同时提供添加新员工的方法,分别传递给表单和表格组件。
import { useState } from "react"; import EmpFormComponent from "./EmpForm"; import EmployeeTableComponent from "./EmpTable"; function App() { // 初始化员工列表,包含原有示例数据 const [employees, setEmployees] = useState([ { id: 1, firstname: "Smith", lastname: "Mathew", joindate: "09/Jan/2021", department: "Development", technologies: [ { id: 1, domain: "Java Spring Boot" }, { id: 4, domain: " Asp.Net MVC" }, ], projects: 3, }, { id: 2, firstname: "Maria", lastname: "Garcia", joindate: "09/Oct/2019", department: "Development", technologies: [ { id: 1, domain: "Java Spring Boot" }, { id: 2, domain: "Python Django" }, ], projects: 8, }, { id: 3, firstname: "Jacob", lastname: "Abraham", joindate: "21/Mar/2021", department: "Testing", technologies: [{ id: 3, domain: "Express Js" }], projects: 1, }, { id: 4, firstname: "Jessica", lastname: "Antoine", joindate: "18/Aug/2021", department: "Development", technologies: [ { id: 1, domain: "Java Spring Boot" }, { id: 4, domain: "Asp.Net MVC" }, ], projects: 11, }, ]); // 添加新员工的方法,处理数据格式转换 const addNewEmployee = (newEmp) => { // 将表单的日期格式转换为表格需要的格式(如DD/MMM/YYYY) const formattedDate = new Date(newEmp.userDate).toLocaleDateString("en-GB", { day: "2-digit", month: "short", year: "numeric", }).replace(/ /g, "/"); // 转换technologies为表格需要的结构 const formattedTechnologies = newEmp.userTechnology.map((tech, index) => ({ id: index + 1, domain: tech, })); // 构造符合表格结构的新员工对象 const employeeToAdd = { id: parseInt(newEmp.userId), firstname: newEmp.userFirstName, lastname: newEmp.userLastName, joindate: formattedDate, department: newEmp.userDepartment, technologies: formattedTechnologies, projects: parseInt(newEmp.userCount), }; // 更新员工列表 setEmployees([...employees, employeeToAdd]); }; return ( <div className="container-fluid"> <div className="row"> {/* 左侧表单 */} <div className="col-md-6"> <EmpFormComponent onAddEmployee={addNewEmployee} /> </div> {/* 右侧表格 */} <div className="col-md-6"> <div className="card"> <div className="card-header"> <h3>Employee List</h3> </div> <div className="card-body"> <EmployeeTableComponent employees={employees} /> </div> </div> </div> </div> </div> ); } export default App;
步骤2:修改EmpForm.jsx
移除内部的submit状态和表格渲染逻辑,改为调用父组件传递的onAddEmployee方法,并重置表单数据。
import { useState } from "react"; import DepartmentComponent from "./Department"; import TechnologyComponent from "./Technology"; let EmpFormComponent = ({ onAddEmployee }) => { const [newEmployee, setNewEmployee] = useState({ userId: "", userFirstName: "", userLastName: "", userDate: "", userDepartment: "", userTechnology: [], userCount: "", }); const updateChange = (e) => { if (e.target.name !== "userTechnology") { setNewEmployee({ ...newEmployee, [e.target.name]: e.target.value }); } else { // 更新userTechnology数组 if (!newEmployee.userTechnology.includes(e.target.value)) { setNewEmployee({ ...newEmployee, [e.target.name]: [...newEmployee.userTechnology, e.target.value], }); } else { let filterUserTech = newEmployee.userTechnology.filter((item) => { return item !== e.target.value; }); setNewEmployee({ ...newEmployee, [e.target.name]: filterUserTech }); } } }; const handleSubmit = (e) => { e.preventDefault(); // 调用父组件的添加方法 onAddEmployee(newEmployee); // 重置表单 setNewEmployee({ userId: "", userFirstName: "", userLastName: "", userDate: "", userDepartment: "", userTechnology: [], userCount: "", }); }; return ( <div className="card ms-2"> <div className="card-header"> <h3>Employee Form</h3> </div> <form onSubmit={handleSubmit}> <div className="card-body"> <div className="row g-1 my-1"> <div className="col-md-2"> <input type="text" className="form-control text-center" placeholder="id" name="userId" value={newEmployee.userId} onChange={updateChange} /> </div> <div className="col-md-5"> <input type="text" className="form-control text-center" placeholder="first name" name="userFirstName" value={newEmployee.userFirstName} onChange={updateChange} /> </div> <div className="col-md-5"> <input type="text" className="form-control text-center" placeholder="last name" name="userLastName" value={newEmployee.userLastName} onChange={updateChange} /> </div> </div> <div className="row g-1 my-1"> <div className="col-md-6"> <input type="date" className="form-control" name="userDate" value={newEmployee.userDate} onChange={updateChange} /> </div> <div className="col-md-6"> <DepartmentComponent updateChange={updateChange} /> </div> </div> <div className="row g-1 my-1"> <div className="col-md-12"> <p className="my-1 text-center">Select Technology</p> <TechnologyComponent updateChange={updateChange} /> </div> </div> <div className="row g-1 my-1"> <div className="col-md-6"> <p className="my-1 ms-1">Count of Completed Projects</p> </div> <div className="col-md-6"> <input type="text" className="form-control text-center" placeholder="count" name="userCount" value={newEmployee.userCount} onChange={updateChange} /> </div> </div> <div className="row g-1 my-1"> <div className="col-md-12"> <button className="btn btn-outline-primary float-end" type="submit" > Submit </button> </div> </div> </div> </form> </div> ); }; export default EmpFormComponent;
步骤3:修改EmpTable.jsx
移除内部的employees数组,改为接收父组件传递的employees props,同时调整依赖项,监听employees变化。
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faEye } from "@fortawesome/free-solid-svg-icons"; import EmpDetails from "./EmpDetails"; import { useState, useEffect } from "react"; let EmployeeTableComponent = ({ employees }) => { const [hideThisDetail, setHideThisDetail] = useState(); const toggleUnhide = (key) => { setHideThisDetail(key); }; useEffect(() => { console.log("员工列表已更新:", employees); }, [employees]); return ( <table className="table table-hover" id="myTable"> <thead> <tr> <th>Id</th> <th>Employee</th> <th>Join Date</th> <th>Projects</th> <th>#</th> </tr> </thead> <tbody> {employees.map((item, key) => ( <tr key={item.id}> <td>{item.id}</td> <td> {item.firstname} {item.lastname} </td> <td>{item.joindate}</td> <td>{item.projects}</td> <td> <button onClick={() => toggleUnhide(key)} className="btn btn-link p-0" > <FontAwesomeIcon icon={faEye} color="#1c8ee3" /> </button> {key === hideThisDetail && ( <EmpDetails key={item.id} department={item.department} technologies={item.technologies} /> )} </td> </tr> ))} </tbody> </table> ); }; export default EmployeeTableComponent;
关键说明
- 状态提升:将员工列表状态放在父组件,确保表单和表格共享同一数据源,避免状态分散导致的不同步问题。
- 数据格式适配:表单提交的新员工数据需要转换为表格组件期望的结构(如日期格式、technologies数组结构),保证渲染一致性。
- 表单重置:提交后清空表单,提升用户体验。
内容的提问来源于stack exchange,提问作者tulipz123
相关产品推荐
相关产品推荐

