gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 13:53:00 31 4
gpt4 key购买 nike

场景是这样的:

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

处理这个问题最优雅的方法是什么?我应该分离 reducer 吗?

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

我还考虑过不在 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 来同步多个组件之间的状态:https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367 , 没关系。但如果只是因为您想重用加载部分,那么“一种优雅的方式”应该是为每个页面使用本地状态,并将所有加载代码放在 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-higher-order-component-53062c086cb

但是如果你需要或者你想保留 Redux 的想法,那么如果详细信息页面和列表页面共享来自 Redux State 的配置文件和评估 Prop ,那么你应该添加到 Redux State 和指示器,以便你可以协调所有数据已加载:

// 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
}

即便如此,您也应该阅读此链接 How to to cancel pending asynchronous actions in React/Redux ,并且您应该防止在应取消异步操作时继续加载。

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

关于reactjs - Next.js 保持当前页面处于事件状态并重新渲染,同时下一页的 getInitialProps 完成加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58138760/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com