使用 shouldComponentUpdate 时子组件被删除
Child component is deleted when using shouldComponentUpdate
我有 3 个组成部分:SemesterList、Semester 和 Course。
SemesterList 包含状态(包含所有学期及其内容的数组)。
在 Course 组件中,我创建了一个 shouldComponentUpdate() 方法,以避免呈现未更改的课程。如果没有这个方法,所有学期的所有课程都会重新渲染。
但是,添加课程后,当我修改除了添加的课程以外的其他课程时,添加的课程被删除了!
当我添加多门课程然后尝试修改最初存在的课程时,也会发生同样的事情。
我不知道为什么,但我认为这是由于 shouldComponentUpdate() 方法造成的。
这是 shouldComponentUpdate():
shouldComponentUpdate(nextProps, nextState) {
if (JSON.stringify(this.props.course) === JSON.stringify(nextProps.course)) {
return false;
}
return true;
}
我在 React 文档中读到 JSON.stringify() 很昂贵,但我暂时忽略它。
学期部分render方法部分:
{semester.courses.map(
course => (
<Course
key={course.id}
course={course}
semester={semester}
onInputChange={onInputChange}
onDeleteCourse={onDeleteCourse}
/>
)
)}
这是按下字符时调用的 onInputChange() 函数和添加课程时调用的 handleAddCourse .
handleInputChange = (event, course, semester) => {
const { name, value } = event.target;
var semesters = [...this.state.semesters], semesterCourses = [...semester.courses];
var course = { ...course };
course[name] = value;
semesterCourses[course.id-1] = course;
semester.courses = [...semesterCourses];
semesters[semester.number-1] = semester;
this.setState({ semesters });
}
handleAddCourse = semester => {
var semesters = [...this.state.semesters], semester = { ...semester };
var semesterCourses = [...semester.courses];
const semesterIndex = semester.number - 1;
semesterCourses.push({
// new course's id is obtained by incrementing last course's id which is the number of courses
id: semesterCourses.length + 1,
name: '',
credit: 0,
markOver100: 0.0,
grade: '',
});
semester.courses = semesterCourses;
semesters[semesterIndex] = semester;
this.setState({ semesters });
}
正如我之前所说,我认为问题出在 shouldComponentUpdate() 方法中,因为当它被注释掉时,一切都按预期工作。
您正在将 course
和 semester
属性传递给 <Course>
组件,但您的 JSON.stringify
比较仅检查 course
.
每次 add/change 一门课程,您都会使用扩展运算符创建 semester
和 semesterCourses
的新副本。因此,您现有的 <Course>
未重新渲染的组件将保留旧的 semester
。这就是当您更改任何现有课程时新添加的课程消失的原因,因为旧 semester
和 semesterCourses
不包含新添加的课程。
因此,要解决此问题,您还需要将 semester
添加到您的比较中
if (JSON.stringify(this.props.course) === JSON.stringify(nextProps.course) &&
JSON.stringify(this.props.semester) === JSON.stringify(nextProps.semester)
) {
return false;
}
以上代码可以解决您的问题,但不会阻止其他课程的重新呈现。
更好的设计是不将 semester
属性传递给 <Course>
组件。
但如果这是不可避免的,那么也许不要创建 semester
和 semesterCourses
的新副本并保持你的 shouldComponentUpdate
不变。
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 semesters = [...this.state.semesters];
的新副本
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
}
我有 3 个组成部分:SemesterList、Semester 和 Course。
SemesterList 包含状态(包含所有学期及其内容的数组)。
在 Course 组件中,我创建了一个 shouldComponentUpdate() 方法,以避免呈现未更改的课程。如果没有这个方法,所有学期的所有课程都会重新渲染。
但是,添加课程后,当我修改除了添加的课程以外的其他课程时,添加的课程被删除了!
当我添加多门课程然后尝试修改最初存在的课程时,也会发生同样的事情。
我不知道为什么,但我认为这是由于 shouldComponentUpdate() 方法造成的。
这是 shouldComponentUpdate():
shouldComponentUpdate(nextProps, nextState) {
if (JSON.stringify(this.props.course) === JSON.stringify(nextProps.course)) {
return false;
}
return true;
}
我在 React 文档中读到 JSON.stringify() 很昂贵,但我暂时忽略它。
学期部分render方法部分:
{semester.courses.map(
course => (
<Course
key={course.id}
course={course}
semester={semester}
onInputChange={onInputChange}
onDeleteCourse={onDeleteCourse}
/>
)
)}
这是按下字符时调用的 onInputChange() 函数和添加课程时调用的 handleAddCourse .
handleInputChange = (event, course, semester) => {
const { name, value } = event.target;
var semesters = [...this.state.semesters], semesterCourses = [...semester.courses];
var course = { ...course };
course[name] = value;
semesterCourses[course.id-1] = course;
semester.courses = [...semesterCourses];
semesters[semester.number-1] = semester;
this.setState({ semesters });
}
handleAddCourse = semester => {
var semesters = [...this.state.semesters], semester = { ...semester };
var semesterCourses = [...semester.courses];
const semesterIndex = semester.number - 1;
semesterCourses.push({
// new course's id is obtained by incrementing last course's id which is the number of courses
id: semesterCourses.length + 1,
name: '',
credit: 0,
markOver100: 0.0,
grade: '',
});
semester.courses = semesterCourses;
semesters[semesterIndex] = semester;
this.setState({ semesters });
}
正如我之前所说,我认为问题出在 shouldComponentUpdate() 方法中,因为当它被注释掉时,一切都按预期工作。
您正在将 course
和 semester
属性传递给 <Course>
组件,但您的 JSON.stringify
比较仅检查 course
.
每次 add/change 一门课程,您都会使用扩展运算符创建 semester
和 semesterCourses
的新副本。因此,您现有的 <Course>
未重新渲染的组件将保留旧的 semester
。这就是当您更改任何现有课程时新添加的课程消失的原因,因为旧 semester
和 semesterCourses
不包含新添加的课程。
因此,要解决此问题,您还需要将 semester
添加到您的比较中
if (JSON.stringify(this.props.course) === JSON.stringify(nextProps.course) &&
JSON.stringify(this.props.semester) === JSON.stringify(nextProps.semester)
) {
return false;
}
以上代码可以解决您的问题,但不会阻止其他课程的重新呈现。
更好的设计是不将 semester
属性传递给 <Course>
组件。
但如果这是不可避免的,那么也许不要创建 semester
和 semesterCourses
的新副本并保持你的 shouldComponentUpdate
不变。
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 semesters = [...this.state.semesters];
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
}