In der Schüler-(Kind-)Komponente
useEffect
挂钩将通过 handleStudentsChange
(von der übergeordneten Komponente bereitgestellte Funktion) aktualisiert das übergeordnete Array. In der Schüler-(Eltern-)Komponente
handleStudentsChange
函数使用 useCallback
Hook-Definition. Allerdings scheint es nicht zu funktionieren. Fragen/Fragen
handleStudentsChange
wird sie auf unbestimmte Zeit ausgeführtSehen Sie sich den Code hier an: Ich bin CodeSandBox-Link
Student.tsx(Kind)
import React, { useState, useEffect, useRef } from "react"; import TextField from "@mui/material/TextField"; interface student { firstName: string; lastName: string; grade: number; } interface studentProps { id: number; firstName: string; lastName: string; grade: number; handleStudentsChange: (index: number, student: student) => void; } function Student(props: studentProps) { const [firstName, setFirstName] = useState(props.firstName); const [lastName, setLastName] = useState(props.lastName); const [grade, setGrade] = useState(props.grade); useEffect(() => { handleStudentsChange(id, { firstName: firstName, lastName: lastName, grade: grade }); }, [firstName, lastName, grade, props]); return ( <> <TextField label="firstName" onChange={(event) => setFirstName(event.target.value)} value={firstName} /> <TextField label="lastName" onChange={(event) => setLastName(event.target.value)} value={lastName} /> <TextField label="grade" onChange={(event) => setGrade(+event.target.value)} value={grade} /> </> );
Students.tsx(Elternteil)
import React, { useState, useCallback } from "react"; import Student from "./Student"; interface student { firstName: string; lastName: string; grade: number; } export default function Students() { const [students, setStudents] = useState<student[]>([ { firstName: "Justin", lastName: "Bieber", grade: 100 }, { firstName: "Robert", lastName: "Oppenhiemer", grade: 100 } ]); const handleStudentsChange = useCallback( (index: number, updatedStudent: student) => { // console.log(index) //I only want this to rerender when the value change however it turn into an infinity loop setStudents((prevStudents) => { const updatedStudents = [...prevStudents]; updatedStudents[index] = updatedStudent; return updatedStudents; }); }, [] ); return ( <> {students.map((student, index) => { return ( <Student key={index} id={index} firstName={student.firstName} lastName={student.lastName} grade={student.grade} handleStudentsChange={(index: number, newStudent: student) => handleStudentsChange(index, newStudent) } /> ); })} </> ); }
Wie im Code oben gezeigt, habe ich versucht, React.memo
für die Schülerkomponente (untergeordnete Komponente) und useCallback
für React.memo
,并在 handleStudentsChange
上使用 useCallback
zu verwenden, in der Hoffnung, eine Endlosschleife zu verhindern. Die Endlosschleife geht jedoch weiter.
问题
handleStudentsChange
不仅在发生更改时无限运行一次-它从第一次渲染开始就无限运行。这是因为Student
组件具有调用handleStudentsChange
的useEffect
,它更新了Students
组件中的状态,导致Student
组件重新渲染,然后再次调用useEffect
,无限循环。解决方案
您需要在更新输入后才调用
handleStudentsChange
,而不是在每次渲染后都调用。我在下面的示例中包含了一个示例,它在从输入触发blur
事件后更新了Students
中的状态。对于更聪明(和复杂)的方法,您可以对比props和state来决定是否需要更新,但我将让您自己解决。