Ari*_*ris 49 reactjs react-router react-router-redux react-router-v4 react-router-dom
我必须根据浏览历史实现一些业务逻辑.
我想做的是这样的:
reactRouter.onUrlChange(url => {
this.history.push(url);
});
Run Code Online (Sandbox Code Playgroud)
当URL更新时,有没有办法从react-router接收回调?
ono*_*ndi 75
React Router 5.1+ 的更新。
import React from 'react';
import { useLocation, Switch } from 'react-router-dom';
const App = () => {
const location = useLocation();
React.useEffect(() => {
console.log('Location changed');
}, [location]);
return (
<Switch>
{/* Routes go here */}
</Switch>
);
};
Run Code Online (Sandbox Code Playgroud)
Shu*_*tri 74
您可以history.listen()在尝试检测路线更改时使用功能.考虑到您正在使用react-router v4,请使用withRouterHOC 包装您的组件以访问history道具.
history.listen()返回一个unlisten函数.你可以用它来unregister听.
您可以配置您的路线
index.js
ReactDOM.render(
<BrowserRouter>
<AppContainer>
<Route exact path="/" Component={...} />
<Route exact path="/Home" Component={...} />
</AppContainer>
</BrowserRouter>,
document.getElementById('root')
);
Run Code Online (Sandbox Code Playgroud)
然后在AppContainer.js中
class App extends Component {
componentWillMount() {
this.unlisten = this.props.history.listen((location, action) => {
console.log("on route change");
});
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<div>{this.props.children}</div>
);
}
}
export default withRouter(App);
Run Code Online (Sandbox Code Playgroud)
从历史文档:
您可以使用以下方法侦听当前位置的更改
history.listen:Run Code Online (Sandbox Code Playgroud)history.listen((location, action) => { console.log(`The current URL is ${location.pathname}${location.search}${location.hash}`) console.log(`The last navigation action was ${action}`) })location对象实现了window.location接口的子集,包括:
Run Code Online (Sandbox Code Playgroud)**location.pathname** - The path of the URL **location.search** - The URL query string **location.hash** - The URL hash fragment地点也可能具有以下属性:
location.state - 此位置的一些额外状态,不在URL中(支持
createBrowserHistory和createMemoryHistory)
location.key- 表示此位置的唯一字符串(支持createBrowserHistory和createMemoryHistory)该操作
PUSH, REPLACE, or POP取决于用户如何访问当前URL.
当您使用反应路由器V3,你可以利用history.listen()从history包如上所述,或者您也可以使用browserHistory.listen()
您可以配置和使用您的路线
import {browserHistory} from 'react-router';
class App extends React.Component {
componentDidMount() {
this.unlisten = browserHistory.listen( location => {
console.log('route changes');
});
}
componentWillUnmount() {
this.unlisten();
}
render() {
return (
<Route path="/" onChange={yourHandler} component={AppContainer}>
<IndexRoute component={StaticContainer} />
<Route path="/a" component={ContainerA} />
<Route path="/b" component={ContainerB} />
</Route>
)
}
}
Run Code Online (Sandbox Code Playgroud)
dav*_*wil 35
react-router v6在即将发布的v6 中,这可以通过组合useLocation和useEffect钩子来完成
import { useLocation } from 'react-router-dom';
const MyComponent = () => {
const location = useLocation()
React.useEffect(() => {
// runs on location, i.e. route, change
console.log('handle route change here', location)
}, [location])
...
}
Run Code Online (Sandbox Code Playgroud)
为了方便重用,您可以在自定义useLocationChange钩子中执行此操作
// runs action(location) on location, i.e. route, change
const useLocationChange = (action) => {
const location = useLocation()
React.useEffect(() => { action(location) }, [location])
}
const MyComponent1 = () => {
useLocationChange((location) => {
console.log('handle route change here', location)
})
...
}
const MyComponent2 = () => {
useLocationChange((location) => {
console.log('and also here', location)
})
...
}
Run Code Online (Sandbox Code Playgroud)
如果你还需要在变化时看到之前的路线,你可以结合一个usePrevious钩子
const usePrevious = (value) => {
const ref = React.useRef()
React.useEffect(() => { ref.current = value })
return ref.current
}
const useLocationChange = (action) => {
const location = useLocation()
const prevLocation = usePrevious(location)
React.useEffect(() => {
action(location, prevLocation)
}, [location])
}
const MyComponent1 = () => {
useLocationChange((location, prevLocation) => {
console.log('changed from', prevLocation, 'to', location)
})
...
}
Run Code Online (Sandbox Code Playgroud)
重要的是要注意,上述所有内容都会在安装的第一个客户端路由以及后续更改上触发。如果这是一个问题,请使用后一个示例并prevLocation在执行任何操作之前检查 a 是否存在。
Fab*_*ltz 11
如果你想history全局收听对象,你必须自己创建并传递给它Router.然后你可以用它的listen()方法听它:
// Use Router from react-router, not BrowserRouter.
import { Router } from 'react-router';
// Create history object.
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
// Listen to history changes.
// You can unlisten by calling the constant (`unlisten()`).
const unlisten = history.listen((location, action) => {
console.log(action, location.pathname, location.state);
});
// Pass history to Router.
<Router history={history}>
...
</Router>
Run Code Online (Sandbox Code Playgroud)
如果您将历史对象创建为模块,则更好,因此您可以轻松地将其导入到您可能需要的任何位置(例如, import history from './history';
Joh*_*pis 11
这是一个老问题,我不太了解监听路由更改以推动路由更改的业务需求;似乎迂回。
但是,如果您最终来到这里是因为您想要的只是更新'page_path'Google 分析/全局站点标签/类似内容的 react-router 路由更改,这里有一个您现在可以使用的钩子。我根据接受的答案写了它:
useTracking.jsimport { useEffect } from 'react'
import { useHistory } from 'react-router-dom'
export const useTracking = (trackingId) => {
const { listen } = useHistory()
useEffect(() => {
const unlisten = listen((location) => {
// if you pasted the google snippet on your index.html
// you've declared this function in the global
if (!window.gtag) return
window.gtag('config', trackingId, { page_path: location.pathname })
})
// remember, hooks that add listeners
// should have cleanup to remove them
return unlisten
}, [trackingId, listen])
}
Run Code Online (Sandbox Code Playgroud)
你应该在你的应用程序中使用一次这个钩子,靠近顶部但仍在路由器内。我有一个App.js看起来像这样的:
App.jsimport * as React from 'react'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
import Home from './Home/Home'
import About from './About/About'
// this is the file above
import { useTracking } from './useTracking'
export const App = () => {
useTracking('UA-USE-YOURS-HERE')
return (
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
)
}
// I find it handy to have a named export of the App
// and then the default export which wraps it with
// all the providers I need.
// Mostly for testing purposes, but in this case,
// it allows us to use the hook above,
// since you may only use it when inside a Router
export default () => (
<BrowserRouter>
<App />
</BrowserRouter>
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
51700 次 |
| 最近记录: |