react-router-dom: getting props.location from within <BrowserRouter> component
You can also do it using withRouter
which has a similar result to putting the code in a render
parameter and avoids the need for a "fake" <Route/>
.
Essentially you put the JSX that needs to know the location in a component of its own, which is wrapped by withRouter
. This supplies the location to the component:
import { withRouter } from 'react-router-dom';
const Content = withRouter(props =>
<div className={(props.location.pathname === "/account") ? "backg...
...
</div>
);
Then you use that in your main router section:
class App extends Component{
render() {
return (
<BrowserRouter>
<Content/>
...
Since react-router v5.1.0
you can use useLocation
.
https://reactrouter.com/web/api/Hooks/uselocation
class App extends Component{
render(){
const location = useLocation();
return (
<div className={(location.pathname === "/account") ? "bgnd-black" : "bgnd-white"} >
//...
</div>
);
}
}
// ...
<BrowserRouter>
<App />
</BrowserRouter>
You achieve what u have asked for by doing this
import AccessRoute from './AccessRoute'
class App extends Component{
render(){
return (
<BrowserRouter>
<AccessRoute>
<div className={(this.props.location.pathnme === "/account") ? "bgnd-black" : "bgnd-white"} >
<Switch>
<Route path="/login" component={LoginPage}/>
<Route path="/success" component={LoginSuccess}/>
<Route path="/account" component={MyAccount}/>
...
<Route component={Error404}/>
</Switch>
</div>
</AccessRoute>
</BrowserRouter>
);
}
}
AccessRoute.jsx
import React from 'react'
import {withRouter} from 'react-router';
class AccessRoute extends React.Component{
constructor(props){
super(props);
}
//If you want to find the location on mount use this
componentDidMount(){
console.log("the path name is ",this.props.location.pathname);
}
//If you want to find the location on change use this
componentDidUpdate(prevprops){
if(this.props.location.pathname!=prevprops.location.pathname){
console.log("the new path name is ",this.props.location.pathname);
}
}
render(){
return(
this.props.children
);
}
}
export default withRouter(AccessRoute)
After digging through their GitHub issues, I found the solution. I must render a <Route />
within <BrowserRouter />
and pass the rest of my app into its render()
function with history
as a parameter. Within the render function, I can find the app's location in history.location.pathname
.
class App extends Component{
render(){
return (
<BrowserRouter>
// We must add a parent <Route> and render its children while passing 'history' as parameter
<Route path={Paths.reserve} render={(history) =>
// Within render(), we can find it in history.location.pathname
<div className={(history.location.pathname === "/account") ? "background-black" : "background-white"} >
<Switch>
<Route path="/login" component={LoginPage}/>
<Route path="/success" component={LoginSuccess}/>
<Route path="/account" component={MyAccount}/>
...
<Route component={Error404}/>
</Switch>
</div>
}/>
}} />
</BrowserRouter>
);
}
}
This will update the history
parameter automatically, without having to re-render on componentDidMount()
or componentDidUpdate()