簡體   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