Problem to change class in React that has Bootstrap responsive menu

1

I'm doing a site with Bootstrap and ReatJs and this site has a responsive menu. This menu looks like this (example):

  • Dashboard
  • Registration
    • User
    • Administrator

Each 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 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 "User" menu and also the "Register", because the "user" page is inside "register". I have tried to do this but I have not been able to. The code for this is this:

I have the Menu that is calling 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 the 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 it can be verified, if I click on a MenuTreeItem, it changes and inserts the active in the class and so it works, however it does not change the MenuTree which is the parent, so I did the "hasActiveLink" function that checks if it has some link inside that tree with the active in the class, but this works with error, because only appears the active in my main menu, in the case the "Register" when I click the second time, because from what I noticed it verifies the state always before the click, since it is only triggered after rendering, so only next time the class of my main menu is changed. What can I do to pick up that child information and place active on parent?

Note: I have already tried to put all functions of the react itself, such as "componentDidUpdate".

    
asked by anonymous 27.07.2018 / 23:07

1 answer

0

I was able to solve it as described below. I do not know if it's the best alternative, but it's working perfectly now.

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)
    
31.07.2018 / 20:29