【问题标题】:BrowserRouter vs Router with history.push()BrowserRouter 与带有 history.push() 的路由器
【发布时间】:2019-11-04 13:37:01
【问题描述】:

我试图了解react-router-dom (v5) 包的BrowserRouterRouter 之间的区别以及它对我下面的示例有何不同。

文档说:

浏览器路由器 使用 HTML5 历史 API(pushState, replaceState 和 popstate 事件)以使您的 UI 与 网址。

来源:https://reacttraining.com/react-router/web/api/BrowserRouter

路由器 所有路由器组件的通用低级接口。通常 应用程序将改为使用高级路由器之一:BrowserRouter、HashRouter、MemoryRouter、NativeRouter、StaticRouter

来源:https://reacttraining.com/react-router/web/api/Router

据我了解,我应该将 BrowserRouter 用于我的 HTML5 浏览器应用程序,到目前为止我一直在这样做。

history.push(...) 示例:

我正在尝试在 thunk 中执行 history.push('/myNewRoute')

import history as './history';

...

export function someAsyncAction(input) {
  return dispatch => {
    fetch(`${API_URL}/someUrl`, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ input }),
    }).then(() => {
      history.push('/myNewRoute');
    }).catch((err) => {
      dispatch(setError(err));
    })
  };
};

history 被定义为这个模块:

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

history 也被传递到我的路由器:

import { BrowserRouter as Router } from 'react-router-dom';
import history as './history';

...

const App = () => (
  <Router history={history}>
     ...
  </Router>
);

问题:history.push() 将更新浏览器栏中的 URL,但不会渲染路由后面的组件。

如果我导入 Router 而不是 BrowserRouter,它会起作用:

// Does not work:
import { BrowserRouter as Router } from 'react-router-dom';

// Does work:
import { Router } from 'react-router-dom';

【问题讨论】:

    标签: reactjs react-router react-router-dom html5-history


    【解决方案1】:

    BrowserRouter 会忽略 history 属性,因为它会自动为您处理历史记录。如果您需要访问 react 组件之外的历史记录,那么使用 Router 应该没问题。

    【讨论】:

    • Router相比,BrowserRouter如何自动处理它?
    • offsite post 解释了差异。 “使用 React router v5,路由不再是集中式的,而是成为应用程序布局和 UI 其余部分的一部分。” “如果您使用的是可以处理动态 URL 的动态服务器,那么您需要使用 BrowserRouter 组件,但如果您使用的服务器仅提供静态文件,那么在这种情况下将使用 HashRouter 组件。”
    【解决方案2】:

    您可以通过 useHistory 钩子 let history = useHistory(); 访问历史记录,为 BrowserRouter 执行 history.push()

    查看HTML5 History API documentation,似乎历史API 会自动为用户保留状态。假设您最初位于第 1 页,并且第 1 页具有页面外观 A。您执行了一些操作,将第 1 页的外观更改为 B。如果您现在移动到第 2 页,当您单击浏览器上的后退按钮时,您将直接返回第 1 页。History API 保存您的状态,因此它知道将 Outlook B 呈现给您,这就是使用BrowserRouter 的优势。虽然我不能 100% 确定,但我想 Browser 没有此功能,在这种情况下,当您被引导回到第 1 页时,它会呈现 Outlook A。 这不是真的。我不确定其中的区别。

    【讨论】:

      【解决方案3】:

      我也有同样的问题。

      BrowserRouteruseHistory() 钩子已用于我的组件。而createBrowserHistory() 已被用于 redux-saga。但是,页面并没有像你的情况那样被 redux-saga 移动。

      另外,我的源码是用 BrowserRouter 开发的,我不想替换成 Router 组件。

      作为我可怜的调查,我发现两个历史对象是不同的。 (我将它们与if== 进行了比较。)我想这就是原因。

      为了解决这个问题,我将 useHistory() 获得的历史对象的引用保存到一些全局实用程序代码中,并在 redux-saga 代码中使用它。然后,它运行良好。

      我不认为这是最好的方法,但我还找不到最好的官方方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-13
        • 2020-10-20
        • 2018-02-23
        • 2023-03-06
        • 2017-02-23
        • 2020-09-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多