初始渲染之前如何进行异步获取

问题描述

我目前正在前端使用Next.js使用wordpress API。我想获取导航/菜单数据并进行渲染。我已经尝试过,但是当我检查源代码时,仅呈现一个空的<nav> </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的方面根本不是异步的,即使您在async回调函数中定义了useEffect,执行此操作的正确方法是设置单独的状态-{{1} }应用于微调器,或将其包含在现有的控件中,该控件将控制微调器,因为您是通过REST获取数据的,所以基本上完​​整的示例应如下所示:

useState(false)钩子:

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
,

所以我弄清楚了,我在组件嵌套到的页面上获取了链接数据,然后使用组件组成将数据馈给了下来。问题是我必须直接将它们全部嵌套在页面上。如果有人有更好的解决方案,请告诉我:)

页面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>
  );
}