React Hooks中如何将子组件多个表单字段数据传递给父组件
实现方案
核心逻辑是通过逐层透传回调函数实现跨层级数据传递,多字段可直接打包为对象传递,无需拆分单个字段处理,同步更新父组件状态即可触发子组件重渲染。
1. 修改父组件 StudentList
新增接收更新后学生数据的回调函数,将函数通过 props 传递给 StudentDetails 组件:
import React, { useState } from "react"; import { useQuery } from "@apollo/client"; import { getStudents } from "../queries"; import StudentDetails from "./StudentDetails"; const StudentList = () => { const [student, setStudent] = useState(""); const { loading, error, data } = useQuery(getStudents); if (loading) return <p>Loading...</p>; if (error) return <p>Error!</p>; const handleClick = (student)=> { setStudent(student); }; // 新增:接收孙组件提交的最新学生数据,更新本地状态 const handleStudentUpdate = (updatedStudent) => { setStudent(updatedStudent); }; let filteredStudents = []; for(let i = 0; i < data.students.length; i++){ if(data.students[i].class.name === "1FE1"){ filteredStudents.push(data.students[i]) } } return ( <div> <ul id="student-list"> {data.students.map((student) => ( <li key={student.id} onClick={(e) => handleClick(student)}>{student.name}</li> ))} </ul> { student ? // 传递回调函数给子组件 <StudentDetails student={student} onStudentUpdate={handleStudentUpdate} /> : <p>No Student Selected</p> } </div> ); }; export default StudentList;
2. 修改中间层组件 StudentDetails
无需额外逻辑,仅透传父组件传入的回调函数给孙组件 EditStudent 即可:
import React from "react"; import DeleteStudent from "./DeleteStudent" import EditStudent from "./EditStudent"; const StudentDetails = (props)=> { return ( <div id="student-details" > <h2>Name: {props.student.name}</h2> <h3>Age: {props.student.age}</h3> <h3>Class: {props.student.class.name}</h3> <h3>Test 1 Score: {props.student.test1}</h3> <DeleteStudent id={props.student.id}/> {/* 透传回调函数给孙组件 */} <EditStudent id={props.student.id} student={props.student} onStudentUpdate={props.onStudentUpdate} /> </div> ) } export default StudentDetails;
注:原组件中声明的
astudent状态未被使用,可以直接删除避免冗余。
3. 修改孙组件 EditStudent
接收上层透传的回调函数,在表单提交、mutation 执行成功后,将所有表单字段打包为对象传递给父组件:
import React, { useState } from "react"; import { useMutation } from "@apollo/react-hooks"; import { editStudentMutation, getStudents } from "../queries/index"; const EditStudent = (props) => { // 新增:初始化表单默认值为当前学生的原有信息,优化用户体验 const [name, setName] = useState(props.student.name); const [age, setAge] = useState(props.student.age); const [test, setTest] = useState(props.student.test1); const [editStudent] = useMutation(editStudentMutation); return ( <form id="edit-student" onSubmit={(e) => { e.preventDefault(); editStudent({ variables: { id: props.id, name: name, age: age, test1: test }, refetchQueries: [{ query: getStudents}], // 新增:提交成功后将最新数据回传给父组件 onCompleted: (res) => { // 若editStudentMutation配置了返回完整的学生数据,直接用返回结果即可 props.onStudentUpdate(res.editStudent); // 若没有配置返回完整数据,手动拼接数据如下: // props.onStudentUpdate({ // ...props.student, // name, // age, // test1: test // }) } }); }}> <div className="field"> <label>Student Name:</label> <input type="text" value={name} onChange={(e) => setName(e.target.value)}/> </div> <div className="field"> <label>Age:</label> <input type="text" value={age} onChange={(e) => setAge(e.target.value)}/> </div> <div className="field"> <label>Test One:</label> <input type="text" value={test} onChange={(e) => setTest(e.target.value)}/> </div> <button>submit</button> </form> ) } export default EditStudent;
原问题原因说明
之前子组件无法重渲染是因为提交表单后仅触发了getStudents的重查,更新了列表数据,但父组件中存储的选中学生状态student还是旧值,导致StudentDetails接收的props没有变化,自然不会触发重渲染。修改后提交成功会主动更新父组件的student状态,所有下层组件都会自动触发重渲染。
内容的提问来源于stack exchange,提问作者user14593966
相关产品推荐
相关产品推荐

