Nextjs 获取链接中的参数

Posted by CodingWithAlice on February 14, 2025

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);
        }
    };
}