'React routing cannot read pathname property on navigation
I have recently started developing frontend apps with React and I come from a little programming experience with react-native. To improve my knowledge on react I studied both the official documentation and took courses on udemy. So I'm building a small test app in which to use react routing (following what we saw in the udemy course). However, I have the following error related to routing (I attach the error screen)
I have searched here on the stack that online for possible solutions, such as downgrading react-router-dom, or modifying the history declaration, but unfortunately I still get this error and I can't understand what it comes from. Do you have any suggestions or advice?
My app configuration:
- package.json
"name": "app1",
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.8.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"history": "^5.3.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-redux": "^7.2.8",
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.0",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
- routes.js
import React, { Component } from 'react';
import Component1 from './functional/component1';
import Component2 from './functional/component2';
import Component3 from './functional/component3';
//import container home-page
import Container1 from './containers/container1';
import Header from './containers/header';
import history from './utils/history';
//react router import
import { Router, Route } from 'react-router';
class Routes extends Component {
render() {
return (
<div>
<Router history={history.location} navigator={history} >
<div>
<Header />
<Route path="/" component={Container1} />
<Route path="/component1" component={Component1} />
<Route path="/component2" component={Component2} />
<Route path="/component3" component={Component3} />
</div>
</Router>
</div>
)
}
}
export default Routes;
-history.js
var createHistory = require('history').createBrowserHistory;
export default createHistory();
Solution 1:[1]
Issue
The low-level Router takes a few different props than it did in v5.
declare function Router( props: RouterProps ): React.ReactElement | null; interface RouterProps { basename?: string; children?: React.ReactNode; location: Partial<Location> | string; // <-- required navigationType?: NavigationType; navigator: Navigator; // <-- required static?: boolean; }
export function Router({
basename: basenameProp = "/",
children = null,
location: locationProp, // <-- undefined location
navigationType = NavigationType.Pop,
navigator,
static: staticProp = false,
}: RouterProps): React.ReactElement | null {
...
let {
pathname = "/", // <-- cannot read "pathname" of undefined!
search = "",
hash = "",
state = null,
key = "default",
} = locationProp;
...
if (location == null) {
return null;
}
return (
<NavigationContext.Provider value={navigationContext}>
<LocationContext.Provider
children={children}
value={{ location, navigationType }}
/>
</NavigationContext.Provider>
);
}
You are incorrectly using a history prop instead of the location prop, and this is why location is undefined in the component and unable to read a pathname.
Additionally, in react-router-dom@6 the Route components necessarily need to be wrapped in the Routes component in order for route path matching and rendering to work.
Solution
Pass the correct required props and wrap the Route components in Routes component.
import React, { Component } from 'react';
import Component1 from './functional/component1';
import Component2 from './functional/component2';
import Component3 from './functional/component3';
//import container home-page
import Container1 from './containers/container1';
import Header from './containers/header';
import history from './utils/history';
//react router import
import { Router, Routes, Route } from 'react-router';
class Routes extends Component {
render() {
return (
<div>
<Router location={history.location} navigator={history} >
<div>
<Header />
<Routes>
<Route path="/" component={Container1} />
<Route path="/component1" component={Component1} />
<Route path="/component2" component={Component2} />
<Route path="/component3" component={Component3} />
</Routes>
</div>
</Router>
</div>
)
}
}
Solution 2:[2]
You are using react router v6 and in v6 you have to wrap all of your route's in <Routes>...</Routes> tag.
//react router import
import { Router, Route, Routes } from 'react-router'; // Make sure to import ----Routes----
class Routes extends Component {
render() {
return (
<div>
<Router history={history.location} navigator={history} >
<div>
<Header />
<Routes>
<Route path="/" component={Container1} />
<Route path="/component1" component={Component1} />
<Route path="/component2" component={Component2} />
<Route path="/component3" component={Component3} />
</Routes>
</div>
</Router>
</div>
)
}
}
export default Routes;
And you can't add anything between <Routes>...</Routes> except <Route />.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Drew Reese |
| Solution 2 | Dharmik Patel |

