React router 4 history.listen 永远不会触发
Posted
技术标签:
【中文标题】React router 4 history.listen 永远不会触发【英文标题】:React router 4 history.listen never fires 【发布时间】:2017-10-21 02:25:02 【问题描述】:切换到路由器 v4 和历史 v4.5.1,现在历史监听器不工作
import createBrowserHistory from 'history/createBrowserHistory'
const history = createBrowserHistory()
history.listen((location, action) =>
console.log(action, location.pathname, location.state) // <=== Never happens
)
render(
<Provider store=store>
<Router history=history>
...
</Router>
</Provider>,
document.getElementById('root')
)
任何想法为什么它被忽略?
【问题讨论】:
您在这里使用的路由器是什么?是浏览器路由器还是路由器?我问这个是因为有些人用这样的命名导入导入 BrowserRouter。import BrowserRouter as Router from 'react-router-dom'
^ 这就是我正在做的事情
【参考方案1】:
由于您使用的是 BrowserRouter(使用问题的 cmets 中提到的导入别名路由器),它并不关心您传入的历史记录。取而代之的是 internally creates and assigns new browser history to the Router。所以你在Router中监听和使用的历史实例是不一样的。这就是你的监听器不起作用的原因。
导入原始路由器。
import Router from 'react-router-dom';
它将按您的预期工作。
【讨论】:
“原始路由器”是v3。我使用的是 v4,没有'react-router'
,只有'react-router-dom'
和BrowserRouter
和HashRouter
但是,您仍然可以从“react-router-dom”导入路由器。试试import Router from 'react-router-dom';
它应该可以工作。
仍然没有区别
猜不出是什么原因。但它对我有用codesandbox.io/s/9WrAYvjP
我可以确认这也适用于 React Router v4。【参考方案2】:
问题是您正在创建自己的历史对象并将其传递给路由器。但是,React Router v4 已经通过 this.props 为您提供了这个对象。 (导入Router与此无关)
componentDidMount()
this.props.history.listen((location, action) => console.log('History changed!', location, action));
您可能需要对您的应用进行更多分层,如下所示,并将此 componentDidMount 方法放在您的 MyApp.jsx 中,而不是直接放在最顶层.
<Provider store=store>
<BrowserRouter>
<MyApp/>
</BrowserRouter>
</Provider>
(如果你在做 React Native,或者使用 NativeRouter 而不是 BrowserRouter)
【讨论】:
坚持使用 BrowserRouter 解决方案,要访问历史记录,可以在路由器上创建一个 ref 并继续通过 componentDidMount 或 useEffect 在 BrowseRouter 上方的级别上进行侦听。这样就不需要在 BrowserRouter 下添加额外的组件层了。【参考方案3】:像魔术一样工作:?♂️?♂️?♂️
const history = useHistory();
useEffect(() =>
if (history) // for jest sake ))
history.listen(() =>
store.reset();
);
, []);
【讨论】:
以上是关于React router 4 history.listen 永远不会触发的主要内容,如果未能解决你的问题,请参考以下文章
[react-router] React-Router 3和React-Router 4有什么变化?添加了什么好的特性?