Reactjs 当状态的特定部分丢失时,如何防止导航到组件?

Reactjs 当状态的特定部分丢失时,如何防止导航到组件?,reactjs,redux,react-router,react-redux,Reactjs,Redux,React Router,React Redux,首先,请原谅这个措辞拙劣的问题 我有一个SPA,它有一个页面,上面有以下路线: /students 此页面的容器是StudentsView.js,在其中我这样做是为了获得学生列表: componentDidMount () { this.props.actions.loadStudents() } 这是一个学生列表,单击其中一个将根据学生ID进入该学生的详细信息页面: /student/5 此页面的组件是StudentDetailView.js 现在为了避免不必要的API调用来

首先,请原谅这个措辞拙劣的问题

我有一个SPA,它有一个页面,上面有以下路线:

/students

此页面的容器是
StudentsView.js
,在其中我这样做是为了获得学生列表:

  componentDidMount () {
    this.props.actions.loadStudents()
  }
这是一个学生列表,单击其中一个将根据学生ID进入该学生的详细信息页面:

/student/5

此页面的组件是
StudentDetailView.js

现在为了避免不必要的API调用来提高初始应用程序加载期间的性能,我没有向
loadStudents()
操作发送调用,该操作通过API调用设置状态的学生部分,因为此页面不是我的应用程序的主页面

现在的问题是,当用户导航到学生详细信息页面时,会说:

/student/5

然后刷新页面,因为它们位于不同的组件上,并且不再调用
StudentsView.js
组件的
componentDidMount()
,因此在我的状态下,我会得到一个空的students数组,因此在我的students详细信息中,组件student将是未定义的:

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()
操作外,还有其他解决方法吗

最佳做法是什么?如果
学生列表为空,我是否将用户导航回列表页面?有没有办法,建议我取消
StudentDetailView.js
组件中的
loadStudents()
操作

基本上,当用户在
StudentDetailView.js
上时,如何确保始终填充状态的学生部分


谢谢您的帮助。

我相信您正在使用redux,因此在StudentDetail组件中,您可以发送一个操作,比如说
loadStudentById(5)
,在操作中,您可以检查
loadStudents
返回的数据是否可用,如果不可用,您可以先
loadStudents
,然后是
loadStudent()

所以
setStudent
可能是

function setStudent(student) {
  return {
    type: 'SET_STUDENT',
    payload: student
  }
}
要检查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
  }
}

经过深思熟虑后,我认为现在实现这一点的最佳方法是对student detail组件分派
loadStudentById()
操作。我可以在
componentDidMount()中执行此操作

事实证明,它有一种独特的异步加载路由的方法,他们建议不要使用生命周期挂钩来显示操作以检索数据。基本上,只有在路由匹配之后才能加载组件,在这一点上,我可以截获这个钩子,并在加载组件之前调度一个
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')
  }
})
详情如下:

这个项目的创作者采用了一种非常圆滑的方法

  componentDidMount () {
    const studentId = this.props.params.id
    this.props.actions.loadStudentById(studentId)
  }
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')
  }
})