#javascript #reactjs #bootstrap-4
#javascript #reactjs #bootstrap-4
Вопрос:
Когда я нажимаю на одну ссылку выпадающего меню на панели навигации, все ссылки выпадающего меню также отображаются. Как мне это исправить, разрешив показывать только одну ссылку выпадающего меню?
Я попытался изменить значение id, которое указывает на aria-labelledby
Это состояние моего приложения
state = {
dropDown: false
};
handleDropdown = e => {
this.setState({ dropDown: !this.state.dropDown });
};
Внутри функции рендеринга
render() {
const { dropDown } = this.state;
/*Conditional statement to select a class base on the state*/
const dropMenu = dropDown ? 'dropdown-menu show' : 'dropdown-menu';
/*The two dropdown menu list the displays(both) even when one is clicked*/
<li className="nav-item dropdown">
<Link
onClick={this.handleDropdown}
className="nav-link dropdown-toggle"
href="#"
id="navbarDropdown"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Dropdown
</Link>
<div className={dropMenu} aria-labelledby="navbarDropdown">
<Link className="dropdown-item" to="#">
Action
</Link>
<Link className="dropdown-item" to="#">
Another action
</Link>
<div className="dropdown-divider" />
<Link className="dropdown-item" to="#">
Something else here
</Link>
</div>
</li>
<li className="nav-item dropdown">
<Link
onClick={this.handleDropdown}
className="nav-link dropdown-toggle"
href="#"
id="navbarDropdown"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Dropdown
</Link>
<div className={dropMenu} aria-labelledby="navbarDropdown">
<Link className="dropdown-item" to="#">
Action
</Link>
<Link className="dropdown-item" to="#">
Another action
</Link>
<div className="dropdown-divider" />
<Link className="dropdown-item" to="#">
Something else here
</Link>
</div>
</li>
};
Комментарии:
1. Так же, как в качестве альтернативы написанию этого вручную, вам следует использовать чужой код. reactstrap.github.io/components/navs В нем присутствуют все ранее существовавшие меню Bootstrap 4.
2. Спасибо за ресурс. Но в этом проекте я хочу использовать Bootstrap как зависимость, а не использовать пакет начальной загрузки, такой как react-bootstrap
Ответ №1:
потому что у вас только 1 состояние для обработки отображения и скрытия выпадающего меню. попробуйте сделать это так :
state = {
dropDown: {
link1: false,
link2: false,
}
}
handleDropdown = e => {
const { id } = e.target;
this.setState(prevState => ({
dropDown : {
...prevState.dropDown,
[id]: !prevState.dropDown[id],
}
}));
}
render() {
const { dropDown } = this.state;
/*Conditional statement to select a class base on the state*/
const dropMenu = dropDown ? 'dropdown-menu show' : 'dropdown-menu';
/*The two dropdown menu list the displays(both) even when one is clicked*/
<li className="nav-item dropdown">
<Link
onClick={this.handleDropdown}
className="nav-link dropdown-toggle"
href="#"
id="link1" // name your id same as the variable from state dropDown
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Dropdown
</Link>
<div className={`dropdown-menu ${dropDown.link1 ? 'show' : ''}`} aria-labelledby="navbarDropdown">
<Link className="dropdown-item" to="#">
Action
</Link>
<Link className="dropdown-item" to="#">
Another action
</Link>
<div className="dropdown-divider" />
<Link className="dropdown-item" to="#">
Something else here
</Link>
</div>
</li>
<li className="nav-item dropdown">
<Link
onClick={this.handleDropdown}
className="nav-link dropdown-toggle"
href="#"
id="link2" // name your id same as the variable from state dropDown
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Dropdown
</Link>
<div className={`dropdown-menu ${dropDown.link2 ? 'show' : ''}`} aria-labelledby="navbarDropdown">
<Link className="dropdown-item" to="#">
Action
</Link>
<Link className="dropdown-item" to="#">
Another action
</Link>
<div className="dropdown-divider" />
<Link className="dropdown-item" to="#">
Something else here
</Link>
</div>
</li>
}
надеюсь, это сработает.
Ответ №2:
Обновленный код
Измените переменную состояния следующим образом:
state = {
dropDownState: [false, false]
};
Поскольку у вас их всего два li > div
, массив содержит два элемента, если пункты меню увеличиваются, увеличьте и их.
Тогда div будет выглядеть как
<div className={dropMenu[0]} aria-labelledby="navbarDropdown">
и <div className={dropMenu[1]} aria-labelledby="navbarDropdown">
Каждая из привязок функций будет выглядеть следующим образом
onClick={() => this.handleDropdown(0)}
onClick={() => this.handleDropdown(1)}
Затем фактическая функция изменится на
handleDropdown = (menuIndex) => {
let newMenuState = this.state.dropDownState.map((val, index) => {
if(index === menuIndex) {
return !val
} else return val
});
this.setState({ dropDownState: newMenuState })
};
Пожалуйста, обратите внимание, что я не запускал код со своей стороны, но вы должны понять идею.
Старый ответ
Вместо вызова функции привяжите значение к функции:
Изменить
onClick={this.handleDropdown}
Для
onClick={() => this.handleDropdown()}
Комментарии:
1. Я попытался привязать метод, но он по-прежнему вызывал две ссылки выпадающего меню
2. Где вы используете const
const dropMenu
? Я больше нигде не вижу этого в вашем коде. Разве вам не нужно использовать это как класс div внутри каждогоli
? Мало того, одна переменная состояния определяет класс, который затем влияет на все подразделения внутри каждогоli
s (после применения const в качестве класса для div). Вам нужно сделать его динамическим с помощью массива. Каждый элемент массива будет содержать состояние для каждогоli > div
.3. Ой, извините. Я только что отредактировал код. Точно, я использовал dropMenu в div внутри li, и проблема все еще существует. Пожалуйста, я не получаю путь, по которому мне нужно сделать его динамическим. Потому что const dropMenu содержит класс в зависимости от состояния выпадающего списка в функции рендеринга . Спасибо за ваше время.
4. Я приближаюсь к решению. Я console.log(dropMenu[0]), который вы использовали в элементе div в своем обновленном коде, и получил первую букву класса, которая была d (т. Е. выпадающее меню).
5. Измените
<div className={dropMenu[0]} aria-labelledby="navbarDropdown">
на<div className={this.state.dropDownState[0]} aria-labelledby="navbarDropdown">
, извините, я пропустил эту часть. В основном используется элемент массива из новой переменной состояния.