在浏览器的后退按钮上反应路由器历史记录

Posted

技术标签:

【中文标题】在浏览器的后退按钮上反应路由器历史记录【英文标题】:React Router history on browser's back button 【发布时间】:2021-10-27 20:45:33 【问题描述】:

我有一个带有加载显示组件的链接的主组件,并且在显示组件中我有相同的链接再次加载显示组件。

如果用户在显示组件中多次单击该链接,则会有很多路由器历史记录。我希望当用户单击浏览器后退按钮时,它应该加载主组件,而不是所有以前的历史记录。

当我在带有 onClick 事件的 Display 组件中使用 history.replace("/"); 时,它只会返回一次。但再次返回会导致 Display 组件的先前历史记录

Routes.js

import Home from "./Components/Home"
import Display from "./Components/Display"

<Router>
    <Switch>
        <Route exact path="/">
            <Home />
        </Route>
        <Route path="/:city">
            <Display />
        </Route>        
    </Switch>
</Router>

Home.js

<Link to =`/$city` onClick=()=>dispatch(fetchWeather(city)); >Search</Link>

Display.js

<Link to =`/$city` onClick=()=>dispatch(fetchWeather(city)); >Search</Link>

【问题讨论】:

您是否尝试告诉链接组件替换? &lt;Link replace to= /&gt;。或者,您可以定义一个函数来为您处理此问题,而不是让链接的默认重定向行为通过,而是使用反应路由器 history 替换 Display 中的状态。这样,每一次城市点击都会用新的目标更新当前的历史状态......并且按下后退按钮将返回主页。如果这对你有用,我很乐意把它写成答案:) 同意,Display 中的 Link 应该是重定向到自己 (REPLACE),而不是导航 (PUSH)。这只会替换当前条目,而不是逐页推送。完成后退导航 (POP) 后,用户返回主页。 @JohnRuddell 你能写出答案吗,我很想看看应该如何实现:-) @Shyam 这实际上是只是replace 属性添加到Link。 reactrouter.com/web/api/Link/replace-bool @DrewReese 哦,好吧,以前没遇到过这个用例。很高兴知道。 【参考方案1】:

根据您使用的 react 路由器的版本,您只需在 Link 文件中的 Link 组件上添加 replace 属性,即可不在历史堆栈中推送新状态,而是更新当前状态。

<Link replace to =`/$city` onClick=()=>dispatch(fetchWeather(city)); >Search</Link>

如果您使用的是不支持此功能的旧版本,您可以让点击处理程序为您执行此操作

// Display.js file

function Display(props) 
  // whatever code you have for this file
  const handleViewCity = useCallback((event, city) => 
    // prevent the default redirect from happening, were going to manage that ourselves
    event.preventDefault()

    dispatch(fetchWeather(city))
    props.history.replace(`/$city`)

  , [props.history, fetchWeather])

  return (
    // your jsx
    // keep the href so you get browser builtin functionality like right click "open in new window"
    <a href=`/$city` onClick=(e) => handleViewCity(e, city)>Search</Link>
  )


export default withRouter(Display)

为了形象化这里会发生什么,可以将历史想象成一堆地点。 (这是一个简单的例子——伪代码)

history.push('/city1') // ['/home', '/city1']
history.push('/city2') // ['/home', '/city1', '/city2']
history.push('/city3') // ['/home', '/city1', '/city2', '/city3']

按下浏览器后退按钮会触发一个窗口popstate 事件。流行音乐是那里的关键词。当按下浏览器后退按钮时,您的历史记录看起来像这样['/home', '/city1', '/city2'],这就是为什么您会看到历史记录中的不同城市。

相反,您想使用替换来达到预期的效果

history.replace('/city1') // ['/home', '/city1']
history.replace('/city2') // ['/home', '/city2']
history.replace('/city3') // ['/home', '/city3']

【讨论】:

以上是关于在浏览器的后退按钮上反应路由器历史记录的主要内容,如果未能解决你的问题,请参考以下文章

后退按钮后反应路由器“历史”和“位置”不匹配

怎样查看浏览历史记录

使用 Jquery 过滤功能锚定标签和浏览器历史记录

添加到浏览器历史记录而无需重新加载页面

JavaScript 之 history对象

如何保留 html 内容历史记录以使后退按钮起作用?