Open isolated dropdown with useState and useRef

Asked

Viewed 25 times

0

I have a sidebar where I’m using a dropdown while hovering over each icon on that sidebar. I am using useState to open the dropdown and would like to use only one state for everyone, but open each one separately. I’m using useRef to open each one separately, but I’m not sure how to do it.

const Sidebar = () => {
        const [dropdown, setDropdown] = useState(null);
        const dashboard = useRef(dropdown)
        const tickets = useRef(dropdown)
        const services = useRef(dropdown);
        const analytics = useRef(dropdown);
        const register = useRef(dropdown);
        const administracao = useRef(dropdown);)

        const showDropdown = (e) => {
            console.log(dashboard.current)
            switch (e.target) {
                case "Dashboard":
                    setDropdown(true);
                    break;
                case "Tickets":
                    setDropdown(true);
                    break;
                default:
                    break;
            }
        };

        const closeDropdown = () => {
            setDropdown(null);
        };

        return(
            <nav className="sidebar__content">
                <div className="logo__area sb-flex-center">
                    <Logo width={"2.5rem"}/>
                </div>
                <div className="sidebar__icons" >
                    
                    <div className="sb-flex-aligcenter" ref={dashboard}>
                        <NavLink to="/" end activeClassName="icon-select" onMouseOver={showDropdown} onMouseOut={closeDropdown} id="Dashboard" className="sb-flex-aligcenter" >
                            <Icon iconSvg={Icons.IconDashboard} iconWidth={1.75} iconWidthContainer={[3,2.6]} iconStyle={"icon__area"} iconStatus={""}/>
                            <span className="active-icon"></span>
                        </NavLink>
                        {dropdown===true && <SideModal titulo={"Dashboard"}/>}
                    </div>
                    <div className="sb-flex-aligcenter">
                        <NavLink to="tickets" activeClassName="icon-select" onMouseOver={showDropdown} onMouseOut={closeDropdown} id="Tickets" className="sb-flex-aligcenter" ref={tickets}>
                            <Icon iconSvg={Icons.IconTickets} iconWidth={1.5} iconWidthContainer={[3,2.6]} iconStyle={"icon__area"} disable={true}/>
                            <span className="active-icon" style={{}}></span>
                        </NavLink>
                        {dropdown===true && <SideModal titulo={"Tickets"}/>}
                    </div>
                    <div className="sb-flex-aligcenter">
                        <NavLink to="servicos" activeClassName="icon-select" onMouseOver={"showDropdown"} onMouseOut={"closeDropdown"} className="sb-flex-aligcenter">
                            <Icon iconSvg={Icons.IconServices} iconWidth={1.5} iconWidthContainer={[3,2.6]} iconStyle={"icon__area"}/>
                            <span className="active-icon" style={{}}></span>
                        </NavLink>
                        {dropdown && <SideModal titulo={"Serviços"} ref={services}/>}
                    </div>
                    <div className="sb-flex-aligcenter">
                        <NavLink to="analytics" activeClassName="icon-select" onMouseOver={"showDropdown"} onMouseOut={"closeDropdown"} className="sb-flex-aligcenter">
                            <Icon iconSvg={Icons.IconAnalytics} iconWidth={1.5} iconWidthContainer={[3,2.6]} iconStyle={"icon__area"}/>
                            <span className="active-icon" style={{}}></span>
                        </NavLink>
                        {dropdown && <SideModal titulo={"Analytics"} ref={analytics}/>}
                    </div>
                    <div className="sb-flex-aligcenter">
                        <NavLink to="cadastro" activeClassName="icon-select" onMouseOver={"showDropdown"} onMouseOut={"closeDropdown"} className="sb-flex-aligcenter">
                            <Icon iconSvg={Icons.IconRegister} iconWidth={1.5} iconWidthContainer={[3,2.6]} iconStyle={"icon__area"}/>
                            <span className="active-icon" style={{}}></span>
                        </NavLink>
                        {dropdown && <SideModal titulo={"Cadastros"} ref={register}/>}
                    </div>
                    <div className="sb-flex-aligcenter">
                        <NavLink to="administracao" activeClassName="icon-select" onMouseOver={"showDropdown"} onMouseOut={"closeDropdown"} className="sb-flex-aligcenter">
                            <Icon iconSvg={Icons.IconManagement} iconWidth={1.5} iconWidthContainer={[3,2.6]} iconStyle={"icon__area"}/>
                            <span className="active-icon" style={{}}></span>
                        </NavLink>
                        {dropdown && <SideModal titulo={"Administração"} ref={administracao}/>}
                    </div>
                </div>
                <div className="side-footer icon-hover sb-flex-center" onMouseOver={"showDropdown"} onMouseOut={"closeDropdown"}>
                    <Icon iconSvg={Icons.IconModules} iconWidth={1.3} iconWidthContainer={[3,2.6]} iconStyle={"icon__area"} className="teste"/>
                </div>
            </nav>
        )
}

export default Sidebar;

1 answer

0


Using useRef may not be the best choice, since useRef .Current may be confused when used with the same reference by other elements. In my opinion the best choice would be for you to create a single component Dropdown and maintain the individual state for each component, so you would avoid sharing Hooks. Another solution is to use as a dropdown state an object that holds the boolean values for each of the elements, something like the following:

const [dropdown, setDropdown] = useState({"Dashboard": true, "Tickets": false})

The two methods work, but I would choose to abstract everything into one component.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.