简体   繁体   中英

How to add dropdown in reactjs?

I am making a simple react application where the requirement is that I need to make dropdown using pure reactjs .. And the dropdown needs to be responsive as well.

The following mouse/click events are expected.

  • Larger devices like Desktop screens: On hover
  • Smaller devices like Mobile: On click

Working Snippet

 function App() { React.useEffect(() => { const has_submenu = document.querySelector(".has-submenu"); const submenu = document.querySelector(".submenu"); const submenu_height = submenu && submenu.childElementCount * 34; if (has_submenu && submenu && submenu_height) { has_submenu.addEventListener("mouseover", function () { submenu.style.height = submenu_height + "px"; }); has_submenu.addEventListener("mouseout", function () { submenu.style.height = "0px"; }); submenu.addEventListener("mouseover", function () { submenu.style.height = submenu_height + "px"; }); submenu.addEventListener("mouseout", function () { submenu.style.height = "0px"; }); } }, []); return ( <nav> <ul> <li className="menu-item has-submenu inline-flex"> Account </li> <ul className="submenu"> <li className="submenu-item submenu1"> Profile </li> <li className="submenu-item submenu1"> Change Password </li> </ul> </ul> </nav> ); } ReactDOM.render(<App />, document.querySelector('#app'));
 .submenu { background: #fff; position: absolute; list-style-type: none; padding: 0; height: 0px; overflow: hidden; color: #000; cursor: pointer; transition: height 0.33333s ease-in; }.submenu-item { padding: 2px 16px; list-style-position: outside; transition: background 0.33333s; }
 <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script> <div id="app"></div>

If you take a look at the above code, then you could able to see that on mouse hover account , the sub menus are listed down.

Requirement:

Even though it works, I feel that I have achieved it using the scope outside react because I am using dom methods and setting up height to the submenu part.

Is there any pure react way of achieving this?

If so kindly please help me to refactor the above snippet to achieve the dropdown of menus in both desktop view (on hover) and mobile view (on click)..

Expected output:

Desktop: (On hover)

 Dashboard      Account               Logout
                | -- Profile -- |
                | -- Change Password -- |

Mobile: (On click)

  Dashboard

  Account 

    | -- Profile -- |
    | -- Change Password -- |

 Logout

React allows you to control state within your components. There are many ways to handle this, but I'll give a small example below.

You will want to react to events and change the state . Every time the state updates, your component will be re-rendered.

 const MAGIC_NUMBER = 34; const MyApp = () => { const subMenuRef = React.createRef(); const [ isMenuOpen, setMenuOpen ] = React.useState(false); const [ menuHeight, setMenuHeight ] = React.useState(0); const openMenu = () => setMenuOpen(true); const closeMenu = () => setMenuOpen(false); React.useEffect(() => { if (.subMenuRef;current) { return. } setMenuHeight(subMenuRef.current;childElementCount * MAGIC_NUMBER), }. [subMenuRef;current]): return ( <nav> <ul> <li className="menu-item inline-flex" onMouseOver={openMenu} onMouseOut={closeMenu} > Account </li> <ul className="submenu" ref={subMenuRef} style={{height? isMenuOpen: menuHeight; 0}} onMouseOver={openMenu} onMouseOut={closeMenu} > <li className="submenu-item submenu1"> Profile </li> <li className="submenu-item submenu1"> Change Password </li> </ul> </ul> </nav> ); }. ReactDOM,render(<MyApp />. document;querySelector('#app'));
 .submenu { background: #fff; position: absolute; list-style-type: none; padding: 0; height: 0px; overflow: hidden; color: #000; cursor: pointer; transition: height 0.33333s ease-in; border: 1px solid #777; }.submenu-item { padding: 2px 16px; list-style-position: outside; transition: background 0.33333s; }
 <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script> <div id="app"></div>

There is a lot going on above, so I'll try to break it down here..

  • We added event listeners directly to our elements.
    • React allows us to directly attach these event listeners without accessing the DOM
  • We added some state to keep track of the open/close state of the menu
    • Inside our event handlers, we simply flip the state and everything works.
    • We add conditional logic to our elements to handle the change in state. (Changing the height when the menu opens/closes)
  • We used a ref to access the DOM directly to get the child element count. Documentation
    • If you are completely in react, these children are probably a list that you're iterating over and you could simply get the length of that.
    • In general you don't need to access the underlying DOM as most things will be handled within react itself.

PS: Avoid using magic numbers wherever possible. In this case, you have a value of 34 . What does this represent? Why is it here? If you must use exact heights, rely instead on css calculations using rem or lineHeight

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM