0

I'm using the following JavaScript code to toggle between 0 height and X height. It's the dropdown menu for a hamburger icon.

// Hamburger navigation
const menuToggle = document.querySelector(".menu-toggle");
const nav = menuToggle.parentElement;
const menuDropdown = document.querySelector(".menu-dropdown");

menuToggle.addEventListener("click", event => {
    event.preventDefault();
    nav.classList.toggle("is-open");

    const height = menuDropdown.scrollHeight;

    if (nav.classList.contains("is-open")) {
        menuDropdown.style.setProperty("height", height + "px");
    } else {
        menuDropdown.style.setProperty("height", "0");
    }
});

I can do the toggling of the class "is-open" using something like this in React and it works:

const [isOpen, setState] = useState(false)
const toggleNav = () => setState(!isOpen)

But how do I handle the height?

const height = menuDropdown.scrollHeight;

if (nav.classList.contains("is-open")) {
     menuDropdown.style.setProperty("height", height + "px");
} else {
     menuDropdown.style.setProperty("height", "0");
}

I would be grateful for any suggestion.

Zoltan King
  • 1,964
  • 4
  • 18
  • 38
  • Does this answer your question? [ReactJS - Get Height of an element](https://stackoverflow.com/questions/35153599/reactjs-get-height-of-an-element) – Emile Bergeron Apr 20 '20 at 21:11
  • Once you have retrieved the height correctly with the right React API (using a ref in this case), you could just use the following to apply it to the right element: `
    `.
    – Emile Bergeron Apr 20 '20 at 21:19
  • Converting vanilla DOM manipulations to React doesn't really make sense. You need to [think in React and invert the data flow](https://reactjs.org/docs/thinking-in-react.html), where instead of reading the DOM, you only read from your own data state and always write to the DOM. – Emile Bergeron Apr 20 '20 at 21:27

3 Answers3

1

use style attribute with react braces {}

import React, { useState } from 'react';
import './Header.scss';

const Header = () => {
 const [Height, setHeight] = useState('0px');

 const handleClickMenu = () => ((Height == '0px') ? setHeight('80px') : 
 setHeight('0px'));

 return (
   <nav>
     <button 
       type='button' 
       onClick={handleClickMenu} 
       className='your-navbar-burger-class'
     >
       your-hamburger-button
     </button>

     <div 
       className='your-dropdown-menu-class'
       style={{ height: Height}}
     >
       //your dropdown
     </div>
   </nav>
 );
};

export default Header;
  • 1
    With display: none I cannot use the transition animation. The menu already works fine in vanilla JS/CSS I just need a way to make it work with React that's all. – Zoltan King Apr 20 '20 at 20:06
  • 1
    mmm, ok then you could use inline style html attribute, i updated the answer check it out – Pedro Sánchez Apr 20 '20 at 21:33
  • the handleClick function, change it for whatever your logic is – Pedro Sánchez Apr 20 '20 at 21:35
  • 1
    It would be clearer if the state was a boolean flag like `open` and you'd only need to use it within the style object: `style={{ height: open ? heightValue : 0 }}` – Emile Bergeron Apr 20 '20 at 21:35
  • 1
    Thank you. Your solution works fine. I need to take a deeper look at React. I'll take a course or something. I only used components for displaying stuff but when it comes to adding logic it seems strange compared to vanilla ES6. – Zoltan King Apr 20 '20 at 22:18
  • 1
    @ZoltanKing yes exactly, React requires a complete mind shift! Its data first pattern really shines when you embrace it instead of fighting it! – Emile Bergeron Apr 20 '20 at 22:37
0

You can use useEffect to manage the height.

useEffect(()=>{
// your code mere below is just an example.
 if (nav.classList.contains("is-open")) {
     menuDropdown.style.setProperty("height", height + "px");
} else {
     menuDropdown.style.setProperty("height", "0");
}
// [isOpen] here maintain this useEffect and runs only if the value isOpen is changed
}, [isOpen])

useEffect

costal oktopus
  • 319
  • 2
  • 12
0

If you're trying to transition the height of a dropdown menu, you might be better off toggling a class on the menu and using a pure CSS technique. I recommend "Technique 1: max-height" detailed here:

https://css-tricks.com/using-css-transitions-auto-dimensions/

symlink
  • 11,984
  • 7
  • 29
  • 50