【问题标题】:React router use in library - not possible to use useHistory()在库中使用 React 路由器 - 无法使用 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 中遇到了这个问题,这篇文章为我提供了解决方案:stackoverflow.com/questions/56750633/… 基本上将 react-router-dom 移动到库中的 peerDepencencies 并将其从汇总脚本中的构建中排除.

标签: javascript reactjs npm react-router yarnpkg


【解决方案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
猜你喜欢
  • 1970-01-01
  • 2021-09-11
  • 2021-02-21
  • 2020-04-20
  • 2017-04-09
  • 2015-02-07
  • 2014-12-22
  • 2018-05-01
  • 2016-03-17
相关资源
最近更新 更多