[英]How to do an async fetch before initial render
我目前正在使用 Wordpress API 在前端使用 Next.js。 我想获取我的导航/菜单数据并进行预渲染。 我已经尝试过,但是当我检查源代码时,只呈现了一个空的<nav> </nav>
元素。 有一个简单的解决方案吗?
这是我的导航组件:
import { Config } from "../config";
import Link from "next/link";
import useFetch from "../hooks/useFetch";
export default function MainNav() {
const links = useFetch(`${Config.apiUrl}/wp-json/menus/v1/menus/main-nav`);
return (
<nav>
{!!links &&
links.map((link) => (
<Link href="/">
<a>{link.title}</a>
</Link>
))}
</nav>
);
}
我的自定义useFetch.js
挂钩:
import { useEffect, useState } from "react";
export default function useFetch(url) {
const [links, setLinks] = useState();
// Must use useEffect in non-page component
useEffect(async () => {
let res = await fetch(url);
res = await res.json();
setLinks(res.items);
}, []);
return links;
}
首先,useEffect 根本不是异步的,即使您在useEffect
回调 function 中定义了async
,正确的方法是为微调器设置单独的 state - useState(false)
或将其包含到现有的微调器中,这将控制微调器,因为您是通过 REST 获取数据,基本上完整的示例应该如下所示:
useFetch.js
钩子:
import { useEffect, useState } from "react";
export default function useFetch(url) {
const [{ links, isLoading }, setLinks] = useState({ links: [], isLoading: true });
// Must use useEffect in non-page component
useEffect(() => {
(async funtion() {
const res = await fetch(url);
const { items } = await res.json();
setLinks({ links: items, isLoading: false });
})()
}, []);
return [isLoading, links];
}
Nav.js
组件:
import { Config } from "../config";
import Link from "next/link";
import useFetch from "../hooks/useFetch";
export default function MainNav() {
const [links, isLoading] = useFetch(`${Config.apiUrl}/wp-json/menus/v1/menus/main-nav`);
if(isLoading) {
return <Spinner/>
}
return (
<nav>
{!!links && !isLoading &&
links.map((link) => (
<Link href="/">
<a>{link.title}</a>
</Link>
))}
</nav>
);
}
所以我想通了,我在组件嵌套的页面上获取了链接数据,然后使用组件组合将数据向下馈送。 问题是我必须直接将它们全部嵌套在页面上。 如果有人有更优雅的解决方案,请告诉我:)
页面index.js
:
import PostIndex from "../components/PostIndex";
import Layout from "../components/Layout";
import Header from "../components/Header";
import MainNav from "../components/MainNav";
import { Config } from "../config";
export default function Home(props) {
return (
<Layout>
<Header>
<MainNav links={props.links} />
</Header>
<h2>Home Page</h2>
<PostIndex limit={3} />
</Layout>
);
}
export async function getServerSideProps() {
const [data1, data2] = await Promise.all([
fetch(`${Config.apiUrl}/wp-json/wp/v2/posts?per_page=3`),
fetch(`${Config.apiUrl}/wp-json/menus/v1/menus/main-nav`),
]);
const posts = await data1.json();
const links = await data2.json();
return {
props: {
posts,
links,
},
};
}
Layout.js
组件:
export default function Layout({ children }) {
return <div>{children}</div>;
}
Header.js
组件:
import Link from "next/link";
export default function Header({ children }) {
return (
<div>
<Link href="/">
<a>
<h1>Wordpress Blog</h1>
</a>
</Link>
{children}
</div>
);
}
MainNev.js
组件:
import { Config } from "../config";
import Link from "next/link";
export default function MainNav({ links }) {
return (
<nav>
{!!links &&
links.items.map((item) => (
<Link href="/">
<a>{item.title}</a>
</Link>
))}
</nav>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.