首页 > 解决方案 > React Lifting State:使用父级的 setState 函数更新子级的状态

问题描述

我一直在研究这个问题的变体一段时间。基本上,我有一个可以更新现有数据的子组件。它可以毫无问题地更新数据,并且父级会相应地重新渲染。子组件不会重新渲染。因此,根据本网站上的建议,我尝试解除状态。我正在将道具传递给我正在运行的两个子组件。我的问题是“EditStudent”组件。我似乎无法解构/获取从父组件向下传递的“setStudent”函数,因此无论我如何尝试调用此函数,我都会收到“setStudent 不是函数错误”。非常感谢任何建议,因为它一直让我慢慢发疯如何解决这个问题。

这是到目前为止我一直在使用的代码。父组件“StudentList”

import React, { useState } from "react";
import { useQuery } from "@apollo/client";
import { getStudents } from "../queries";
import StudentDetails from "./StudentDetails";
import DeleteStudent from "./DeleteStudent";
import EditStudent from "./EditStudent";


const StudentList = () => {
  const [selectedStudent, setSelectedStudent] = useState("");
  
  const { loading, error, data } = useQuery(getStudents);
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error!</p>;

  const handleClick = (student)=> {
    //console.log(student)
  
    setSelectedStudent(student);
  };
let filteredStudents = [];

//console.log(data.students)

for(let i = 0; i < data.students.length; i++){
  //console.log(data.students[i].class.name)
  if(data.students[i].class.name === "1FE1"){
    //console.log(data.students[i].name)
    filteredStudents.push(data.students[i])
  }
  
}

console.log(selectedStudent.id);
  
  return (
    
    <div>
      <ul id="student-list">
        {data.students.map((student) => (
          <li key={student.id} onClick={(e) => handleClick(student)}>{student.name}</li>
        ))}
        
      </ul>
        {
          selectedStudent ? <div>
            <StudentDetails student={selectedStudent} setStudent={setSelectedStudent}/>
           </div>
          : <p>No Student Selected</p>
          
        }
      
    </div>
  );
};

export default StudentList;

这是“StudentDetails”——一个接收“studentDetails”属性的组件,还有两个嵌套在里面的组件——“DeleteStudent”和“EditStudent”

import React from "react";
import { useEffect, useState } from "react";
import { getStudentQuery } from "../queries";
import { useQuery } from "@apollo/client";
import DeleteStudent from "./DeleteStudent"
import EditStudent from "./EditStudent";


const StudentDetails = ( selectedStudent )=> {
    const {setStudent} = selectedStudent;
    console.log(selectedStudent)

    //const [astudent, setStudent] = useState(props)
    
    return (
        <div id="student-details" >
            <h2>Name: {selectedStudent.student.name}</h2>
            <h3>Age: {selectedStudent.student.age}</h3>
            <h3>Class: {selectedStudent.student.class.name}</h3>
            <h3>Test 1 Score: {selectedStudent.student.test1}</h3>
            <EditStudent student={selectedStudent} setstudent={setStudent}/>
            <DeleteStudent student={selectedStudent} setter={setStudent} />
        </div>
        
    )
    
}

export default StudentDetails;

最后,这是给我带来很多问题的“EditStudent”组件(无法从父级获取 setStudent 函数来更改状态)

import React, { useEffect, useState } from "react";
import { useMutation } from "@apollo/react-hooks";
//import { getStudents } from "../queries";
import StudentDetails from "./StudentDetails";
import { editStudentMutation, getStudentQuery, getStudents } from "../queries/index";


const EditStudent = ( setStudent ) => {
    const { setStudent } = selectedStudent;
    console.log(props)
    const [name, setName] = useState(); 
    const [age, setAge] = useState();
    const [test, setTest] = useState();
    const [editStudent] = useMutation(editStudentMutation);

    
    return (
    
        <form id="edit-student" 
            onSubmit={(e) => {
                e.preventDefault();
                editStudent({
                variables: {
                    id: selectedStudent.student.student.id,
                    name: name,
                    age: age,
                    test1: test
                },
                refetchQueries: [{ query: getStudents}]
                })
                const aStudent = e.target.value;
                setStudent(aStudent);
            }}>
            
            <div className="field" onChange={(e) => setName(e.target.value)}>
                <label>Student Name:</label>
                <input type="text"
                 value={name}/>
            </div>
            <div className="field" onChange={(e) => setAge(e.target.value)}>
                <label>Age:</label>
                <input type="text"
                 value={age}/>
            </div>
            <div className="field" onChange={(e) => setTest(e.target.value)}>
                <label>Test One:</label>
                <input type="text"
                 value={test}/>
            </div>
    <button type="submit" >submit</button>
        </form>
    )
}

export default EditStudent;

标签: reactjsreact-hookssetstate

解决方案


您在道具中命名的方法setstudent“检查传递道具的左侧”

<EditStudent student={selectedStudent} setstudent={setStudent}/>

请像下面这样访问它

const EditStudent = ( {setstudent} ) => {}

// or
const EditStudent = ( props ) => {

 props.setstudent()
}

而且这些代码行似乎不正确,您从哪里得到这个 selectedStudent?您命名的道具setStudent然后您正在访问它以获取方法setStudent

const EditStudent = ( setStudent ) => {
    const { setStudent } = selectedStudent;

推荐阅读