Reactjs 使用shouldComponentUpdate时将删除子组件

Reactjs 使用shouldComponentUpdate时将删除子组件,reactjs,components,Reactjs,Components,我有三个部分:学期表、学期表和课程表 学期列表包含状态(包含所有学期及其内容的数组) 在课程组件中,我创建了shouldComponentUpdate()方法,以避免在课程未更改时呈现课程。如果没有这种方法,所有学期的所有课程都会重新呈现 但是,在添加课程后,当我修改添加课程以外的其他课程时,添加的课程将被删除 当我添加多个课程,然后尝试修改最初出现的课程时,也会发生同样的情况 我不知道为什么,但我认为这是由于shouldComponentUpdate()方法造成的 以下是shouldCompo

我有三个部分:学期表、学期表和课程表
学期列表包含状态(包含所有学期及其内容的数组)
在课程组件中,我创建了shouldComponentUpdate()方法,以避免在课程未更改时呈现课程。如果没有这种方法,所有学期的所有课程都会重新呈现

但是,在添加课程后,当我修改添加课程以外的其他课程时,添加的课程将被删除
当我添加多个课程,然后尝试修改最初出现的课程时,也会发生同样的情况
我不知道为什么,但我认为这是由于shouldComponentUpdate()方法造成的

以下是shouldComponentUpdate()

shouldComponentUpdate(nextProps, nextState) {
   if (JSON.stringify(this.props.course) === JSON.stringify(nextProps.course)) {
      return false;
   }

   return true;
}
我在React文档中读到JSON.stringify()非常昂贵,但现在我将忽略这一点

学期组件中渲染方法的一部分:

{semester.courses.map(
   course => (
     <Course
       key={course.id}
       course={course}  
       semester={semester}
       onInputChange={onInputChange}
       onDeleteCourse={onDeleteCourse}
    />
  )
)}

正如我前面所说的,我认为问题在于shouldComponentUpdate()方法,因为当它被注释掉时,一切都按预期进行。

您正在将
课程
学期
道具传递给
组件,但是您的
JSON。stringify
比较只检查
课程

每次添加/更改课程时,都要使用扩展运算符创建
学期
学期
的新副本。因此,您现有的未重新渲染的
组件将保留旧的
组件。这就是当您更改任何现有课程时,新添加的课程将消失的原因,因为旧的
学期
学期课程
不包含新添加的课程

因此,要解决这个问题,您还需要将
学期
包括在您的比较中

if (JSON.stringify(this.props.course) === JSON.stringify(nextProps.course) &&
    JSON.stringify(this.props.semester) === JSON.stringify(nextProps.semester)
   ) {
      return false;
}
上面的代码将修复您的问题,但不会阻止重新渲染其他课程

更好的设计是不将
学期
道具传递给
组件。 但是如果这是不可避免的,那么也许不要创建新的
学期
学期
副本,并保持你的
应该组件更新

handleInputChange = (event, course, semester) => {
  const { name, value } = event.target;
  var semesters = [...this.state.semesters];
  var course = { ...course };
  course[name] = value;
  semester.courses[course.id-1] = course;
  this.setState({ semesters });
}

handleAddCourse = semester => {
  var semesters = [...this.state.semesters];

  semester.courses.push({
    // new course's id is obtained by incrementing last course's id which is the number of courses
    id: semester.courses.length + 1,
    name: '',
    credit: 0,
    markOver100: 0.0,
    grade: '',
  });  
  this.setState({ semesters });
}
您甚至不需要创建
var semests=[…this.state.semests]的新副本

handleInputChange = (event, course, semester) => {
  const { name, value } = event.target;
  course[name] = value;
  this.setState(this.state); // enough to trigger re-render
}

handleAddCourse = semester => {
  semester.courses.push({
    id: semester.courses.length + 1,
    name: '',
    credit: 0,
    markOver100: 0.0,
    grade: '',
  });  
  this.setState(this.state); // trigger re-render
}

handleInputChange
handledCourse
中打印以控制台您放入
setState
的数据。你看到了什么?一个提琴或沙盒链接也很有用,谢谢你的详细解释。我有两个问题;1) 在哪些情况下,this.props.sement不等于nextrops.sement(在shouldComponentUpdate方法中)?!2) 我如何知道何时复制与何时不复制(仅分配引用)(例如何时执行foo=…bar vs foo=bar),因为这条语句
seurm={…seurm}
handleAddCourse
中,下一个渲染周期的学期将不一样。对于#2,我根据您的问题提出了一个黑客解决方案。通常不建议直接改变状态,您可以忽略我答案的最后一部分。正如我在回答中提到的,不要将整个
学期
对象发送到

handleInputChange = (event, course, semester) => {
  const { name, value } = event.target;
  course[name] = value;
  this.setState(this.state); // enough to trigger re-render
}

handleAddCourse = semester => {
  semester.courses.push({
    id: semester.courses.length + 1,
    name: '',
    credit: 0,
    markOver100: 0.0,
    grade: '',
  });  
  this.setState(this.state); // trigger re-render
}