前言
主要讲解请求相关的常用方法:
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,则返回第一个匹配到的。
// 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
。
// 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 是否存在的布尔值。
// 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)
"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
"use server";
// app/actions.js
import { cookies } from "next/headers";
export async function create(data) {
cookies().delete("name");
}
cookies().set(name, '')
将指定名称的 cookie 设置为空值
"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 过期
"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 过期
"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 });
}
测试删除效果
如果你想要测试这些删除效果:
"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 来处理。
用法
// app/page.js
import { redirect } from "next/navigation";
export default function Page() {
redirect("/about");
}
permanentRedirect
介绍
permanentRedirect 函数,顾名思义,永久重定向地址,可用于服务端组件、路由处理程序、Server Actions。在 Streaming 中,使用重定向将插入一个 meta 标签以在客户端发起重定向,其他情况,它会返回一个 308 HTTP 重定向响应。如果资源不存在,可以直接使用 notFound 函数,并不一定需要 redirect 来处理。
用法
// 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
来优雅的处理这个错误。
// 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 的动态参数:
"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
不接收任何参数。
用法
const params = useParams();
返回值
useParams
返回一个包含当前路由动态参数的对象,让我们直接看个例子就明白了:
usePathname
介绍
usePathname
是一个客户端组件 hook,用于读取当前 URL 的 pathname。
"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 用于在客户端组件中更改路由:
"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 的查询字符串。
- 代码
"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}</>;
}