ReactJS - допустимая функция не работает при вызове в componentDidMount() и componentDidUpdate()
******** РЕДАКТИРОВАНИЕ ДЛЯ УПРОЩЕНИЯ ПРИМЕРА И УТОЧНЕНИЯ ТРЕБОВАНИЯ И ПРОБЛЕМЫ **********
Я озадачен этим, я надеюсь, что кто-то может помочь.
У меня есть панель навигации, на которой мне нужно запустить функцию для добавления классов.active к элементам li, если у них есть потомки a.active.
Система меню является компонентом React:
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
Это даст мне такую структуру HTML:
<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>
После того, как React отобразит HTML, мне нужно вызвать событие click на узле.treeview >, если какие-либо активные узлы найдены в.treeview-menu. Так: -
<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 () выглядит так:
$('ul.sidebar-menu li.treeview:not(.menu-open)').has('a.active').find('a').trigger( "click" );
Эта функция работает при вызове из onClick() с кнопки на странице, но она не работает в componentDidMount() и componentDidUpdate(). Функция будет работать (протестировано с console.log(), но не повлияет на HTML должным образом. Однако, если я запускаю ее из Button, она работает отлично. Она также отлично работает при запуске HMR.
Я понятия не имею, почему это происходит. У кого-нибудь есть какие-либо идеи?
1 ответ
Это, вероятно, происходит потому, что вы выбираете элемент напрямую, а не используете ссылки, хотя трудно сказать, потому что мы понятия не имеем, что $('ul.sidebar-menu .treeview a').parent().has('a.active').parent().find('.treeview a')
выбирает, поэтому этот вид кода является антипаттерном.
Реакция может быть в каком-то состоянии, когда она не готова обрабатывать события щелчка в этих точках. Попробуйте использовать что-то вроде следующего:
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
уведомление
- Теперь есть массив "menuRefs", и вы просто используете их как обычные элементы DOM.
- Мы нажимаем на menuRefs в подпорке NavLink innerRef (находится здесь)
Тем не менее, обратите внимание, что вы можете сохранить карту, чтобы гарантировать, что дубликаты не будут вставлены в menuRefs.
Чтобы узнать больше о ссылках, посетите документы: https://reactjs.org/docs/refs-and-the-dom.html