'React ERROR:TypeError: Cannot read property 'pathname' of undefined
This is my Menu
component. I later import it in routes.js
. I am getting this error.
TypeError: Cannot read property 'pathname' of undefined
After searching for it and looking over some solutions, it looks like this could be a route.js
. There were some solutions, where it was suggested to use this.props.history.location.pathname
but it doesn't work.
I have also posted routes.js
below.
Navbar.js component
class Menu extends Component {
constructor(props) {
super(props);
this.state = {
collapseOpen: false,
modalSearch: false,
color: "navbar-transparent",
isFull: false,
};
}
goFull = () => {
this.setState({ isFull: true });
};
componentDidMount() {
window.addEventListener("resize", this.updateColor);
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateColor);
}
// function that adds color white/transparent to the navbar on resize (this is for the collapse)
updateColor = () => {
if (window.innerWidth < 993 && this.state.collapseOpen) {
this.setState({
color: "bg-white",
});
} else {
this.setState({
color: "navbar-transparent",
});
}
};
// this function opens and closes the collapse on small devices
toggleCollapse = () => {
if (this.state.collapseOpen) {
this.setState({
color: "navbar-transparent",
});
} else {
this.setState({
color: "bg-white",
});
}
this.setState({
collapseOpen: !this.state.collapseOpen,
});
};
// this function is to open the Search modal
toggleModalSearch = () => {
this.setState({
modalSearch: !this.state.modalSearch,
});
};
render() {
return (
<Fullscreen
enabled={this.state.isFull}
onChange={(isFull) => this.setState({ isFull })}
>
<Navbar
className={classNames("navbar-absolute", {
[this.state.color]:
this.props.location.pathname.indexOf("full-screen-map") === -1,
})}
expand="lg"
>
<Container fluid>
<div className="navbar-wrapper">
<div className="navbar-minimize d-inline">
<Button
className="minimize-sidebar btn-just-icon"
color="link"
id="tooltip209599"
onClick={this.props.handleMiniClick}
>
<i className="icon-align-center visible-on-sidebar-regular" />
<i className="icon-bullet-list-67 visible-on-sidebar-mini" />
</Button>
<UncontrolledTooltip
delay={0}
target="tooltip209599"
placement="right"
>
Sidebar toggle
</UncontrolledTooltip>
</div>
<div
className={classNames("navbar-toggle d-inline", {
toggled: this.props.sidebarOpened,
})}
>
<button
className="navbar-toggler"
type="button"
onClick={this.props.toggleSidebar}
>
<span className="navbar-toggler-bar bar1" />
<span className="navbar-toggler-bar bar2" />
<span className="navbar-toggler-bar bar3" />
</button>
</div>
<NavbarBrand href="#pablo" onClick={(e) => e.preventDefault()}>
{this.props.brandText}
</NavbarBrand>
</div>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navigation"
aria-expanded="false"
aria-label="Toggle navigation"
onClick={this.toggleCollapse}
>
<span className="navbar-toggler-bar navbar-kebab" />
<span className="navbar-toggler-bar navbar-kebab" />
<span className="navbar-toggler-bar navbar-kebab" />
</button>
<Collapse navbar isOpen={this.state.collapseOpen}>
<Nav className="ml-auto" navbar>
<InputGroup className="search-bar" tag="li">
<Button
color="link"
data-target="#searchModal"
data-toggle="modal"
id="search-button"
onClick={this.toggleModalSearch}
>
<i className="icon-zoom-split" />
<span className="d-lg-none d-md-block">Search</span>
</Button>
</InputGroup>
<UncontrolledDropdown nav>
<DropdownToggle
caret
color="default"
data-toggle="dropdown"
nav
>
<div className="notification d-none d-lg-block d-xl-block" />
<i className="icon-sound-wave" />
<p className="d-lg-none">Notifications</p>
</DropdownToggle>
<DropdownMenu className="dropdown-navbar" right tag="ul">
<NavLink tag="li">
<DropdownItem className="nav-item">
Mike John responded to your email
</DropdownItem>
</NavLink>
<NavLink tag="li">
<DropdownItem className="nav-item">
You have 5 more tasks
</DropdownItem>
</NavLink>
<NavLink tag="li">
<DropdownItem className="nav-item">
Your friend Michael is in town
</DropdownItem>
</NavLink>
<NavLink tag="li">
<DropdownItem className="nav-item">
Another notification
</DropdownItem>
</NavLink>
<NavLink tag="li">
<DropdownItem className="nav-item">
Another one
</DropdownItem>
</NavLink>
</DropdownMenu>
</UncontrolledDropdown>
<UncontrolledDropdown nav>
<DropdownToggle
caret
color="default"
data-toggle="dropdown"
nav
onClick={(e) => e.preventDefault()}
>
<div className="photo">
<img alt="user preferences" src={UserIcon} />
</div>
<b className="caret d-none d-lg-block d-xl-block" />
<p className="d-lg-none">Log out</p>
</DropdownToggle>
<DropdownMenu className="dropdown-navbar" right tag="ul">
<NavLink tag="li">
<DropdownItem className="nav-item">Profile</DropdownItem>
</NavLink>
<NavLink tag="li">
<DropdownItem className="nav-item">Settings</DropdownItem>
</NavLink>
<DropdownItem divider tag="li" />
<NavLink tag="li">
<DropdownItem className="nav-item">Log out</DropdownItem>
</NavLink>
</DropdownMenu>
</UncontrolledDropdown>
<li className="separator d-lg-none" />
</Nav>
</Collapse>
</Container>
</Navbar>
</Fullscreen>
);
}
}
export default Menu;
routes.js
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import AdminNavbar from "../components/Menu/Navbar";
const AppRouter = () => {
return (
<Router>
<div>
<Switch>
<Route path="/navbar">
<AdminNavbar />
</Route>
</Switch>
</div>
</Router>
);
};
export default AppRouter;
Solution 1:[1]
react-router-dom@5
To "inject" route props into the component
You can either render AdminNavbar
as a component
, render
, or children
render methods:
const AppRouter = () => {
return (
<Router>
<div>
<Switch>
<Route path="/navbar" component={AdminNavbar} />
</Switch>
</div>
</Router>
);
};
Or decorate AdminNavbar
with withRouter Higher Order Component
import { withRouter } from "react-router-dom";
class Menu extends Component {
...
render() {
return (
<Fullscreen
enabled={this.state.isFull}
onChange={isFull => this.setState({ isFull })}
>
<Navbar
className={classNames("navbar-absolute", {
[this.state.color]:
this.props.location.pathname.indexOf("full-screen-map") === -1
})}
expand="lg"
>
...
</Navbar>
</Fullscreen>
);
}
}
export default withRouter(Menu);
react-router-dom@6
react-router-dom
v6 Removed the route props. If needing to access "route props" in a class component you will need to create a custom withRouter
HOC since it was also removed in v6. Keep in mind that a navigate
function replaced the history
object.
Example:
import { useLocation, useNavigation, useParams } from 'react-router-dom';
const withRouter = Component => props => (
<Component
{...props}
location={useLocation()}
navigate={useNavigate()}
params={useParams()}
/>
);
export default withRouter;
Solution 2:[2]
is not available in react-router-dom
instead use
<Routes> <Route path="/" component={componentName}> </Routes>
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 | |
Solution 2 | Maryam |