I'm going through a navbar tutorial on youtube (https://www.youtube.com/watch?v=IF6k0uZuypA&t=987s) - the link is with the timecode. It should work like at this moment in the vid
calcHeight should do the work but it doesn't. The navbar changes abruptly like at https://www.youtube.com/watch?v=IF6k0uZuypA&t=925s
function DropdownMenu() {
const [activeMenu, setActiveMenu] = useState("main");
const [menuHeight, setMenuHeight] = useState(0);
function calcHeight(el) {
const height = el.offsetHeight;
setMenuHeight(height);
}
const mainMenuRef = useRef(null);
const settingsMenuRef = useRef(null);
function DropdownItem(props) {
return (
<a href="#" className="menu-item" onClick={() => props.goToMenu && setActiveMenu(props.goToMenu)}>
<span className="icon-button">{props.leftIcon}</span>
{props.children}
<span className="icon-right">{props.rightIcon}</span>
</a>
);
}
return (
<div className="dropdown" style={{height: menuHeight}}>
<CSSTransition
in={activeMenu === "main"}
unmountOnExit
timeout={500}
classNames="menu-primary"
nodeRef={mainMenuRef}
onEnter={calcHeight}
>
...
It's a relatively old tutorial, react changed a bit and, as far as I know, we need to now add a ref.
Even after adding dropdownRef it still doesn't work. It messed up the result even more. Now the height of menu stays the same.
function DropdownMenu() {
const [activeMenu, setActiveMenu] = useState("main");
const [menuHeight, setMenuHeight] = useState(null);
const dropdownRef = useRef(null);
//function calcHeight(el) {
// const height = el.offsetHeight;
// setMenuHeight(height);
//} Used to be like this
function calcHeight() {
const height = dropdownRef.current.offsetHeight;
setMenuHeight(height);
}
const mainMenuRef = useRef(null);
const settingsMenuRef = useRef(null);
function DropdownItem(props) {
//...
)
}
return (
<div className="dropdown" style={{ height: menuHeight }} ref={dropdownRef}>
//...
)
How to fix this? Looking forward to any help. Thanks in advance
https://github.com/fireship-io/229-multi-level-dropdown/tree/master/src - github repo for the tutorial
Part of the CSS code:
.menu-primary-enter {
position: absolute;
-webkit-transform: translateX(-110%);
-ms-transform: translateX(-110%);
transform: translateX(-110%);
}
.menu-primary-enter-active {
-webkit-transform: translateX(0%);
-ms-transform: translateX(0%);
transform: translateX(0%);
-webkit-transition: all var(--speed) ease;
-o-transition: all var(--speed) ease;
transition: all var(--speed) ease;
}
.menu-primary-exit {
position: absolute;
}
.menu-primary-exit-active {
-webkit-transform: translateX(-110%);
-ms-transform: translateX(-110%);
transform: translateX(-110%);
-webkit-transition: all var(--speed) ease;
-o-transition: all var(--speed) ease;
transition: all var(--speed) ease;
}
.menu-secondary-enter {
-webkit-transform: translateX(110%);
-ms-transform: translateX(110%);
transform: translateX(110%);
}
.menu-secondary-enter-active {
-webkit-transform: translateX(0%);
-ms-transform: translateX(0%);
transform: translateX(0%);
-webkit-transition: all var(--speed) ease;
-o-transition: all var(--speed) ease;
transition: all var(--speed) ease;
}
.menu-secondary-exit {
}
.menu-secondary-exit-active {
-webkit-transform: translateX(110%);
-ms-transform: translateX(110%);
transform: translateX(110%);
-webkit-transition: all var(--speed) ease;
-o-transition: all var(--speed) ease;
transition: all var(--speed) ease;
}
.dropdown {
position: absolute;
top: 58px;
width: 300px;
-webkit-transform: translateX(-45%);
-ms-transform: translateX(-45%);
transform: translateX(-45%);
background-color: var(--bg);
border: var(--border);
border-radius: var(--border-radius);
padding: 1rem;
overflow: hidden;
-webkit-transition: height var(--speed) ease;
-o-transition: height var(--speed) ease;
transition: height var(--speed) ease;
}
Full App.js code below:
import { ReactComponent as BellIcon } from './icons/bell.svg';
import { ReactComponent as MessengerIcon } from './icons/messenger.svg';
import { ReactComponent as CaretIcon } from './icons/caret.svg';
import { ReactComponent as PlusIcon } from './icons/plus.svg';
import { ReactComponent as CogIcon } from './icons/cog.svg';
import { ReactComponent as ChevronIcon } from './icons/chevron.svg';
import { ReactComponent as ArrowIcon } from './icons/arrow.svg';
import { ReactComponent as BoltIcon } from './icons/bolt.svg';
import React, { useState, useRef, useEffect } from "react";
import { CSSTransition } from "react-transition-group";
function App() {
return (
<Navbar>
<NavItem icon={ <PlusIcon /> } />
<NavItem icon={ <BellIcon /> } />
<NavItem icon={ <MessengerIcon /> } />
<NavItem icon={<CaretIcon />}>
<DropdownMenu></DropdownMenu>
</NavItem>
</Navbar>
);
}
function DropdownMenu() {
const [activeMenu, setActiveMenu] = useState("main");
const [menuHeight, setMenuHeight] = useState(null);
function calcHeight(el) {
const height = el.offsetHeight;
setMenuHeight(height);
}
const mainMenuRef = useRef(null);
const settingsMenuRef = useRef(null);
function DropdownItem(props) {
return (
<a href="#" className="menu-item" onClick={() => props.goToMenu && setActiveMenu(props.goToMenu)}>
<span className="icon-button">{props.leftIcon}</span>
{props.children}
<span className="icon-right">{props.rightIcon}</span>
</a>
);
}
return (
<div className="dropdown" style={{ height: menuHeight }} >
<CSSTransition
in={activeMenu === "main"}
unmountOnExit
timeout={500}
classNames="menu-primary"
nodeRef={mainMenuRef}
onEnter={calcHeight}
>
<div className="menu" ref={mainMenuRef}>
<DropdownItem>My Profile</DropdownItem>
<DropdownItem
leftIcon={<CogIcon />}
rightIcon={<ChevronIcon />}
goToMenu="settings"
>
Settings
</DropdownItem>
</div>
</CSSTransition>
<CSSTransition
in={activeMenu === "settings"}
unmountOnExit
timeout={500}
classNames="menu-secondary"
nodeRef={settingsMenuRef}
>
<div className="menu" ref={settingsMenuRef}>
<DropdownItem leftIcon={<ArrowIcon />} goToMenu="main" />
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Settings</DropdownItem>
</div>
</CSSTransition>
</div>
)
}
function Navbar(props) {
return (
<nav className="navbar">
<ul className="navbar-nav">{ props.children }</ul>
</nav>
)
}
function NavItem(props) {
const [open, setOpen] = useState(false);
return (
<li className="nav-item">
<a href="#" className="icon-button" onClick={() => setOpen(!open)}>
{ props.icon }
</a>
{open && props.children}
</li>
)
}
export default App;
Top comments (0)