在库中使用 React 路由器 - 无法使用 useHistory()

Posted

技术标签:

【中文标题】在库中使用 React 路由器 - 无法使用 useHistory()【英文标题】:React router use in library - not possible to use useHistory() 【发布时间】:2020-07-29 17:47:24 【问题描述】:

我有一个包含多个应用程序和库的 monorepo,它运行得非常好(基于纱线)。我最近做了一些重构,并确定了一个我想在我的“公共”库中“外包”的公共组件。这包含一个使用ReactRouter.Route的组件:

import React from 'react';
import  Route, useHistory  from 'react-router-dom';

export const AuthenticatedRoute = (props: Props): JSX.Element => 
   const history = useHistory(); // Crashes here

   ... do auth stuff ...

   useEffect(() => 
     if (!authenticated) 
        history.push(...);
     
   , []);

   return (
     <Route ...props>
       props.children
     </Route>
   );


当包含我的 react 应用程序时,这个组件就像一个魅力。但是,当提取到commons 库中时,它在运行时会失败并出现以下错误:

Uncaught TypeError: Cannot read property 'history' of undefined
    at useHistory (index.js:5914)
    at AuthenticatedRoute (index.js:9848)
    at renderWithHooks (react-dom.development.js:16260)
    at mountIndeterminateComponent (react-dom.development.js:18794)
    at beginWork$1 (react-dom.development.js:20162)
    at htmlUnknownElement.callCallback (react-dom.development.js:336)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:385)
    at invokeGuardedCallback (react-dom.development.js:440)
    at beginWork$$1 (react-dom.development.js:25780)
    at performUnitOfWork (react-dom.development.js:24695)

我猜这与库/应用程序如何引用 react-router-dom 库有关。

commons/package.json:


  "name": "commons",
  "version": "1.0.0",
  "main": "dist/index.js",
  "private": true,
  "dependencies": 
  ,
  "peerDependencies": 
    "react-router-dom": "^5.1.2"
  

app/package.json:


  "name": "app",
  "version": "1.0.0",
  "private": true,
  "dependencies": 
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-router-dom": "^5.1.2",
    "commons": "1.0.0"
  


app/app.ts:

import React from 'react';
import  BrowserRouter as Router  from 'react-router-dom';

export const App = (): JSX.Element => 
  return (
    <Router>
      <AuthenticatedRoute />
    </Router>
  );
;

注意:如果我评论 useHistory,它会在 &lt;Route&gt; 上失败,说它需要是 &lt;Router&gt; 的子代。

我尝试过的事情:

使用peerDependencies,以便库和应用使用相同的反应路由器实例 clean & yarn install 多次 react-routerreact-router-dom 依赖项的任意组合

【问题讨论】:

您是否 100% 确定它被包裹在路由器中?像useParams 这样的其他钩子有用吗? 是的。当只将AuthenticatedRoute(并更新c的导入)更改为app模块时,它可以工作。其他钩子,例如 useEffect 工作正常,控制台中也没有警告。 @MikeKasperlik 你能找到解决这个问题的方法吗?我有同样的问题 我没有找到解决方案 - 我们最终将文件直接包含在应用程序中。 我在 monorepo 中遇到了这个问题,这篇文章为我提供了解决方案:***.com/questions/56750633/… 基本上将 react-router-dom 移动到库中的 peerDepencencies 并将其从汇总脚本中的构建中排除. 【参考方案1】:

withRouter 是一个 HOC。你必须相应地使用它。来自documentation:

import  withRouter  from "react-router";

class ShowTheLocation extends React.Component 
  static propTypes = 
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  ;

  ...


const ShowTheLocationWithRouter = withRouter(ShowTheLocation);

BrowserRouter 的初始化似乎没问题。

【讨论】:

不,那是旧的,并不能解决 op 遇到的问题 取决于版本。我想说的是useHistory 可能不存在,因此他无法从undefined 中读取某些内容。他可能会被一个过时的例子抓住。 > “6.0 中没有 useHistory 挂钩。切换回 5.1.2 或调整您的代码以不使用该挂钩”来自 github.com/ReactTraining/react-router/issues/7189。虽然乍一看范围似乎还可以。 是的,这是预挂钩。我也使用 5.1.2 - 查看最初的帖子依赖项。由于此组件在 1:1 复制到 app 时有效,因此它不能在代码本身中,但必须具有依赖关系。 您是否尝试过明确地创建历史记录并使用来自react-routerRouter

以上是关于在库中使用 React 路由器 - 无法使用 useHistory()的主要内容,如果未能解决你的问题,请参考以下文章

AVFoundation PhotoApp - 在图像保存在库中之前无法使闪存正常工作

arcgis在库中怎么搜索选中

使用 CMake 在库中查找符号

在库中使用 fstream 时,可执行文件中出现链接器错误

在库中使用 Swift 在 CoreData 中获取 nil managedObjectContext

在库中搜索 mangle