繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM