React Routing: Detect route change
Solution 1
Wrapping with withRouter
works fine, but from react-router5, they have hooks to avoid it. so that we don't inject unwanted props to the component.
In this case, you could make use of useLocation
hook.
If you try to run const location = useLocation()
inside App.js you'll get: "TypeError: useContext(...) is undefined" on line 712 of react-router/esm/react-router.js
. But you can access useLocation()
inside a child component (e.g. Route.js) and pass the location back up to the parent via a prop function setPathname()
<Router>
must be in a parent component in order for useLocation()
to work.
App.js
import React, { useEffect } from "react"
import { BrowserRouter as Router, NavLink} from "react-router-dom"
import "./App.css"
function App() {
const setPathname = (pathname) => {
console.log("**", pathname)
}
return (
<>
<NavLink exact={true} className="nav-link" to="/AdminDashboard">Admin Dashboard</NavLink>
<NavLink exact={true} className="nav-link" to="/UserList">User List</NavLink>
<Router onChange={routeChange}>
<Routes setPathname={setPathname} />
</Router>
</>
);
}
export default App
Routes.js
import React from "react"
import { Router, Route, Switch, NavLink, useLocation } from "react-router-dom"
import AdminDashboard from "./pages/AdminDashboard"
import UserList from "./pages/UserList"
function Routes(props) {
const location = useLocation()
useEffect(() => {
console.log("*", location.pathname)
props.setPathname(location.pathname)
},[location])
return (
<>
<Switch>
<Route path="/AdminDashboard" component={AdminDashboard} exact />
<Route path="/UserList" component={UserList} exact />
</Switch>
</>
);
}
export default Routes
The result of this will give you two console logs. One from the child Routes.js and one from the parent App.js. Then you can set your variable based on the pathname
in either component, as needed.
*, [pathname]
**, [pathname]
Solution 2
I think you need to tie the router into the component using withRouter
..
withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.
https://reacttraining.com/react-router/web/api/withRouter
Micah B.
A C#, MVC, SQL, Web and Windows developer with over 17 years experience in the software development industry with extensive experience in architecture, design and development of secure, high-performance applications, including e-commerce applications, with a variety of standards based technologies. Have worked as a consultant for years directly with high level managers and executives of various companies. I’ve learned their vision and direction, and to analyzed business needs to make recommendations for custom development solutions and integration with existing systems. Have worked with high capacity production databases with up to 500 million rows. Have worked primarily SQL Server, but I have also worked with Oracle and MySQL. Have performance tuned databases, using replication, de-normalization (as well as indices) and other methods to give high-speed access to large data sets. Have several years of experience using Microsoft Azure PaaS and IaaS cloud solutions, including writing applications that run on multiple servers and handle requests for transactional operations while maintaining data integrity with optimistic and pessimistic concurrency.
Updated on June 05, 2022Comments
-
Micah B. almost 2 years
I'm having trouble detecting route changes with React Router v5.
The desire is, when the route changes I want output a console.log.The desire is, when the route changes I want output that route in a console.log in the App component (as shown in the code below) so I can then set a variable in App.js based on the route.Package versions:
"dependencies": { "react": "^16.12.0", "react-router-dom": "^5.1.2", }
This is the App.js code where my router is currently located:
import React from "react"; import { BrowserRouter as Router, Route, Switch, NavLink } from "react-router-dom" import "./App.css"; import AdminDashboard from "./pages/AdminDashboard" import UserList from "./pages/UserList" function App() { const routeChange = () => { console.log("foo!") console.log(window.location.pathname) } return ( <> <Router onChange={routeChange}> <NavLink exact={true} className="nav-link" to="/AdminDashboard">Admin Dashboard</NavLink> <NavLink exact={true} className="nav-link" to="/UserList">User List</NavLink> <Switch> <Route path="/AdminDashboard" component={AdminDashboard} exact /> <Route path="/UserList" component={UserList} exact /> </Switch> </Router> </> ); } export default App;
-
Micah B. about 4 yearsprops.history is undefined.
-
TZiebura about 4 yearshistory prop is inside every component passed to Route so I'm not really sure what is the case, you might try
import { createBrowserHistory } from 'history'; const history = createBrowserHistory()
and assign the listen function that history -
TZiebura about 4 yearsyep that's one of the options as well either operating on history prop or using the hook
-
madannes about 4 yearsThis is cleaner and more intuitive than my answer =)
-
Micah B. about 4 yearsI've tried this method, but when I run "const location = useLocation()" I get an error: "TypeError: useContext(...) is undefined" on line 712 of react-router/esm/react-router.js
-
Vishnu about 4 yearsIts because the react-router context isn't set in that component. Since its the <Router> component that sets the context you could use useHistory in a sub-component, but not in that one. Sorry, i didn't notice this before. Updated my answer. Please check
-
Micah B. about 4 yearsMoving the routes to a child component and then sending those back to the parent via a props function works well. I clarified this, and added information about the error I mentioned in a previous comment inside the answer which edit is awaiting community approval.
-
Ievgen almost 4 yearshow to get before and after changed?
-
Mike Willis over 3 yearsThis worked great for me, but I had to make some minor adjustments: App.js: the
onChange
prop forRouter
did not seem to be used so I removed it. In Routes.js:import React, { useEffect } from "react"
.