Nextjs 获取链接中的参数
总结:
-
目标:获取链接上的参数
-
使用 useSearchParams + layout.tsx:
import { useSearchParams } from 'next/navigation'; const searchParams = useSearchParams(); -- import { useSearchParams } from 'react-router-dom'; const [searchParams, setSearchParams] = useSearchParams(); const date = searchParams.get('date')
// layout.tsx - Suspense 为了处理依赖的路由的异步加载 export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="en"> <body> <Suspense fallback={<div>Loading...</div>}> {children} </Suspense> </body> </html> ); }
之前使用的方法
function getUrlParams() {
const queryString = window.location.search.substring(1); // 去掉 "?"
if (!queryString) return {};
const params = qs.parse(queryString);
return params;
}
但是由于 Nextjs 会预渲染 - 在服务端渲染时,没有 window
- Step1:使用 useRouter 处理路由
- 问题:在一个没有被「Nextjs路由系统管理」的页面中使用时,会报错
-
Step2:更推荐新的 hooks usePathname + useSearchParams
-
问题:使用时提示
useSearchParams should be wrapped in a suspense boundary at page
-
原因:和 App Router 架构及 React 的 Suspense 机制有关【使用 suspense 机制是为了处理异步数据的获取】
异步数据:useSearchParams 依赖路由信息,即依赖于路由数据的异步加载
-
解决方案:Nextjs 处理异步数据时,使用
<Suspense>
组件提供一个加载状态 - 在 layout.tsx 中export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="en"> <body> <Suspense fallback={<div>Loading...</div>}> {children} </Suspense> </body> </html> ); }
-
使用 Route 路由,可以封装一个自定义 useRouter
import {
useLocation,
useNavigate,
useParams,
useSearchParams
} from 'react-router-dom';
function useRouter() {
const location = useLocation(); // 获取当前位置对象
const navigate = useNavigate(); // 获取用于编程式导航的函数
const params = useParams(); // 获取 URL 参数
const [searchParams, setSearchParams] = useSearchParams(); // 获取查询参数
return {
pathname: location.pathname, // 当前路径
search: location.search, // 查询字符串
fullPath: location.pathname + location.search, // 完整的 URL 路径
hash: location.hash, // 哈希值
navigate, // 导航函数
params, // 路由参数
getQuery: (key) => searchParams.get(key), // 获取指定查询参数
setQuery: (key, value) => { // 设置查询参数
const newSearchParams = new URLSearchParams(searchParams);
newSearchParams.set(key, value);
setSearchParams(newSearchParams);
},
removeQuery: (key) => { // 移除查询参数
const newSearchParams = new URLSearchParams(searchParams);
newSearchParams.delete(key);
setSearchParams(newSearchParams);
}
};
}