如何渲染异步页面组件作为一个孩子在next.js?



我正在使用next.js的新功能来渲染使用SSR的内容,我正在制作组件async作为docs所说的。

这是我的简单页面组件

export default async function Home() {
const res = await fetch("http://localhost:3000/api/get-quotes");
const quotes = await res.json();
return (
<main className={styles.main}>
<h1>Hello Visrut</h1>
<div>
<span>Total quotes: {quotes.length}</span>
</div>
</main>
)
}

我的应用程序中有authenticatednon-authenticated路由,我在_app.tsx

中如何将它们分开
// _app.tsx
interface AppProps {
Component: React.ElementType;
pageProps: Record<string, unknown>;
}
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
const router = useRouter();
if (router.pathname.includes("home")) {
return <Home />;   // Error: 'Home' can't be used as a JSX component, Its return type Promise<Home> is not a valid JSX component.
}
return (
<AuthContextProvider>
<Navbar />
<Head />
<Component {...pageProps} />
<Footer />
</AuthContextProvider>
)
};
export default App;

我想渲染不需要身份验证的Home组件,似乎我不能直接把它作为孩子也因为async关键字。

我也在浏览器上得到这个错误,而直接渲染async组件到其他正常组件在next.js

Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.

将异步代码移动到getServerSideProps函数中,并将响应作为Props传递到Home组件

未来12参考:https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props

export async function getServerSideProps() {
const res = await fetch("http://localhost:3000/api/get-quotes");
const quotes = await res.json();
return {
props: {
quotes: quotes,
}, // will be passed to the page component as props
};
}
export default function Home({quotes}) {
return (
<main className={styles.main}>
<h1>Hello Visrut</h1>
<div>
<span>Total quotes: {quotes.length}</span>
</div>
</main>
)
}
<标题>

下13 h1> div class="one_answers">你的代码中有一些概念问题

你不能有这样的异步组件,组件必须是同步函数,为了解决这个问题,你有一些方法

使用useEffect:您可以在处理这些异步问题的效果中调用fetch,就像这样:

import { useState, useEffect } from 'react';
export default function Home() {
const [quotes, setQuotes] = useState([])
const [loading, setLoading] = useState(true)
useEffect(() => {
const getData = async () => {
const res = await fetch("http://localhost:3000/api/get-quotes");
const data = await res.json();
setQuotes(data)
setLoading(false)
}
getData();
return () => {
// here you can clean the effect in case the component gets unmonth before the async function ends
}
},[])
if (loading) {
return <>loading...</>
}
return (
<main className={styles.main}>
<h1>Hello Visrut</h1>
<div>
<span>Total quotes: {quotes.length}</span>
</div>
</main>
)
}

使用Next中的SSR看看这里的https://nextjs.org/docs/basic-features/data-fetching/overview,你可以看到一些在渲染页面之前获取数据的选项,这很好,这里有一个例子:

import { useRouter } from 'next/router'
export default function Home({data}) {
const router = useRouter();
if (!router.isReady) {
return <>loading...</>
}
return (
<main className={styles.main}>
<h1>Hello Visrut</h1>
<div>
<span>Total quotes: {data.length}</span>
</div>
</main>
)
}
export const getServerSideProps = async () => {
const res = await fetch("http://localhost:3000/api/get-quotes");
const data = await res.json();
return {
props: {
data,
},
}
}

这将解决你提到的问题,但你也有一个概念问题与_app文件,你想要限制导航的方式,它看起来像你想要的布局(导航栏,页脚等)只渲染时,它不是家,所以这将是这样的:

const App: React.FC<AppProps> = ({ Component, pageProps }) => {
const router = useRouter();
if (router.pathname.includes("home")) {
return <Component {...pageProps} />
}
return (
<AuthContextProvider>
<Navbar />
<Head />
<Component {...pageProps} />
<Footer />
</AuthContextProvider>
)
};

然而,这只限制了它根据每个路由显示的视觉效果,这里你并没有真正验证你是否有一个活跃的会话,但是,嘿,我希望它能帮助你!

最新更新