Js:减少数据提取并在页面之间共享数据 [英] Next.js: Reduce data fetching and share data between pages
问题描述
我正在寻找在Next.js应用程序中更好地获取数据的解决方案。在这个问题中,我不仅在寻找解决方案,我还在寻找多个选项,以便我们可以看到利弊。
我遇到的问题
现在我有几个页面,它们都包括一个显示一些静态内容的组件和一个具有从API获取的一些动态内容的组件。每个页面在其getInitialProps()
中执行fetch()
以获取自己的页面数据和页脚数据,对所有页面都是相同的。
这当然是可行的,但有很多重复的数据获取。页脚数据将始终为所有页面显示,并且始终相同。它在API中也很少更改,因此不需要重新验证数据。
我正在寻找的答案
我不仅希望解决这一个问题,我还希望获得一个概述,以便为未来的项目学习一些新的实践。我喜欢写"显而易见的"代码,所以不去寻找过于繁琐的解决方案,比如写window
对象等。简单的解决方案依赖程度较低。我们的目标是建立一个快速的网站。减少网络使用量/API调用并不那么重要。
我到目前为止的想法
这是我提出的可能的解决方案,从简单/显而易见到更复杂。
- 在页脚组件(客户端)内执行提取
- 在所有/Pages上的getInitialProps(服务器端和客户端)中执行提取
- 使用临时对象Fetch in_app.js并挂钩到它的
getInitialProps()
并将其添加到道具中,这样所有页面都可以使用数据 - 使用Zeit/SWR和数据预取来缓存数据
- 使用redux存储全局状态
所有这些"工作",但它们中的大多数将不必要地重新获取数据,和/或增加一点复杂性。以下是我认为的利弊(数字同上):
- 👍简单!取码只在一个地方,它位于它被使用的地方。👎数据是在页面加载后提取的,因此内容会"跳"到视图中。数据一直在刷新。
- 👍简单!数据是在服务器上提取的,因此内容在呈现页面之前就可用。为每一页重新获取👎数据。我们必须记住为
getInitialProps()
中的每个页面获取相同的页脚数据。 - 👍我们可以在一个位置进行提取并将其添加到所有页面道具,因此页脚数据自动可用于所有页面道具。对于一些人来说,👎可能要更复杂一些才能容易地理解发生了什么,因为它需要更多地理解Next.js/Reaction是如何工作的。仍然重新获取所有页面的数据。我们现在相继执行两个
fetch()
调用(首先在_app.js中加载页脚内容,然后在每个页面中获取定制内容),因此速度更慢。 - 👍有点简单。我们甚至可以在加载JS之前使用预取将数据加载到缓存。在第一个页面加载后,我们将有快速的数据获取。可以在页脚组件中直接获取代码。👎
rel="preload"
预取技术并不适用于所有类型的获取(例如,Sanity的客户端使用groq)。为了避免在初始页面加载后加载数据的"跳跃"内容,我们应该为useSWR()
提供initialData
,这仍然需要我们在getInitialProps()
中获取数据,但只在服务器端这样做就足够了。可以使用新的getServerSideProps()
。 - 👍我们只需加载一次数据(?)并使其在整个应用程序中可用。快速和更少/不需要重新提取。👎增加了外部依赖。更复杂,因为您必须学习redux,即使只加载一个共享数据对象也是如此。
当前解决方案,使用项目符号编号2中描述的解决方案。
const HomePage = (props) => {
return (
<Layout data={props.footer}>
<Home data={props.page} />
</Layout>
)
}
// Not actual query, just sample
const query = `{
"page": *[_type == "page"][0],
"footer": *[_type == "footer"][0]
}`
HomePage.getInitialProps = async () => {
const data = await client.fetch(query)
return {
page: data.page
footer: data.footer
}
}
export default HomePage
想要更深入地了解这一点。我明显漏掉了什么?
推荐答案
O‘Right!我在找别的东西的时候发现了这个帖子。但既然我要处理类似的问题,我可以给你一些指导,我会尽我所能为你澄清。
因此,您希望在您的应用程序(页面/组件)之间共享某些数据。
- Next.js使用App组件初始化页面。您可以重写它并控制页面初始化。要实现这一点,只需在
pages
目录的根目录中创建_app.js
文件。有关更多信息,请访问此链接:https://nextjs.org/docs/advanced-features/custom-app - 就像您可以在页面中使用
getInitialProps
从API获取数据一样,您也可以在_app.js
中使用相同的方法。因此,我会获取我需要的数据,以便在我的应用程序中共享它们,并消除我的API调用。
好的,现在我可以想出两种方法在我的应用程序中共享数据
- 使用
createContext
挂钩。
1.1。使用createContext挂钩创建一个DataContext。并用<DataContext.Provider>
将<Component {...pageProps} />
括起来。
以下是一段代码片段,可以为您提供更好的线索:
<DataContext.Provider value={{ userData, footerData, etc... }}>
<Component {...pageProps} />
</DataContext.Provider>
1.2。现在,在其他页面/组件中,您可以访问数据上下文,如下所示:
const { footerData } = useContext(DataContext);
然后您就可以在您的前端进行操作
- 使用
getInitialProps
填充props
2.1。getInitialProps
用于异步获取一些数据,然后填充props
。这与_app.js
中的情况相同。
_app.js
中的代码如下所示:
function MyApp({ Component, pageProps, footerData }) {
//do other stuffs
return (
<Component {...pageProps} footerData={footerData} />
;
}
MyApp.getInitialProps = async ({ Component, ctx }) => {
const footerRes = await fetch('http://API_URL');
const footerData = await footerRes.json();
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps, footerData };
};
2.2。现在,在您的页面中(而不是在您的组件中),您可以访问道具,包括您从分享的道具 你就可以开始操控了。
希望我能给你一点提示和方向。祝您探索愉快。
这篇关于Js:减少数据提取并在页面之间共享数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!