******** EDITED TO SIMPLIFY EXAMPLE AND CLARIFY REQUIREMENT AND PROBLEM **********
I'm stumped with this one, I hope someone can help.
I have a nav bar that I need to run a function on to add .active classes to li elements if they have descendants of a.active.
The menu system is a React component: -
import React, {Component} from "react";
import { Link, NavLink } from 'react-router-dom'
import {activateMenu} from './ActivateMenu'
class SidebarMenu extends React.Component {
componentDidMount() {
activateMenu()
}
componentDidUpdate() {
activateMenu()
}
render() {
const renderNavLink = (to, text, icon, renderArrow = false) => {
return(
<NavLink to={to}>
<i className="bullet">{icon}</i>
<span>{text}</span>
{renderArrow ? <span className="pull-right-container">
<i className="angle-left"><FaAngleLeft /></i>
</span> : null}
</NavLink>
)
}
return (
<ul className="sidebar-menu" data-widget="tree">
<li className="">
{renderNavLink('/','Home',<FaHome />)}
</li>
<li className="treeview">
{renderNavLink("#",'Users',<FaGroup />, true)}
<ul className="treeview-menu">
<li>
{renderNavLink(userSearchSlug,'Search',<FaSearch />)}
</li>
</ul>
</li>
<button onClick={activateMenu}>Press Me</button>
</ul>
)
}
}
export default SidebarMenu
This will give me an HTML structure like this: -
<ul class="sidebar-menu tree" data-widget="tree">
<li class="treeview">
<a href="#">
<i class="fa fa-dashboard"></i> <span>Links</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li>
<a href="/link1"><i class="fa fa-circle-o"></i> Link1</a>
</li>
<li>
<a href="/link2"><i class="fa fa-circle-o"></i> Link2</a>
</li>
</ul>
</li>
</ul>
After React has rendered the HTML, I need to trigger a click event on the the .treeview > a node if any a.active nodes are found under .treeview-menu. So: -
<li class="treeview">
<a href="#" *****TRIGGER CLICK EVENT*****>
<i class="fa fa-dashboard"></i> <span>Links</span>
<span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i>
</span>
</a>
<ul class="treeview-menu">
<li>
<a href="/link1"><i class="fa fa-circle-o *****.ACTIVE CLASS HERE****"></i> Link1</a>
</li>
<li>
<a href="/link2"><i class="fa fa-circle-o"></i> Link2</a>
</li>
</ul>
</li>
activeMenu() looks like this: -
$('ul.sidebar-menu li.treeview:not(.menu-open)').has('a.active').find('a').trigger( "click" );
This function works when called from onClick() from a button on the page but it is not working in componentDidMount() and componentDidUpdate(). The function will run (tested with console.log() but not affect the HTML as it should. However, if I run it from a Button, it works perfectly. It also works perfectly when HMR runs.
I've no idea why this is happening. Does anyone have any ideas?
This is probably happening because you're selecting the element directly rather than using refs, although it's hard to say because we have no idea what $('ul.sidebar-menu .treeview a').parent().has('a.active').parent().find('.treeview a')
is selecting, which is why this kind of code is an antipattern.
React may be in some state where it's not prepared to handle click events at those points. Try using something like the following:
import React, {Component} from "react";
import { Link, NavLink } from 'react-router-dom'
class SidebarMenu extends React.Component {
constructor(props) {
super(props);
this.menuRefs = [];
}
componentDidUpdate() {
if (this.menuRefs.length) {
this.menuRefs[0].click();
}
}
render() {
const renderNavLink = (to, text, icon, renderArrow = false) => {
return(
<NavLink to={to} innerRef={ref => this.menuRefs.push(ref)}>
<i className="bullet">{icon}</i>
<span>{text}</span>
{renderArrow ? <span className="pull-right-container">
<i className="angle-left"><FaAngleLeft /></i>
</span> : null}
</NavLink>
)
}
return (
<ul className="sidebar-menu" data-widget="tree">
<li className="">
{renderNavLink('/','Home',<FaHome />)}
</li>
<li className="treeview">
{renderNavLink("#",'Users',<FaGroup />, true)}
<ul className="treeview-menu">
<li>
{renderNavLink(userSearchSlug,'Search',<FaSearch />)}
</li>
</ul>
</li>
<button onClick={() => this.menuRefs[0] && this.menuRefs[0].click()}>Press Me</button>
</ul>
)
}
}
export default SidebarMenu
Notice
Note however that you may want to keep a map to ensure that no duplicates get pushed into menuRefs.
To learn more about refs, visit the docs: https://reactjs.org/docs/refs-and-the-dom.html
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.