#javascript #jquery #reactjs #menu #header
Вопрос:
У меня есть компонент заголовка, в котором я хочу переключать имя класса между всеми элементами меню (если один из элементов меню активен, и пользователь нажимает на другой элемент — этот элемент становится активным, а все остальные нет). У меня есть такой код
import React, { useState } from 'react'; import './header.scss'; export const Header = ({ favoriteCount }) =gt; { const [activeIndex, setActiveIndex] = useState(0); function toggleClass(index) { setActiveIndex(index); } return ( lt;header className="header"gt; lt;div className="container header-container"gt; lt;ul className="header-menu"gt; lt;ligt; lt;a className={ activeIndex === 0 ? 'header-menu__link active' : 'header-menu__link' } onClick={() =gt; { toggleClass(0); }} href="##" gt; Characters lt;/agt; lt;/ligt; lt;ligt; lt;a className={ activeIndex === 1 ? 'header-menu__link active' : 'header-menu__link' } onClick={() =gt; { toggleClass(0); }} href="##" gt; Favorites lt;/agt; lt;/ligt; lt;/ulgt; lt;div className="header-favorite-count"gt; lt;i className="far fa-heart"gt;lt;/igt; {favoriteCount} lt;/divgt; lt;/divgt; lt;/headergt; ); };
и стили для визуализации классов переключения
amp;-menu__link { color: lightgray; } .active { color: #fff; }
Этот подход работает, но выглядит жутковато. Может быть, кто-то знает, как его оптимизировать?
Ответ №1:
Я бы не стал использовать индекс, я бы использовал текст элемента. Я бы также включил этот текст в href
, чтобы было указание на то, к чему ведет якорь. Чтобы избежать повторного кода, вы можете поместить пункты меню в повторно используемый массив, что-то вроде этого:
const menuItems = [ "Characters", "Favorites", ]; export const Header = ({ favoriteCount }) =gt; { const [activeItem, setActiveItem] = useState(""); const setActiveItem = useCallback((event) =gt; { setActiveItem(event.currentTarget.href.substring(2)); }, []); const list = menuItems.map(item =gt; lt;li key={item}gt; lt;a className={`header-menu__link ${item === activeItem ? "active" : ""}`} onClick={setActiveItem} href={"##" item}gt; {item} lt;/agt; lt;/ligt; ); return ( lt;header className="header"gt; lt;div className="container header-container"gt; lt;ul className="header-menu"gt; {list}} lt;/ulgt; lt;div className="header-favorite-count"gt; lt;i className="far fa-heart"gt;lt;/igt; {favoriteCount} lt;/divgt; lt;/divgt; lt;/headergt; ); };