Reputation: 548
I'm trying to make my navigation responsive, so clicking a burger menu icon will then add a class to the nav. Simple concept.
Still new to react and next js.
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useRef, setState, useEffect } from 'react'
const Nav = (props) => {
const router = useRouter()
const isExpanded = () => {
this.state = {
isExpanded: false
}
}
function handleToggle(e) {
e.preventDefault();
this.setState({
isExpanded: !this.state.isExpanded
});
}
return (
<nav>
<div>
<Link href="/">
<a><img src="/img/logo.svg" /></a>
</Link>
<button onClick={e => this.handleToggle(e)} className="nav-icon">
<svg className="fill-current text-white" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"/></svg>
</button>
</div>
<div>
<ul className={`collapsed ${isExpanded ? "is-expanded" : ""}`}>
<li className={router.pathname == "/" ? "active" : ""}>
<Link href="./">
<a>Home</a>
</Link>
</li>
<li className={router.pathname == "/blog" ? "active" : ""}>
<Link href="/blog">
<a>Blog</a>
</Link>
</li>
</ul>
</div>
</nav>
)
}
export default Nav
When I click on the menu burger icon, I then get
TypeError: Cannot read property 'handleToggle' of undefined
Any advice in the right direction would be greatly appreciated. Thank you
Upvotes: 1
Views: 1794
Reputation: 12957
You are confusing class based and functional components and not leveraging the advantages of either. Here is a working snippet illustrating a minimal implementation.
It uses React.useState()
to declare and set state. Also, when calling named functions event
will be passed implicitly so you can simply declare onClick={handleToggle}
.
p {
font-family: monospace;
}
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<div id="App"></div>
<script type="text/babel">
const {useState} = React;
const Nav = () => {
const [isExpanded, setIsExpanded] = useState(false);
function handleToggle(e) {
setIsExpanded(prevState => !prevState);
}
return (
<nav>
<div>
<button type="button" onClick={handleToggle} className="nav-icon">
Burger
</button>
</div>
<p>{`isExpanded: ${isExpanded}`}</p>
</nav>
)
}
ReactDOM.render(<Nav />, document.getElementById('App'));
</script>
Upvotes: 2