12.Next.js14 数据获取fetch、服务端请求和客户端请求以及缓存设置

12.Next.js14 数据获取fetch、服务端请求和客户端请求以及缓存设置

获取数据

使用fetch在服务器上获取数据

Next.js扩展了原生的fetch Web API,允许您在服务器上配置每个fetch请求的缓存和重新验证行为。react通过在呈现React组件树时自动记忆fetch请求来扩展fetch。

您可以在服务器组件(Server Components)、路由处理程序(Route Handlers)和服务器操作(Server Actions)中使用async/awaitfetch

例如下面的例子:

//app/page.tsx
type User = {
    id:string,
    name:string,
    email:string
}
async function getData({
    const res = await fetch('https://jsonplaceholder.typicode.com/users')
    if (!res.ok){
        throw new Error('请求失败')
    }
    return res.json()
}
export default async function Home({
    const users:User[] = await getData()
  return (
   <main>
     <Link href="/users">Users</Link>
       <h1>用户列表</h1>
       {users.map((user)=>(
           <li key={user.id}>
               <Link href={`users/${user.id}`}>{user.name}</Link>
           </li>
       ))}
   </main>

  )
}

通过后端api获取到数据(通过服务端渲染)

首先我们在app目录下创建一个文章列表的文件posts,设置一个动态路由[id],这样我们就可以通过路由获取到文章的id,看以下代码:

//app/posts/[id]/page.tsx
export default function PostID({params}:any{
    return <main className="min-h-screen  p-24 " >
        文章ID:{params.id}
    </main>

}
12.Next.js14 数据获取fetch、服务端请求和客户端请求以及缓存设置
image.png

接下来我们来写后端的api,首先在app目录下面创建一个api/posts目录,在posts下面创建一个名为[id]的动态路由,我们要根据前端传过来的id,返回文章的内容。代码如下:

//app/api/posts/[id]/route.ts
import {NextResponse} from "next/server";
//有两篇文章
const posts:any = [
    {
        id:1,
        title:"Next.js学习1",
        description:"了解Next.js的基础知识1"
    },
    {
        id:12,
        title:"Next.js学习2",
        description:"了解Next.js的基础知识2"
    }
]
//文章筛选返回
export async function GET(request:Request,context:any{
    const { params } = context;
    return NextResponse.json({
        post:posts.find((item:any) =>item.id.toString() === params.id)
    });
}
  • 在前端发送请求
//app/posts/[id]/page.tsx
//通过id来查询文章
async function getPostById(postId:string{
    const response = await fetch(`http://localhost:3000/api/posts/${postId}`,{
        method:"GET"
    })
    return response.json();
}

 export default async function PostID( {params}:any{
    //调用根据id获取文章的方法
    const { post } = await getPostById(params.id);
    console.log('post',post)
    return <main className="min-h-screen  p-24 " >
        <h1 className="text-lg text-slate-900 py-3">{post.title}</h1>
        <p className="text-slate-500">{post.description}</p>
    </main>

}

我们选择的是id为1的文章,在浏览器上是不会看到数据的(是服务端渲染),只有在terminal里面看到打印的post如下:

12.Next.js14 数据获取fetch、服务端请求和客户端请求以及缓存设置
image.png

通过后端api获取到数据(通过客户端渲染)

如果你想在客户端获取到数据,首先我们要把页面改成客户端的,也就是设置'use client';

再来刷新一下页面,就会在浏览器的控制套看到:

12.Next.js14 数据获取fetch、服务端请求和客户端请求以及缓存设置
image.png

我们会发现接口请求了很多次。 而且,在terminal里面也有打印,显然不是一个客户端请求,下面我们来改一下。

//app/posts/[id]/page.tsx
'use client';
import { useState ,useEffect } from "react";
//对Post这个类型进行了定义,该类型是一个对象,包含可选的title和description属性,这两个属性的类型都是字符串。
type Post = {
    title?:string,
    description?:string
}

export default  function PostID({params}:any{
//使用React的useState hook来创建一个名为post的状态变量和一个修改这个变量的函数setPost。
//这个状态变量的初始值被设定为null,类型为Post或者null。
    const [post, setPost] = useState<Post | null>(null);
    //定义了一个异步函数getPostById,用于发起http请求,从服务器读取id为params.id的post。
    //如果读取成功,会使用setPost函数将读取到的post赋值给post状态变量。
    const getPostById = async  () =>{
        try {
            const response = await fetch(`http://localhost:3000/api/posts/${params.id}`,
                {method:"GET"}
            )
            if (response) {
                const {post} = await  response.json()
                console.log(response)
               if (post) {
                   setPost(post)
               }
            }
        }catch (e) {
            console.log(e)
        }
    }
    useEffect(() => {
        getPostById();
    }, []);

    return <main className="min-h-screen  p-24 " >
        {post && <h1 className="text-lg text-slate-900 py-3">{post.title}</h1>}
        {post &&<p className="text-slate-500">{post.description}</p>}
    </main>

}

再来看我们的页面,此时浏览器上就能看到请求:

12.Next.js14 数据获取fetch、服务端请求和客户端请求以及缓存设置
image.png

设置loading

当我们换成客户端渲染的时候,速度比服务端渲染慢了。这时我们可以加入一个加载的效果,你也可以因为一些UI的骨架组件。下面来简单的写一下:

'use client';
import { useState ,useEffect } from "react";
type Post = {
    title?:string,
    description?:string
}

export default  function PostID({params}:any{
    const [post, setPost] = useState<Post | null>(null);
    const [loading, setLoading] = useState(false);
    const getPostById = async  () =>{
        setLoading(true)
        console.log('222',loading)
        try {
            console.log('loading',loading)
            const response = await fetch(`http://localhost:3000/api/posts/${params.id}`,
                {method:"GET"}
            )
            if (response) {
                const {post} = await  response.json()
                console.log(response)
               if (post) {
                   setPost(post)
               }
            }
        }catch (e) {
            console.log(e)
        }finally {
            setLoading(false)
            console.log('333',loading)
        }
    }
    useEffect(() => {
        getPostById();
    }, []);

    return <main className="min-h-screen  p-24 " >
        {loading && <div>loading</div>}
        {!loading && <div>
            {post && <h1 className="text-lg text-slate-900 py-3">{post.title}</h1>}
            {post &&<p className="text-slate-500">{post.description}</p>}
        </div>}

    </main>

}

缓存

你在 App Router 中使用 fetch 功能时,它会自动配置为使用缓存。这扩展了 Web API 获取功能,因此可以使用选项来更改缓存设置。

默认情况下设置强制缓存。除了force-cache之外,还有no-store可以禁用缓存。

 const response = await fetch('http://localhost:3000/api',
        {cache:'no-store'}
    )

设置后,无论访问接口多少次,缓存值都保持“MISS”。

12.Next.js14 数据获取fetch、服务端请求和客户端请求以及缓存设置
image.png

由于我们正在向 http://localhost:3000/api 发送 GET 请求,因此我们将设置 console.log 来检查请求是否确实正在发送。

设置 next.revalidate

cache选项设置是否使用缓存,但通过设置next.revalidate选项,可以指定缓存的生存期。一旦配置的生命周期结束,将执行新的获取函数。

秒数可以使用revalidate值来设置,所以下面设置5秒。通过 fetch 进行访问,并且缓存值使用 5 秒,但之后会再次执行 fetch 函数。

 const response = await fetch('http://localhost:3000/api/hello',
        {
            // cache:'no-store'
            next: { revalidate5 },
        }
)


原文始发于微信公众号(大前端编程教学):12.Next.js14 数据获取fetch、服务端请求和客户端请求以及缓存设置

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/224340.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!