我正在使用
/app
目录构建 Next.js 13 项目。我有一个问题 - 在根布局中,我有一个永久的导航栏组件,该组件是从 /components/Navbar.jsx
导入的。基本上在Navbar.jsx
内部,我希望能够访问url中的slug参数,例如:localhost:3000/:slug
,其中我想要slug id。我已经为该 slug 定义了 Next.js 13 page.jsx。但是如何获取 navbar 组件中的 slug id。我也不想使用 window.location.pathname
,因为当页面路由到不同的 slug 时它不会改变,并且仅在我刷新时才会改变。
我尝试过旧的 Next.js 12 方法:
//components/navbar.jsx;
import { useRouter } from "next/navigation";
export default function Navbar () {
const router = useRouter();
const { slug } = router.query;
useEffect(() => {
console.log(slug);
}, []);
return <p>Slug: {slug}</p>
}
但是它不起作用。
要获取 Next.js 13 中服务器组件中的 URL 参数,您可以使用 Page 函数的
searchParams
参数。
网址
localhost:3000/?slug
page.js
export default function Page({searchParams}) {
return <Navbar slug={searchParams}></Navbar>
}
navbar.js
export default function Navbar(props) {
return <p>Slug: {props.slug}</p>
}
更多信息:https://beta.nextjs.org/docs/api-reference/file-conventions/page
另一种方法是使用挂钩
useSearchParams
。
来自文档:
import { useSearchParams } from 'next/navigation';
export default function Page() {
const searchParams = useSearchParams();
// E.g. `/dashboard?page=2&order=asc`
const page = searchParams.get('page');
const order = searchParams.get('order');
return (
<div>
<p>Page: {page}</p>
<p>Order: {order}</p>
</div>
);
}
(/blog/1)
(/blog?postId=123)
(/blog/1?postId=123)
UseParams()
'use client'
import { useParams } from 'next/navigation'
export default function ExampleClientComponent() {
const params = useParams()
// Route -> /shop/[tag]/[item]
// URL -> /shop/shoes/nike-air-max-97
// `params` -> { tag: 'shoes', item: 'nike-air-max-97' }
console.log(params)
return <></>
}
useSearchParams()
'use client'
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}</>
}
any
类型'use client'
export default function BlogPost(props: any) {
// URL -> blog/a/b?param1=IamfirstParam¶m2=IamsecondParam
return <div>{props}</div>;
// Output ->
//{
// params: { blogId: [ 'a', 'b' ] },
// searchParams: { param1: 'IamfirstParam', param2: 'IamsecondParam' }
//}
}
defined
类型'use client';
// URL -> blog/a/b?param1=IamfirstParam¶m2=IamsecondParam
export default function BlogPost({
params,
searchParams,
}: {
params: { blogId: string[] };
searchParams: { param1: string; param2: string };
}) {
return (
<div>
{params.blogId[0]}
{params.blogId[1]}
{searchParams.param1}
{searchParams.param2}
</div>
);
}
有关动态参数的所有可能性,请参阅:如何使用 nextjs 13 进行动态路由?
另请参阅最新的 Nextjs 13 代码模板 Next.js 13+ 强大片段 | TypeScript/Javascript
它包含
ts
和js
的广泛代码片段。查找所有片段 此处
我不知道问题是否仍然相关,但如果它是数组,您可以使用 NextRequest 包含的方法 nextUrl.searchParams.get 或 getAll
import { NextResponse, NextRequest } from 'next/server';
export async function GET(request: NextRequest) {
const queryParam = request.nextUrl.searchParams.get("queryParam");
return NextResponse.json({ message: 'Query parameter value is ' + queryParam }, { status: 200 });
}
我在端点中使用了它,但对于页面也是如此,必须警告 NextRequest 只能在服务器组件中使用,对于客户端组件,您需要 useRouter 和“使用客户端”
为了在 Next.js 13 中使用 typescript 在服务器端组件中获取
params
和 searchParams
,您应该定义您期望的 params 和 searchParams。例如:
// /app/category/[slug]/page.tsx
// Request URL localhost:3000/category/news?page=2
export default function PostsCategory({ params, searchParams }: { params: { slug: string }; searchParams: { page: string } }) {
const posts = getPostsByTag(params.slug, ['title', 'date', 'excerpt', 'image', 'slug', 'tags']);
const currentPage = searchParams && searchParams.page ? Number(searchParams.page) : 1;
const { slug } = params;
return (
<main>
<PaginatedPosts posts={posts} page={currentPage} title={`${slug}`} />
</main>
);
}
必须使用
usePathname
import { usePathname } from 'next/navigation';
官方文档对此说得非常清楚:https://nextjs.org/docs/app/api-reference/functions/use-search-params#server-components
页数
要访问页面(服务器组件)中的搜索参数,请使用
searchParams
属性。
布局
与页面不同,布局(服务器组件)不会收到
searchParams
属性。这是因为共享布局在导航期间不会重新渲染,这可能会导致导航之间出现陈旧的searchParams
。
相反,请在客户端组件中使用 Page
searchParams
属性或 useSearchParams
挂钩,该组件会使用最新的 searchParams
在客户端上重新渲染。
因此,只需制作一个小型客户端组件,该组件将在每次导航时重新渲染,并从布局中引用它。