繁体   English   中英

Next.js 保持当前页面处于活动状态并重新渲染,同时下一页的 getInitialProps 完成加载

[英]Next.js keeps current page active and re-rendering while getInitialProps of next page finishes loading

场景是这样的:

  1. 在一个页面( AssessmentListPage )中,我显示了现有评估的列表; 在第二页( AssessmentDetailPage )中,我显示了所选评估的详细信息;
  2. 我正在使用 redux 并且两个页面都使用相同的切片 os state( assessments
  3. 当我从AssessmentListPage移动到AssessmentDetailPage时,一切正常; 当我按下后退按钮时,它崩溃了。
  4. 它崩溃的原因: Next.js 保持AssessmentDetailPage页面处于活动状态,直到static getInitialProps方法完成。 被调用的操作会更改 state 并导致当前页面在没有预期数据的情况下重新呈现。 然后它正确呈现AssessmentListPage

处理这个问题的最优雅的方法是什么? 我应该分开减速器吗?

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

我还考虑过不在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))
  }
}

If you are using Redux to synchronize the state between several components for one of the reasons exposed here: https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367 , it is ok. 但如果只是因为你想重用加载部分,那么“一种优雅的方式”应该是为每个页面使用本地 state,并将所有加载代码放在一个 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} />
   )
 }
}}

所以现在,您可以通过这种方式加载数据:

class AssessmentListPage extends React.PureComponent {
   static propTypes = {
     profile: PropTypes.object.isRequired,
     assessment: PropTypes.array.isRequired
   }

   static async getInitialProps(context) {
      // load specific data for this page here
   }

   render () {
     const { profile, assessment } = this.props

     if (profile && assessment) {
       <div>your component code</div>
     } else {
       return (
         <div>Loading some data...</div>
       )
     }
   }
}

export default withAssessmentInfo(AssessmentListPage)

AssessmentDetailPage 的想法相同。

参考:

https://reactjs.org/docs/higher-order-components.html https://medium.com/@Farzad_YZ/handle-loadings-in-react-by-using-higher-order-components-2ee8de9c3deb https:/ /medium.com/@mcculloughjchris/fetching-data-with-a-higher-order-component-in-react-43c622c30a82 https://medium.com/@guigonc/refactoring-moving-api-calls-to-a-高阶组件 53062c086cb

But if you need or you want to keep the Redux idea, then if detail page and list page are sharing profile and assessment props from the Redux State, so you should add to the Redux State and indicator so you can coordinate all data loaded:

// Redux State
{
  assessmentData: {
     operation: 'ready', // ready || loading
     profile: null,
     assessments: null
  }
}

如果您总是一起加载配置文件和评估,您可以使用异步操作来加载它们( https://github.com/reduxjs/redux-thunk )或使用中间件:

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
}

即便如此,你应该阅读这个链接如何在 React/Redux 中取消挂起的异步操作,并且你应该防止在应该取消异步操作时继续加载。

我希望这些信息可以帮助您找到构建项目以处理使用 NextJS 加载数据的最佳方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM