Bob*_*erg 10 javascript next.js
我希望能够从服务器端的 API 检索数据,并将其加载到 React 上下文中,以使其可用于我的应用程序中的任何组件。我尝试了各种方法,但似乎没有什么能让我完全按照自己的意愿去做。我尝试过的一些事情包括:
getServerSideProps - 这允许我在服务器端检索数据,但只存在于页面组件中,所以如果我希望在每个页面上都可以使用它,并且我不知道我的用户将登陆哪个页面,我需要将此逻辑添加到每个页面。
_app.js 中的 getInitialProps - 我可以将其添加到 _app.js 组件中,该组件将在服务器端运行,并且可以通过上下文提供程序使其对所有组件可用,但问题是它在每个页面上运行,甚至在浏览客户端时。我希望能够一次且仅一次调用 API,但这似乎不允许。
_document.js 中的 getInitialProps - 我可以将其添加到 _document.js 组件中,该组件仅在服务器上运行,这似乎解决了为每个页面调用它的问题,但我无法弄清楚如何将它存储在 React 上下文中从那里。事实上,我似乎无法弄清楚如何在任何地方访问这些数据。它看起来像在_document.js getInitialProps被称为后在_app.js getInitialProps,所以我不知道如果我能在_document.js当我在_app.js使用我产生的价值从getInitialProps。
如果我在客户端上调用 API,有多种方法可以使此工作正常进行,但这不适用于我的用例,因为当客户端使用 API 中的数据更新时,它会导致内容闪烁。
有没有人想出解决这个用例的方法?
Eri*_*rel 35
Next.js 实验性应用程序文件夹现在完美地涵盖了这个用例。
当然,您可以在树中更下方的 RSC 中设置此上下文,例如,如果您仅在某个页面或页面的某个组件上需要它。
在这个现实生活中的示例中,我在 RSC 页面中获取调查定义,并通过上下文将其传递给客户端代码。我的上下文提供程序公开了一个类型化的可重用挂钩。
React 服务器组件的示例代码(此处为页面):
// /app/referer/page.tsx (Server Component)
import { headers } from 'next/headers'
export default async function Page() {
const headersList = headers()
const referer = headersList.get('referer')
return (
// we set a CLIENT context,
// based on the SERVER context that we got via headers()
<RefererProvider value={referer}>
<InteractiveReferer />
</RefererProvider>
)
}
Run Code Online (Sandbox Code Playgroud)
客户端上下文的示例代码(不要忘记"use client"指令):
// /components/InteractiveReferer.tsx (Client Component)
// use "client"
export const InteractiveReferer = () => {
// this context has been initialized by a parent RSC
// but we can access it as expected in a Client Component
const referer = useRefererContext()
const [clickedReferer, setClickedReferer] = useState(false)
return (
<button
onCLick={() => {
setClickedReferer(true)
}}
>
Referer: {referer}
</button>
)
}
Run Code Online (Sandbox Code Playgroud)
Next.js 应用程序文件夹的另一个新颖之处是,现在服务器端代码不再局限于页面级别getServerSideProps。嵌套组件也可以是服务器组件并触发服务器调用。因此,有时您可能不仅想设置客户端上下文,还想设置一种服务器端上下文,其范围仅限于当前请求。
我在本文中详细描述了这个用例。综上所述,您可以使用 React 18cache函数(在撰写本文时尚未记录)来实现此目标。
我制作了此模式的开源演示,可以通过以下代码示例进行总结:
import { cache } from "react";
export const getServerContext = cache(() => ({
// a dummy context for the demonstration
createdAt: Date.now().toString(),
calledByLayout: false,
calledByPage: false,
calledByNested: false
}))
Run Code Online (Sandbox Code Playgroud)
您可以直接改变返回值以在此上下文中存储新信息。
关于命名的注释:我一直使用术语“服务器上下文”来指定存储在cache充当上下文的数据。这是因为它是“客户端”上下文的服务器端等效项。然而,“请求缓存”可能更合适,因为“服务器上下文”在 Next.js 和 React 的未来版本中可能用于其他目的(在 RSC 和客户端组件之间共享数据)。
对于 RSC,“缓存”函数允许实现“缓存 getter”,您并不真正传递值,而是调用该函数来获取值。由于缓存,该值实际上只检索一次,您的数据库或 API 不会因请求而过载。
在极少数情况下,无法使用此方法,即如果您想从页面 props 中获取值(而不是从 API/数据库中获取数据)并将其传递给子项而无需进行 props 钻探。
server -only-context包实现了一种替代的“获取/设置”模式,用于模仿 RSC 的上下文。您可以在页面中设置一个值,并在组件中访问它。请注意,您无法保证布局在页面之前呈现(由于客户端导航),因此您无法从布局设置值并从页面获取它。希望这种模式永远不会被严格需要。
在 Next.js 中,没有本机函数 a) 从 API 检索数据,b) 在服务器上执行,c) 使其在每个页面上都可用,以及 d) 仅在用户访问的第一个页面上查询 API。
正如你已经发现了,getInitialProps并且getServerSideProps将运行每次访问该网页。
但是,我们可以让它发挥作用。
getInitialProps在_app.js从API获取数据_app.js文件内的 React 上下文中,使其在页面之间保持不变getInitialProps,检查是否有 cookie。如果是这样,请不要检索数据。在 Next.js 项目中有一个相当流行的库,称为nookies来帮助处理 cookie。
使用getInitialPropsin存在性能成本_app.js:您永远无法创建完全静态的页面。那是因为getInitialProps必须在每个页面加载时运行。
如果可以在页面加载后获取数据,请添加API 路由。然后,在上下文提供程序中,用于useEffect获取数据。
| 归档时间: |
|
| 查看次数: |
988 次 |
| 最近记录: |