首先,请原谅这个措辞不佳的问题。
我有一个SPA,它有一个包含以下路由的页面:
/students
此页面的容器是StudentsView.js,我在其中执行以下操作以获取学生列表:
componentDidMount () {
this.props.actions.loadStudents()
}这是一个学生列表,单击一个将根据学生ID进入该学生的详细信息页面:
/student/5
此页面的组件是StudentDetailView.js
现在,为了避免不必要的应用程序调用以提高初始应用程序加载期间的性能,我没有调度对loadStudents()操作的调用,因为该页面不是我的应用程序的主页。
现在的问题是,当用户导航到学生详细信息页面时,例如:
/student/5
然后刷新页面,因为它们位于不同的组件上,并且StudentsView.js组件的componentDidMount()不再被调用,所以我的状态中有一个空的学生数组,所以在我的学生详细信息组件中,学生将是未定义的:
function mapStateToProps (state, ownProps) {
const studentId = +ownProps.params.id
let student = { id: '', firstName: '', lastName: '' }
if (studentId && state.students.length > 0) {
student = getStudentById(state.students, studentId)
}
return {
student: student
}
}除了确保在最初的应用程序加载中调用loadStudensts()操作之外,有没有办法解决这个问题?
最佳实践是什么?如果students列表为空,我是否要将用户导航回列表页面?有没有一种方法,是否建议我在StudentDetailView.js组件中分离loadStudents()操作?
基本上,当用户在StudentDetailView.js上时,我如何确保始终填充状态的学生部分
谢谢你的帮助。
发布于 2017-07-16 17:10:25
我相信你正在使用redux,所以在你的StudentDetail组件中,你可以分派一个动作,比如loadStudentById(5),在你的动作中,你可以检查loadStudents返回的数据是否可用,如果不能,你可以先loadStudents,然后是loadStudent()。
//somewhere in your actions
function loadStudent(studentId) {
return (dispatch, getState) => {
dispatch(loadStudents()).then(() => {
const students = getState().students.get('students')
const student = students.find(s => s.id === studentId)
// This action will set the student in reducer when type is matched
dispatch(setStudent(student))
})
}
}所以setStudent可能是这样的
function setStudent(student) {
return {
type: 'SET_STUDENT',
payload: student
}
}要检查学生是否已经有空,并避免在loadStudents中调用API,可以这样做。
function loadStudents() {
return (dispatch, getState) => {
const students = getState().students.get('students')
// Return early avoiding API call
if (students && students.length > 0) {
return Promise.resolve()
}
// actual API loading logic here
}
}发布于 2017-07-16 23:26:35
我认为现在实现这一点的最好方法是在学生详细信息组件上分派一个loadStudentById()操作。我可以在componentDidMount()中做这件事
componentDidMount () {
const studentId = this.props.params.id
this.props.actions.loadStudentById(studentId)
}事实证明,the seed project I'm using有一种独特的异步加载路由的方法,他们建议不要使用生命周期钩子来阻碍检索数据的操作。基本上,只有在路由匹配之后才加载组件,此时我可以截获此钩子,并在加载组件之前分派一个getStudentById()操作。类似于:
import { loadStudentById } from '../../actions/studentActions'
export default (store) => ({
path : 'student/:id',
getComponent (nextState, cb) {
require.ensure([], (require) => {
const studentId = nextState.params.id
store.dispatch(loadStudentById(studentId))
const student = require('./components/StudentDetailView').default
cb(null, student)
}, 'student')
}
})更多详细信息请点击此处:
Populating a Component On Load
这个项目的创建者采用了一种非常时髦的方法。
https://stackoverflow.com/questions/45126619
复制相似问题