我正在使用Next.JS在一个应用程序中,我有一个应用程序的所有页面上都需要的Navbar
组件,并且Navbar
呈现必须从我的数据库中获取的数据(特别是product-categories
)。
我希望这个组件是服务器端渲染的,但由于 Next.JS 只支持页面级 SSR 而不是组件级 SSR,因此似乎我必须在要显示此Navbar
的所有页面上使用getServerSideProps
并在每个页面上编写相同的 API 请求,导致跨多个页面的大量重复逻辑和 API 调用。
在研究如何解决这个问题时,我遇到了 React Server 组件,想知道这是否是这种情况的有效解决方案,但由于我是这个概念的新手,我不确定我是否正确理解它,因此我为什么要写这个问题。
我正在考虑执行以下操作,并希望获得一些关于我是否走在正确轨道上的反馈。
我的导航栏组件如下所示:
const Navbar = () => {
const [data, setData] = useState();
useEffect(() => {
fetchData();
}, []);
const fetchData = async () => {
const data = await fetch("/api/someEndpoint");
setData(data);
};
return (
<div>
{data.someProperty}
{data.someOtherProperty}
</div>
);
};
export default Navbar;
然后我可以创建一个全局Layout
组件,以便导航栏包含在所有页面中,这是使用React.Suspense
的地方(如果我理解正确的话):
const Layout = ({ children }) => {
return (
<>
<React.Suspense fallback={<FallbackComponent />}>
<Navbar />
<React.Suspense />
{children}
</>
);
};
export default Layout;
然后在_app.tsx
中,我将包含我的Layout
组件,以便Navbar
无处不在:
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
所以我的问题来了:这是一个正确的实现和有效的React.Suspense
用例吗?组件级数据获取是 React Server 组件的建议优势之一吗?
现在使用Next.JS 13 版本,您可以创建一个默认使用 react 服务器组件的应用程序目录。
但是你应该记住,大多数 React 钩子(如 useState 和 useEffect)不适用于服务器组件,之前的 Next.js API 如 getServerSideProps、getStaticProps 和 getInitialProps 在新的应用目录中也不受支持。
因此,您可以使用基于本机 fetch() Web API 构建的新 fetch() API。查看文档以获取更多详细信息。
您可以在_app.tsx
中使用 SSR 将数据作为 props 传递给MyApp
钩子,而不是通过 API 获取。然后,数据可以进一步传递到Layout
组件中,该组件将再次将其进一步传递到Navbar
组件。所以它看起来像这样:
// _app.tsx
function MyApp({ /* Props */, data }) {
return (
<Layout data={data}>
<Component {...pageProps} />
</Layout>
);
}
export function getServerSideProps(context) {
// Get data
return {
props: {
data: data
},
}
}
// Layout.tsx
const Layout = ({ children, data }) => {
return (
<>
<Navbar data={data} />
{children}
</>
);
};
export default Layout;
// Navbar.tsx
const Navbar = ({ data }) => {
return (
<div>
{data.someProperty}
{data.someOtherProperty}
</div>
);
};
export default Navbar;
编辑:_app.tsx
中的SSR不起作用,但我在这里找到了答案:https://stackoverflow.com/a/72325973/12190941
编辑2: 如果您希望整个站点在服务器端呈现,则可以在_app.js
中使用getInitalProps
。请记住,这将增加初始加载时间。我在下面的.js文档中找到了这个例子
// _app.js
// ...
MyApp.getInitialProps = async (appContext) => {
// calls page's `getInitialProps` and fills `appProps.pageProps`
const appProps = await App.getInitialProps(appContext);
return { ...appProps }