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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:57:04