Problem to change class in React that has Responsive Bootstrap Menu

Asked

Viewed 240 times

1

I’m making a site with Bootstrap and Reatjs and this site has a responsive menu. This menu looks like this (example):

  • Dashboard
  • Register
    • User
    • Administrator

Every time I click on one of the menu items is placed by Navlink an active in the classname to change the color of the menu item, until then everything is working normally, the problem is that I want to change the color of the menu, but when it is a submenu I want to change for example the color of the menu "User" and also "Registration", because the "user" page is within "registration". I’ve been trying to do that but I haven’t yet. The code for that is this:

I have the Menu that will call to mount the menu I want: Menu.jsx

<MenuItem path='/' label='Dashboard' exact={ true } icon='home' />
<MenuTree label='Cadastro' icon='contacts' id='cadastro'>
    <MenuTreeItem path='/user' label='Usuário' />
    <MenuTreeItem path='/admin' label='Administrador' />
</MenuTree>

Menuitem works normally because I do not have this submenu. For Menutree the code is this and here is the problem.

Menutree

import React from 'react'

class MenuTree extends React.Component {

hasActiveLink = () => {
    return (document.querySelectorAll(`#ul_${ this.props.id } a.active`).length === 0) ? "" : "active";
}

render() {
    this.classActive = this.hasActiveLink();

    return (
        <li className="nav-item">
            <a className={`nav-link ${ this.classActive }`} data-toggle="collapse" href={ `#${ this.props.id }` } aria-expanded="false" aria-controls={ this.props.id }>
                <span className="menu-title">{ this.props.label }</span>
                <i className="menu-arrow"></i>
                <i className={`mdi mdi-${ this.props.icon } menu-icon`}></i>
            </a>
            <div className="collapse" id={ this.props.id }>
                <ul className="nav flex-column sub-menu" id={ `ul_${ this.props.id }` }>
                    { this.props.children }
                </ul>
            </div>
        </li>
        )
    }
}

export default (MenuTree)

I have the Menutreeitem

import React from 'react'
import { NavLink } from 'react-router-dom'

export default props => (

<li className="nav-item">
    <NavLink className="nav-link" to={props.path} exact={props.exact} activeClassName="active">{props.label}</NavLink>
</li>
)

As can be verified, in case I click on a Menutreeitem, it is changed and inserted the active in the class and so it works, but it does not change the Menutree that is the Parent, so I made the function "hasActiveLink" that checks if there is any link inside that Tree with the active in the class, but this works with error, because only the active appears in my main menu, in case the "Register" when I click for the second time, because from what I noticed it checks the state always before the click, because it is only triggered after rendering, so only next time is my main menu class changed. What I can do to get this information from Child and turn it on?

Note: I have tried to put also in all functions of the Act itself, for example "componentDidUpdate".

1 answer

0

I managed to solve it in the way described below. I do not know if it is the best alternative, but now it is working perfectly.

import React from 'react'
import { withRouter } from "react-router-dom"

class MenuTree extends React.Component {

    constructor(props) {
        super(props);
        this.classNameNoActive = ""
        this.classNameActive = "active"
        this.classActive = this.classNameNoActive;
    }

    getActiveChild = () => {

        const { match, location } = this.props
        var activeChild = false;
        var arrayChildren = this.props.children

        if (arrayChildren.length === undefined) {

            if (location.pathname === arrayChildren.props.path)
                    return true
        } else {
            for(var i = 0; i < arrayChildren.length; i++) {

                if (location.pathname === arrayChildren[i].props.path)
                    return true
            }
        }

        return activeChild
    }

    render() {
        this.classActive = (this.getActiveChild()) ? this.classNameActive : this.classNameNoActive
        return (
            <li className="nav-item">
                <a className={`nav-link ${ this.classActive }`} data-toggle="collapse" href={ `#${ this.props.id }` } aria-expanded="false" aria-controls={ this.props.id }>
                    <span className="menu-title">{ this.props.label }</span>
                    <i className="menu-arrow"></i>
                    <i className={`mdi mdi-${ this.props.icon } menu-icon`}></i>
                </a>
                <div className="collapse" id={ this.props.id }>
                    <ul className="nav flex-column sub-menu" id={ `ul_${ this.props.id }` }>
                        { this.props.children }
                    </ul>
                </div>
            </li>
        )
    }
}

export default withRouter(MenuTree)

Browser other questions tagged

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