React组件库使用react-router-dom Link组件报错求助
我在开发React TypeScript应用时,将组件拆分到独立的ui-kit组件库中。在组件库的button.tsx里使用react-router-dom的<Link>组件时,触发了以下错误:
Cannot destructure property 'basename' of '(0 , react__WEBPACK_IMPORTED_MODULE_0__.useContext)(...)' as it is null.
场景细节
button.tsx位于组件库ui-kit目录- 主应用的
Navbar.tsx在frontend文件夹内 - 已通过
npm link ui-kit关联组件库与主应用,并用npm link ../frontend/node_modules/react共享React实例避免重复依赖 - 编译组件库并同步后触发错误
解决方案
1. 修正组件库的依赖配置
你的组件库package.json将react-router-dom放在了devDependencies中,这会导致组件库编译时可能打包该依赖,或主应用使用的版本与组件库依赖版本不匹配,引发上下文冲突。需要将react-router-dom添加到peerDependencies,明确要求主应用提供该依赖:
修改package.json:
{ // ... 其他配置 "peerDependencies": { "react": "^18.2.0", "react-router-dom": "^6.20.1" }, "devDependencies": { // ... 保留react-router-dom作为开发依赖,用于本地测试 "react-router-dom": "^6.20.1" } }
这样组件库不会打包react-router-dom,而是使用主应用提供的版本,确保上下文一致。
2. 改造Button组件,兼容非Router场景
硬编码使用<Link>会导致组件必须在BrowserRouter(或其他Router组件)上下文内才能运行,否则会触发Context null错误。可以修改组件,根据props决定渲染Link还是普通按钮:
修改button.tsx:
import React from 'react'; import { Link } from 'react-router-dom'; interface ButtonProps { className: string; link?: string; children: React.ReactNode; onClick?: () => void; } const Button: React.FC<ButtonProps> = ({ className, link, children, onClick }) => { if (link) { return ( <Link className={className} to={link}> {children} </Link> ); } // 无link时渲染普通按钮 return ( <button className={className} onClick={onClick}> {children} </button> ); }; export default Button;
这样组件无论是否在Router上下文内,都能正常工作。
3. 确保主应用组件在Router范围内使用
如果Button在主应用的Navbar中使用,需确保Navbar被包裹在BrowserRouter内部:
主应用入口示例:
import { BrowserRouter } from 'react-router-dom'; import Navbar from './Navbar'; function App() { return ( <BrowserRouter> <Navbar /> {/* 其他路由组件 */} </BrowserRouter> ); }
4. 同步react-router-dom依赖实例
和共享React实例一样,确保组件库使用主应用的react-router-dom实例,避免重复加载导致上下文不匹配:
在组件库目录执行:
npm link ../frontend/node_modules/react-router-dom
完成上述步骤后,重新编译组件库并重启主应用,错误即可解决。
内容的提问来源于stack exchange,提问作者Matt Boston

