Skip to content

前言

主要讲解请求相关的常用方法:

  • fetch

  • cookies

  • headers

  • NextRequest

  • NextResponse

  • redirect

  • permanentRedirect

  • notFound

  • useParams

  • usePathname

  • useRouter

  • useSearchParams

fetch

可以看看 fetch 封装那篇介绍

cookies

介绍

cookies 函数用于:

在服务端组件读取传入请求的 cookie

Server Action 或路由处理程序中写入返回请求的 cookie

注意:之前的文章里也多次提到,cookies() 是一个动态函数,因为其返回值无法提前知道。所以在页面或者布局中使用该函数会导致路由转变为动态渲染。

cookies 方法

  • cookies().get(name)

该方法传入一个 cookie 名,返回一个具有 name 和 value 属性的对象。如果没有找到,返回 undefined,如果匹配到多个 cookie,则返回第一个匹配到的。

ts
// app/page.js
import { cookies } from "next/headers";

export default function Page() {
  const cookieStore = cookies();
  // 如果匹配到,theme 的值为 { name: 'theme', value: 'xxxx' }
  // 如果没有匹配到,theme 的值为 undefined
  const theme = cookieStore.get("theme");
  return "...";
}
  • cookies().getAll(name)

该方法类似于 get,但会以数组形式返回所有匹配到的 cookies ,匹配不到则返回空数组。如果没有指定 name,则返回所有可用的 cookie

ts
// app/page.js
import { cookies } from "next/headers";

export default function Page() {
  const cookieStore = cookies();
  return cookieStore.getAll().map((cookie) => (
    <div key={cookie.name}>
      <p>Name: {cookie.name}</p>
      <p>Value: {cookie.value}</p>
    </div>
  ));
}
  • cookies().has(name)

该方法传入一个 cookie 名,返回一个判断该 cookie 是否存在的布尔值。

ts
// app/page.js
import { cookies } from "next/headers";

export default function Page() {
  const cookiesList = cookies();
  // true | false
  const hasCookie = cookiesList.has("theme");
  return "...";
}
  • cookies().set(name, value, options)
ts
"use server";
// app/actions.js
import { cookies } from "next/headers";

async function create(data) {
  cookies().set("name", "lee");
  // or
  cookies().set("name", "lee", { secure: true });
  // or
  cookies().set({
    name: "name",
    value: "lee",
    httpOnly: true,
    path: "/",
  });
}

还有 domain、expires、httponly、maxage、path、samesite、secure、priority。 自己可以百度下

  • cookies().delete(name)

删除指定名称的 cookie

ts
"use server";
// app/actions.js
import { cookies } from "next/headers";

export async function create(data) {
  cookies().delete("name");
}
  • cookies().set(name, '')

将指定名称的 cookie 设置为空值

ts
"use server";
// app/actions.js
import { cookies } from "next/headers";

export async function create(data) {
  cookies().set("name", "");
}
  • cookies().set(name, value, { maxAge: 0 })

设置 maxAge 为 0,立即使 cookie 过期

ts
"use server";
// app/actions.js
import { cookies } from "next/headers";

export async function create(data) {
  cookies().set("name", "value", { maxAge: 0 });
}
  • cookies().set(name, value, { expires: timestamp })

设置 expires 为过去的值都会使 cookie 过期

ts
"use server";
// app/actions.js
import { cookies } from "next/headers";

export async function create(data) {
  const oneDay = 24 * 60 * 60 * 1000;
  cookies().set("name", "value", { expires: Date.now() - oneDay });
}

测试删除效果

如果你想要测试这些删除效果:

ts
"use client";
// app/page.js
import { create } from "./action";

export default function Page({ params }) {
  return (
    <form action={create}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  );
}

redirect

介绍

redirect 函数,顾名思义,重定向地址,可用于服务端组件、路由处理程序、Server Actions。在 Streaming 中,使用重定向将插入一个 meta 标签以在客户端发起重定向,其他情况,它会返回一个 307 HTTP 重定向响应。如果资源不存在,可以直接使用 notFound 函数,并不一定需要 redirect 来处理。

用法

ts
// app/page.js
import { redirect } from "next/navigation";

export default function Page() {
  redirect("/about");
}

permanentRedirect

介绍

permanentRedirect 函数,顾名思义,永久重定向地址,可用于服务端组件、路由处理程序、Server Actions。在 Streaming 中,使用重定向将插入一个 meta 标签以在客户端发起重定向,其他情况,它会返回一个 308 HTTP 重定向响应。如果资源不存在,可以直接使用 notFound 函数,并不一定需要 redirect 来处理。

用法

ts
// app/page.js
import { permanentRedirect } from "next/navigation";

export default function Page() {
  permanentRedirect("/about");
}

notFound

介绍

调用 notFound()函数会抛出一个 NEXT_NOT_FOUND 错误,并且中止该路由段的渲染。通过声明一个 not-found.js 文件可以为此路由段渲染一个 Not Found UI 来优雅的处理这个错误。

ts
// app/user/[id]/page.js
import { notFound } from "next/navigation";

async function fetchUser(id) {
  const res = await fetch("https://...");
  if (!res.ok) return undefined;
  return res.json();
}

export default async function Profile({ params }) {
  const user = await fetchUser(params.id);

  if (!user) {
    notFound();
  }

  // ...
}

useParams

介绍

useParams 是一个客户端组件 hook,用于读取当前 URL 的动态参数:

ts
"use client";
// app/example-client-component.js
import { useParams } from "next/navigation";

export default function ExampleClientComponent() {
  const params = useParams();

  // 路由 -> /shop/[tag]/[item]
  // URL -> /shop/shoes/nike-air-max-97
  // `params` -> { tag: 'shoes', item: 'nike-air-max-97' }
  console.log(params);

  return <></>;
}

参数

useParams不接收任何参数。

用法

ts
const params = useParams();

返回值

useParams 返回一个包含当前路由动态参数的对象,让我们直接看个例子就明白了:

usePathname

介绍

usePathname 是一个客户端组件 hook,用于读取当前 URL 的 pathname。

ts
"use client";
// app/example-client-component.js
import { usePathname } from "next/navigation";

export default function ExampleClientComponent() {
  const pathname = usePathname();
  return <p>Current pathname: {pathname}</p>;
}

usePathname 需要用在客户端组件中。

useRouter

介绍

useRouter hook 用于在客户端组件中更改路由:

ts
"use client";
// app/example-client-component.js
import { useRouter } from "next/navigation";

export default function Page() {
  const router = useRouter();

  return (
    <button type="button" onClick={() => router.push("/dashboard")}>
      Dashboard
    </button>
  );
}

在 Next.js 中,优先推荐使用 <Link> 组件来导航,其次再针对一些特殊的需求使用 useRouter

useRouter()

push

router.push(href: string, { scroll: boolean })执行一个客户端导航,会将新地址添加到浏览器历史栈中

replace

router.replace(href: string, { scroll: boolean })执行一个客户端导航,但不会在浏览器历史栈中添加新的条目。

refresh

router.refresh() 刷新当前路由

back

router.back() 向后导航到浏览器历史栈中的上一页

forward

router.forward()向前导航到浏览器历史栈中的下一页

useSearchParams

介绍

useSearchParams 是一个客户端组件 hook,用于读取当前 URL 的查询字符串。

  • 代码
ts
"use client";
// app/dashboard/search-bar.js
import { useSearchParams } from "next/navigation";

export default function SearchBar() {
  const searchParams = useSearchParams();

  const search = searchParams.get("search");

  // URL -> `/dashboard?search=my-project`
  // `search` -> 'my-project'
  return <>Search: {search}</>;
}

返回值