【发布时间】:2017-05-01 14:18:12
【问题描述】:
我有一个似乎没有触发componentDidMount 事件的组件。该组件是通过另一个组件使用 react-router 链接访问的父组件。
这是我的列表组件和子组件:
课程页面
import React from 'react';
import CourseList from './CourseList';
import CourseApi from '../../api/courseApi';
import {browserHistory} from 'react-router';
class CoursesPage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
courses: []
};
this.redirectToAddCoursePage = this.redirectToAddCoursePage.bind(this);
}
componentDidMount(){
CourseApi.getAllCourses().then(coursesData => {
this.setState({ courses: coursesData });
}).catch(error => {
throw(error);
});
}
redirectToAddCoursePage() { browserHistory.push('/course'); }
render() {
const courses = this.state.courses;
return (
<div>
<div className="page-header">
<h3>Courses</h3>
</div>
<input type="submit" value="New Course" className="btn btn-default btn-toolbar pull-right" onClick={this.redirectToAddCoursePage} />
<div className="panel panel-default ">
<div className="panel-heading">
<span> </span>
</div>
<CourseList courses={courses} />
</div>
</div>
);
}
}
export default CoursesPage;
课程列表行
import React from 'react';
import PropTypes from 'prop-types';
import CourseListRow from './CourseListRow';
const CourseList = ({courses}) => {
return (
<table className="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Author</th>
<th>Category</th>
<th>Length</th>
</tr>
</thead>
<tbody>
{ courses.map(course => <CourseListRow key={course.CourseId} course={course} /> )}
</tbody>
</table>
);
};
CourseList.propTypes = {
courses: PropTypes.array.isRequired
};
export default CourseList;
课程列表行
import React from 'react';
import PropTypes from 'prop-types';
import {Link} from 'react-router';
const CourseListRow = ({course}) => {
return (
<tr>
<td><Link to={'/course/' + course.CourseId}>{course.CourseId}</Link></td>
<td>{course.Title}</td>
<td>{course.Author.FirstName + ' ' + course.Author.LastName}</td>
</tr>
);
};
CourseListRow.propTypes = {
course: PropTypes.object.isRequired
};
export default CourseListRow;
我的路线
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from './components/App';
import CoursesPage from './components/course/CoursesPage';
import ManageCoursePage from './components/course/ManageCoursePage';
export default (
<Route path="/" components={App}>
<IndexRoute component={HomePage} />
<Route path="courses" component={CoursesPage} />
<Route path="course" component={ManageCoursePage} />
<Route path="course/:id" component={ManageCoursePage} />
</Route>
);
以上所有组件都可以正常工作。但是,当我单击 CourseListRow 组件中的课程链接以路由到下面的组件时,课程对象的状态始终为空。我在 componentDidMount 事件中放置了一个调试器语句,它从来没有命中它,所以这个组件 CourseForm 子组件(未显示)永远不会得到课程:
import React from 'react';
import PropTypes from 'prop-types';
import CourseForm from './CourseForm';
import {authorSelectData} from '../../selectors/selectors';
import CourseApi from '../../api/courseApi';
import AuthorApi from '../../api/authorApi';
export class ManageCoursePage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
course: {},
authors: [],
};
}
componentDidMount() {
let id = this.props.params.id;
if (id) {
CourseApi.getCourse(id).then(courseData => {
this.setState({ course: courseData });
}).catch(error => {
throw(error);
});
}
AuthorApi.getAllAuthors().then(authorsData => {
this.setState({
authors: authorSelectData(authorsData)
});
}).catch(error => {
throw(error);
});
}
render() {
return (
<CourseForm
course={this.state.course}
allAuthors={this.state.authors}
/>
);
}
}
ManageCoursePage.contextTypes = {
router: PropTypes.object
};
export default ManageCoursePage;
对于我的生活,我无法理解为什么 componentDidMount 没有触发和填充课程状态对象。任何帮助表示赞赏
跟进:
我将父 (ManageCoursePage) 组件的渲染方法更改为以下内容,注释掉 CourseForm 子组件:
render() {
return (
<h2>Hi {this.state.course.CourseId}</h2>
/*<CourseForm
course={this.state.course}
authors={this.state.authors}
onChange={this.updateCourseState}
onSave={this.saveCourse}
onDelete={this.deleteCourse}
onCancel={this.cancelChange}
errors={this.state.errors}
saving={this.state.saving}
deleting={this.state.deleting}
/>*/
);
}
这很有效,我得到了“Hi 11”。无论出于何种原因,我的子组件似乎都没有从我的父母那里收到道具。这可能与反应路由器有关,我错过了什么吗?这让我很困惑
【问题讨论】:
-
也许这可以帮助github.com/reactjs/redux/issues/702我的猜测是您期望在路由更改时调用componentDidMount,但如果该组件已经安装它不会再次调用它
-
所以
ManageCoursePage正在渲染,但componentDidMount没有被解雇,对吗? 至少一次它几乎是不可能的,你 100% 确定这不是你的 API 调用的问题吗? -
詹姆斯 - 是的,就是这样。我在 componentDidMount 方法的顶部放置了一个调试器语句,但它没有命中它。如果我将其更改为 componentWillMount,它会到达那里但为时已晚,状态不会到达子组件。
-
其实我撒了谎。如果我在渲染方法中硬编码一个测试“课程”对象并将其传递给 courseForm 组件,它会命中 componentDidMount。我看到在 componentDidMount 之前调用了渲染,这似乎是我的问题。在调用 componentDidMount 之前,状态课程对象中没有任何内容。
-
呃。好的,在 componentDidMount 之前调用渲染不是我的问题,因为调用 this.setState 应该会导致重新渲染。我想我会更多地研究 React 组件的生命周期。
标签: javascript reactjs react-router