react-router:如何在不导致导航/重新加载的情况下更新 url?

Posted

技术标签:

【中文标题】react-router:如何在不导致导航/重新加载的情况下更新 url?【英文标题】:react-router: How do I update the url without causing a navigation/reload? 【发布时间】:2019-11-27 19:42:26 【问题描述】:

使用 react 路由器,我已经完成了更新 url:

this.props.history.push(
            pathname: `/product/$this.props.product.id`,
        );

但是,这会导致重新渲染/导航更改。有没有办法在不这样做的情况下更新网址?

我的用例是我有一个产品列表,当我点击一个产品列表时,我会显示一个模态并希望将 url 更新为 example.com/product/1 之类的内容,以便链接可共享。

【问题讨论】:

这都是 react-router 内置的;它被称为dynamic routing 【参考方案1】:

replace 将覆盖 URL

this.props.history.replace( pathname: `/product/$this.props.product.id`)

【讨论】:

这肯定仍然会导致路由器采取行动,然后出现一个空白屏幕(我猜它找不到路由) 真的,替换应该只覆盖 URL 我发现这行得通:window.history.replaceState(null, null, /product/$this.props.product.id); react-router replace 的行为应该类似于 replaceState。我可以确认替换不会触发渲染,查看这个小演示jsbin.com/jinazirowa/edit?html,js,output 只要路由器路径封装了新路径,这应该可以在不刷新/重新渲染的情况下工作。【参考方案2】:

无法使用 React Router 找到解决方案,但能够使用浏览器的历史界面通过调用:

window.history.replaceState(null, "New Page Title", "/pathname/goes/here")

您可以了解更多关于.replaceStatehere的信息。

React Router 的 history.replace 并不总是有效

React Router 的 history.replace 方法可能会也可能不会触发重新渲染,具体取决于您应用的路由设置(例如,您有一个包罗万象的 /* 路由)。它不会根据定义阻止渲染。

【讨论】:

请注意,如果稍后再次修改,此更改可能会绕过 React Router 对当前路径的了解。例如。如果你使用这种方法追加1个子路径,然后使用RR向上导航1级,它会在视觉上跳转2,因为RR仍然认为该位置没有附加的子路径。 我遇到了与 OP 完全相同的问题,并使用他的方法解决了它。非常感谢! @MagnusBull 浏览器历史记录我只是使用window.history.pushState(stringify(currentParams), "");,这似乎可以解决问题,尽管我没有遇到你谈到的子路径问题 @usr28765526 我的意思是,如果你使用 React Router 来处理导航,那么使用浏览器 API replaceState 可以被认为是“黑客”并且 RR 不会知道路径已更改。如果你在 URL 被修改后尝试使用 React Router 的 location,它将在它知道的 URL 的版本上操作:更改前的那个。这可能是不可预测和令人困惑的。【参考方案3】:

当你在一个 react 组件中时,propshistory,你可以使用它。

对于那些即使不在 React 组件中也正在寻找一种导航方式的人,即您无法获得 props.history,这是一种方法:

在渲染路由器的组件中:

// outside the component
export const browserRouterRef = React.createRef();

// on render
<BrowserRouter ref=browserRouterRef>

然后您可以在任何地方导入browserRouterRef 并使用browserRouterRef.current.history 更改路由,即使您不在react 组件中。

【讨论】:

【参考方案4】:

我正在使用一种很好的方式来欺骗用户,即 URL 不会改变。

为此,您只需要像这样设置您的路线。

const Home = '/';
const About = '/ ';
const Contact = '/  ';

注意空格。所有字符都将计入引号内,因此它应该可以工作。

Routes.tsx

<Route exact path=Home component=Home />
<Route exact path=About component=About />
<Route exact path=Contact component=Contact />

在您的About.tsxContact.tsx 中:

  useEffect(() => 
    window.history.replaceState(null, '', Home);
  , []);

用户导航到AboutContact 页面后,将调用挂钩并运行回调函数内的代码。它会在组件渲染后移除空格。

这应该是伪装隐藏 URL 的干净技巧?

【讨论】:

以上是关于react-router:如何在不导致导航/重新加载的情况下更新 url?的主要内容,如果未能解决你的问题,请参考以下文章

React-Router 组件在转换时卸载

如何在不刷新页面的情况下在 ReactJS 中重新加载?

带有 Reactstrap 的 React-Router 导致警告

React-Router & useContext,无限重定向或重新渲染

导航离开然后返回页面时如何记住 React-Router URL 参数?

使用react-router导航到具体的孩子