BrowserRouter和使用history.push()的Router有什么区别?

66
我正在尝试理解react-router-dom(v5)包中的BrowserRouterRouter之间的区别,以及它对下面的示例有何影响。
文档说:

BrowserRouter 使用HTML5历史API(pushState、replaceState和popstate事件)来使你的UI与URL同步。

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

Router 所有路由器组件的常见低级接口。通常应用程序将使用其中一个高级路由器:BrowserRouter、HashRouter、MemoryRouter、NativeRouter、StaticRouter。

来源: https://reacttraining.com/react-router/web/api/Router 据我所知,我应该在我的HTML5浏览器应用程序中使用BrowserRouter,到目前为止我一直这样做。 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,但不会渲染路由 behind the route。
如果我导入Router而不是BrowserRouter,它可以工作:
// Does not work:
import { BrowserRouter as Router } from 'react-router-dom';

// Does work:
import { Router } from 'react-router-dom';
3个回答

44

BrowserRouter 忽略 history 属性,因为它会自动处理历史记录。如果您需要在 React 组件之外访问历史记录,则使用 Router 就可以了。


2
BrowserRouter 相对于 Router 自动处理了什么? - user3711421
4
这个离线文章解释了不同之处。"使用React Router v5后,路由不再是集中管理,而是成为应用程序布局和UI的一部分。""如果您使用能处理动态URL的动态服务器,则需要使用BrowserRouter组件,但如果您只使用可提供静态文件的服务器,则应使用HashRouter组件。" - DFBerry

6
您可以使用useHistory钩子访问历史记录 let history = useHistory();,对于BrowserRouter执行history.push()
查看HTML5 History API文档,似乎历史API可以自动保留用户状态。例如,您最初在页面1上,并且页面1的外观为A。您执行了一些操作以更改页面1的外观为B。如果您现在移动到页面2,当您单击浏览器的后退按钮时,您会被直接返回到页面1。历史记录API会保留您的状态,因此它知道向您呈现外观B,这就是使用BrowserRouter的优点。虽然我不确定100%,但我认为Browser可能没有这个功能,在这种情况下,当您被导向回页面1时,它将呈现外观A。

0

我遇到了同样的问题。

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

此外,我的源代码已经使用了BrowserRouter,我不想将其替换为Router组件。

通过我的调查,我发现这两个history对象是不同的。(我用if==进行了比较。)我猜这就是原因。

为了解决这个问题,我将通过useHistory()获取的history对象的引用保存到全局实用程序代码中,并在redux-saga代码中使用它。然后,它就可以正常工作了。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接