【问题标题】:How can I check if react-router is in context?如何检查 react-router 是否在上下文中?
【发布时间】:2020-01-30 18:31:31
【问题描述】:

我正在将一个 AngularJS 应用程序一点一点地迁移到 React,我想要一个自定义的 RouterLink React 组件来检查 react-router 是否在上下文中,以便它可以使用 history,如果不是,回退到使用好旧的window.location。但我在react-router 的文档中看不到任何检查方法。

我尝试使用 withRouter,但它在不在上下文中时抛出,并且 ErrorBoundary 似乎没有捕捉到错误。

有人知道我该怎么做吗?

【问题讨论】:

    标签: angularjs reactjs react-router react-router-dom


    【解决方案1】:

    react-router 包中暴露了路由器上下文,即__RouterContext,通过它可以检查路由器是否可用:

    import React, { useContext } from 'react';
    import { __RouterContext } from 'react-router';
    
    const MyComponent = (props) => {
      const router = useContext(__RouterContext);
    
      if (router) {
        // Router context is avaible
      } else {
        // Use window.location as router context is not availble in this component
      }
    
      return <SomeOtherComponent />
    }
    

    【讨论】:

    • 我不敢相信我没有看到那个出口。尽管拥有一个不会在未来更新中意外中断的官方 API 会更好,但我没有看到任何其他选项,因此我将其标记为正确答案。我想我会暂时锁定版本。谢谢!
    • 不客气,我挖了一次,知道导出了一些上下文,所以想出了解决方案?
    • @yadielar 您可能没有看到它,因为它不是公共 API 的一部分。我真的不会依赖这个。看起来很hacky。使用 __ 前缀公开变量的库通常是供内部使用的。
    • 我认为它是从 v4 开始的,目前 react-router 是 v5
    【解决方案2】:

    只需将钩子包裹在try/catch:

    const {useState, useEffect, Fragment} = React;
    const {useLocation, MemoryRouter} = ReactRouter;
    
    const Cmp = () => {
      let loc;
      try {
        loc = useLocation();
      } catch (err) {
        return (
          <div>No Router Available</div>
        );
      }
      return (
        <div>Hello I can see {loc.pathname}</div>
      );
    };
    
    const App1 = () => {
      return (
        <Cmp/>
      );
    };
    
    const App2 = () => {
      return (
        <MemoryRouter>
          <Cmp/>
        </MemoryRouter>
      );
    };
    
    ReactDOM.render(<App1 />, document.getElementById("app1"));
    ReactDOM.render(<App2 />, document.getElementById("app2"));
    <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/react-router@5.1.2/umd/react-router.js"></script>
    
    <div id="app1"></div>
    <div id="app2"></div>

    【讨论】:

    • 不建议有条件地使用钩子。
    • @MuhammadAli 它不是有条件地运行。它总是着火。钩子的值是有条件使用的,这绝对没问题。
    • 是的,但是你必须禁用 eslint 规则才能在没有任何警告的情况下使用它,所以我认为规则的存在是有原因的。我也试过了,但由于那个警告,我不得不放弃这个解决方案。
    猜你喜欢
    • 2020-10-17
    • 2017-02-24
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 2017-02-06
    • 2021-11-08
    • 1970-01-01
    相关资源
    最近更新 更多