javascript - NextJS 官方示例代码:_app.getInitialProps 调用 Component.getInitialProps——这是为了确保所有页面都加载数据吗?
问题描述
我试图了解如何将 redux-saga 连接到 NextJS 并遵循他们提供的示例代码 - https://github.com/zeit/next.js。我知道可以从内部加载数据,getInitialProps
但我不明白调用到Component.getInitialProps
:
class MyApp extends App {
static async getInitialProps({Component, ctx}) {
let pageProps = {}
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps({ctx})
}
return {pageProps}
}
render() {
const {Component, pageProps, store} = this.props
return (
<Container>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</Container>
)
}
}
export default withRedux(createStore)(withReduxSaga({async: true})(MyApp))
这是否允许加载页面的 getIntialProps 中的所有异步加载?也就是说,在index.js
我们有代码
class Index extends React.Component {
static async getInitialProps (props) {
const { store, isServer } = props.ctx
store.dispatch(tickClock(isServer))
if (!store.getState().placeholderData) {
store.dispatch(loadData())
}
return { isServer }
}
componentDidMount () {
this.props.dispatch(startClock())
}
render () {
return <Page title='Index Page' linkTo='/other' NavigateTo='Other Page' />
}
}
这 会getInitialProps
等到所有数据都加载完毕后再返回吗?它如何知道何时加载?
非常感谢任何帮助!
解决方案
由于 _app.js 是一个 HoC,因此 _app.js 中的组件基本上就是您要从 pages 文件夹加载的页面(如果您进一步编写,您可以传播另一个 HoC,然后加载您的页面,这取决于您的应用程序,但随后在你的 compose HoC 你必须再次实现 getInitialProps 然后执行你最终 page.js 的 getInitialProps)。每个页面都可以有一个自己的 getInitialProps(例如,在您的联系页面上,您想要加载您的公司地址,并且仅在您的整个应用程序中)。_app.js 执行 Component.getInitProps(如果设置)。如果组件的方法返回一个非空对象,它将成为您的 pageProps,您最终在 render 方法中将其提供给组件。
您的 page.js 现在实现了一个 getInitProps 方法,该方法分派一个传奇任务并返回 isServer ...给定的情况下,只有您的商店通过分派操作来补充水分 - getInitProps 不必等待任何东西并返回一个布尔值。商店补水后,您的组件将被更新,因为您在商店中的道具已加载/更新。
但是我目前面临同样的问题:
我在我的 getInitProps 中调度 saga 任务,但由于操作是异步的,我在 ComponentDidMount 之后收到了道具。
编辑:
TL:博士;
- Saga 任务是线程,或者如果您想要一种事件侦听器。
- 每次您发送一个 saga 动作(取决于您的 saga)时,都会启动一个侦听器
- 在我们的例子中,如果我们在 getInitialProps 中触发一个动作,我们会使用 saga 任务将动作分派到商店,但是 store.dispatch 方法不是 async => 导致 getInitialProps 不会被动作阻塞并立即返回道具,尽管触发的任务还没有完成
- Victor 的解决方案以及 next-redux-saga 包中的解决方案是 1. 调度停止当前根任务的 'END' 操作和 2. 应用 toPromise() 方法,它使您能够异步等待 sagas结束。=> 你有点阻止 getInitialProps 并强制方法在方法返回之前等待 sagas 结束;
- 重要提示:当您停止 saga 线程时,这没关系,并且必须/应该在服务器上完成,但是您的应用程序需要客户端的 sagas 才能正确处理存储副作用,因此如果 !isServer,您必须重新运行 sagas。
更新:
它不起作用。您只能停止服务器上的 sagas,因为您只需要它们进行初始执行,之后服务器上的 sagas 就毫无用处了。但是在客户端,您无法停止 sagas。
这是我的 store.js ......您可以执行初始 sagas,服务器将在 getInitialProps 中等待它们完成,因为 toPromise() 使停止异步。
在客户端,您必须通过生命周期等方式工作......客户端商店水合作用不像我预期的那样工作。也许更好,否则你会阻止 React 渲染,这通常与 React 背道而驰。
store.runSagas = () => {
if (!store.currentSagas) {
store.currentSagas = sagaMiddleware.run(rootSaga);
}
};
store.stopSagas = async () => {
if (store.currentSagas) {
store.dispatch(END);
await store.currentSagas.toPromise();
}
};
store.execTasks = isServer => async (tasks = []) => {
tasks.forEach(store.dispatch);
if (isServer) {
await store.stopSagas();
}
};
推荐阅读
- reactjs - 如何使用 JSON 用户 API 中的 POST 将密码值传递给 wordpress
- typescript - 如何将“typeorm”模型转换为 graphql 有效负载?
- pdf - 如何在 RMarkdown 中创建一个简单的文本表格,用于 PDF 输出
- python - 任何用于使用 biarcs 逼近 Bezier 曲线的 python 库?
- python - 熊猫中的数据框子
- javascript - Gif 没有在 IE11 上设置动画,而 chrome 可以运行后台脚本
- javascript - getProperty() 属性参数值(未定义)不是字符串。错误:
- c++ - 为什么我们将 [ ] 与指向数组的指针一起使用?
- powershell - 从 PowerShell 脚本调用 MSBuild 运行缓慢 (Visual Studio 2019)
- python - 如何使用 OpenCV 或 numpy 打印线上每个点的坐标?