React (Hooks)父组件状态更新时StudentDetails子组件未重渲染问题求助
问题根因
你对props的认知存在偏差:props发生变化时普通React组件是会触发重渲染的,只有使用React.memo包裹且props浅比较相等、或组件内部主动跳过更新逻辑的情况下才会不触发重渲染。你遇到的问题本质是:StudentList中存储的student状态是首次点击时从学生列表中取出的旧对象,编辑完成后你重新拉取了getStudents接口,Apollo更新了最新的学生列表数据,但你存在状态里的student还是旧引用没有同步更新,所以传给StudentDetails的props没有变化,自然不会重渲染。
解决方案
推荐直接修改StudentList的状态存储逻辑,不要存完整的学生对象,改为存储选中的学生ID,每次从最新的学生列表中匹配对应学生数据,代码修改如下:
import React, { useState, useMemo } from "react"; import { useQuery } from "@apollo/client"; import { getStudents } from "../queries"; import StudentDetails from "./StudentDetails"; const StudentList = () => { // 改为存储选中的学生ID,而非完整对象 const [selectedStudentId, setSelectedStudentId] = useState(null); const { loading, error, data } = useQuery(getStudents); if (loading) return <p>Loading...</p>; if (error) return <p>Error!</p>; // 每次学生列表更新时,自动从最新数据中匹配选中的学生 const selectedStudent = useMemo(() => { if (!selectedStudentId) return null; return data.students.find(item => item.id === selectedStudentId) }, [data.students, selectedStudentId]) const handleClick = (student)=> { setSelectedStudentId(student.id); }; // 原有filteredStudents逻辑保留即可 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> { selectedStudent ? <StudentDetails student={selectedStudent} /> : <p>No Student Selected</p> } </div> ); }; export default StudentList;
如果你不想修改原有状态存储结构,也可以在StudentList中加一段同步逻辑,每次学生列表更新时同步更新选中的学生状态:
// 加在StudentList组件内即可 useEffect(() => { if (!student) return const latestStudent = data.students.find(item => item.id === student.id) if (latestStudent) setStudent(latestStudent) }, [data.students, student])
内容的提问来源于stack exchange,提问作者user14593966
相关产品推荐
相关产品推荐

