Reactjs 在下一页的getInitialProps完成加载时,Next.js保持当前页处于活动状态并重新呈现

Reactjs 在下一页的getInitialProps完成加载时,Next.js保持当前页处于活动状态并重新呈现,reactjs,react-redux,next.js,Reactjs,React Redux,Next.js,场景是这样的: 在一个页面(AssessmentListPage)中,我显示了现有评估的列表;在第二页(AssessmentDetailPage)中,我将显示所选评估的详细信息 我使用的是redux,两个页面都使用相同的切片操作系统状态(评估) 当我从AssessmentListPage移动到AssessmentDetailPage时,一切正常;当我按下后退按钮时,它崩溃了 它崩溃的原因:Next.js将保持AssessmentDetailPage页面处于活动状态,直到静态getInitialP

场景是这样的:

  • 在一个页面(
    AssessmentListPage
    )中,我显示了现有评估的列表;在第二页(
    AssessmentDetailPage
    )中,我将显示所选评估的详细信息
  • 我使用的是redux,两个页面都使用相同的切片操作系统状态(
    评估
  • 当我从
    AssessmentListPage
    移动到
    AssessmentDetailPage
    时,一切正常;当我按下后退按钮时,它崩溃了
  • 它崩溃的原因:Next.js将保持
    AssessmentDetailPage
    页面处于活动状态,直到
    静态getInitialProps
    方法完成。被调用的操作会更改状态,并导致当前页面在没有预期数据的情况下重新呈现。然后正确呈现
    评估列表页面
  • 处理这个问题最优雅的方式是什么?我应该分开减速器吗

    目前,我只是更具防御性,并添加了通常不需要的检查,以避免这种特定的崩溃

    我还考虑过不在
    getInitialProps
    中加载数据,而是在
    componentDidMount()
    中加载数据,但我不喜欢复制代码来处理服务器端和客户端渲染的想法

    任何建议都将不胜感激。谢谢

    class AssessmentListPage extends React.Component {
      static async getInitialProps({ store, req }) {
        await store.dispatch(loadProfile(api)(req))
        await store.dispatch(loadAssessments(api)(req))
      }
    }
    
    class AssessmentDetailPage extends React.Component {
      static async getInitialProps({ store, req }) {
        await store.dispatch(loadProfile(api)(req))
        await store.dispatch(loadAssessment(api)(req, query.id))
      }
    }
    

    如果您使用Redux在多个组件之间同步状态,原因之一如下:,则可以。但是,如果只是因为您想重用加载部分,那么“优雅的方式”应该是为每个页面使用本地状态,并将所有加载代码放在一个HOC中:

    // withAssessmentInfo.js
    export default (WrappedComponent) => {
      return class AssessmentInfo extends React.Component {
         static async getInitialProps (context) {
            const props = await super.getInitialProps(context)
            props.profile = await loadProfile(api)(context.req)
            props.assessment = await loadAssessment(api)(context.req, context.req.query.id)
       }
    
       return {
        ...(WrappedComponent.getInitialProps ? await WrappedComponent.getInitialProps(context) : {}),
        ...props
       }
     }
    
     render () {
       return (
        <WrappedComponent {...this.props} />
       )
     }
    }}
    
    如果总是同时加载概要文件和评估,则可以使用异步操作加载它们()或使用中间件:

    export default store => next => action => {
        const result = next(action)
    
        if (action.type === LOAD_ASSESSMENT_INFO) {
           store.dispatch({
             type: LOADING_ASSESSMENT_INFO // the action put the loading state
           })
           const profile = await loadProfile(api)
           const assessment = await loadAssessment(api)(action.payload.id)
    
           store.dispatch({
             type: LOADED_ASSESSMENT_INFO, // this action put the ready state, and set the data
             payload: {
               profile,
               assessment
             }
           })
        }
    
        return result
    }
    
    即使如此,您也应该阅读此链接,并且应该防止在取消异步操作时继续加载


    我希望这些信息能帮助您找到最好的方法来组织您的项目,以便在使用NextJS时处理加载数据。

    您能发布记录的错误吗?我认为错误并不重要。基本上,列表页面需要一个浅层对象,而详细信息页面需要“完整对象”。发生此错误的原因是,当页面加载浅层版本以移动到列表页面时,详细信息页面仍然处于活动状态,并且重新呈现导致页面崩溃,因为它尝试访问不存在的数据。然后是否可以在codesandbox中进行复制?返回一个包含setTimeout的承诺,以模拟延迟
    // Redux State
    {
      assessmentData: {
         operation: 'ready', // ready || loading
         profile: null,
         assessments: null
      }
    }
    
    export default store => next => action => {
        const result = next(action)
    
        if (action.type === LOAD_ASSESSMENT_INFO) {
           store.dispatch({
             type: LOADING_ASSESSMENT_INFO // the action put the loading state
           })
           const profile = await loadProfile(api)
           const assessment = await loadAssessment(api)(action.payload.id)
    
           store.dispatch({
             type: LOADED_ASSESSMENT_INFO, // this action put the ready state, and set the data
             payload: {
               profile,
               assessment
             }
           })
        }
    
        return result
    }