You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义NPM包中用useSearchParams为何仍报useLocation需在Router上下文?

解决共享NPM包中react-router-dom钩子的上下文错误

我搜了好几个小时都没找到靠谱的解决方案,干脆自己折腾出结果,写下来帮遇到同样坑的人省时间。

问题描述

我有个用react-router-dom做路由的React项目,同时维护了一个独立的NPM共享包,里面放了多个项目共用的逻辑。我在共享包里写了个自定义Hook,用来监听URL搜索参数变化并更新状态:

// 这段代码在我的共享NPM包中
import { useSearchParams } from 'react-router-dom';
import { useEffect } from 'react';

export function useCustomHookExample(): void {
  const [searchParams] = useSearchParams();
  useEffect(() => {
    // 这里处理搜索参数逻辑...
  }, [searchParams]);
}

但在主项目里用这个Hook时,直接抛出错误:

Uncaught Error: useLocation() may be used only in the context of a <Router> component.

我当然知道useSearchParams内部调用了useLocation,必须在Router上下文里用,但我明明已经在项目根组件外层套了BrowserRouter:

export function AppRouter() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path='/' element={<App />} />
      </Routes>
    </BrowserRouter>
  );
}

export function App() {
  // 明明在Router上下文里,还是报错😭
  useCustomHookExample();
  // ...其他代码
}

根本原因

问题出在依赖重复安装上:共享包和主项目各自安装了一份react-router-dom,哪怕版本号看起来差不多,它们也是两个完全独立的模块。主项目的BrowserRouter是主项目里的react-router-dom提供的上下文,而共享包里的useSearchParams用的是共享包自己的react-router-dom的上下文,两者不互通,所以Hook找不到对应的Router。

解决方案

  1. 统一react-router-dom版本
    确保主项目和共享包使用的react-router-dom版本完全一致,比如都用^6.14.0。

  2. 把react-router-dom设为peer依赖
    在共享包的package.json中,把react-router-dom从dependencies或devDependencies移到peerDependencies,这样共享包会直接使用主项目安装的react-router-dom,不会自己单独装一份:

{
  "peerDependencies": {
    "react-router-dom": "^6.0.0"
  }
}

同时可以加上peerDependenciesMeta让安装更友好:

{
  "peerDependenciesMeta": {
    "react-router-dom": {
      "optional": false
    }
  }
}
  1. 强制主项目依赖统一(可选)
    如果是用npm,可以在主项目的package.json里加overrides强制所有依赖的react-router-dom版本统一:
{
  "overrides": {
    "react-router-dom": "^6.14.0"
  }
}

yarn用户可以用resolutions,pnpm用户用pnpm.overrides。

  1. 清除缓存并重启服务
    删掉主项目和共享包的node_modules,重新安装依赖,然后重启开发服务器,确保修改生效。

验证方式

在主项目里打印两个模块的引用是否一致,确认问题解决:

import { useSearchParams as appUseSearchParams } from 'react-router-dom';
import { useSearchParams as pkgUseSearchParams } from '你的共享包名称';

console.log(appUseSearchParams === pkgUseSearchParams); // 输出true说明依赖统一了

内容的提问来源于stack exchange,提问作者souyahia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 11:35:58