Навигационное меню с реакцией - PullRequest
1 голос
/ 05 августа 2020

У меня есть навигационное меню, и я хочу запустить функцию для элемента списка, который я нажимаю, чтобы открыть подменю. Сейчас происходит то, что я нажимаю на элемент, и отображаются все подменю. Я заставил его работать, прежде чем использовать отдельные значения для каждого подменю, хотя мне было интересно, могу ли я заставить его работать с одной функцией, а не копировать и вставлять ту же самую 2 больше раз. Есть предложения, ребята? Вот мой код

import React, { useEffect } from "react";
import { useImmer } from "use-immer";

// Submenu component
import Submenu from "./Submenu";

function Navbar() {
  const [state, setState] = useImmer({
    menu: false
  });
  /*
  return function menu(sub) {
    setState(draft => {
      draft.sub = !draft.sub;
    });
  };
  */

  function handleSubMenu(e) {
    e.preventDefault();
    setState(draft => {
      draft.menu = !draft.menu;
    });
  }

  return (
    <>
      <li className="navbar-main__item navbar-main__item--1">
        <a onClick={handleSubMenu} href="#" className=" navbar-main__link">
          <span>List item 1</span>{" "}
          <svg
            className={
              state.menu
                ? "navbar-main__icon  navbar-main__icon--rotate-down"
                : "navbar-main__icon  navbar-main__icon--rotate"
            }
          >
            <use href="img/sprite.svg#icon-chevron-thin-down" />
          </svg>
        </a>

        <Submenu
          subfirst="Item 1"
          subsecond="Item 2"
          subthird="Meat 3"
          state={state.menu}
        />
      </li>

      <li className="navbar-main__item navbar-main__item--2">
        <a onClick={handleSubMenu} data-id="1" href="#" className="navbar-main__link">
          <span>List Item 2</span>{" "}
          <svg
            className={
              state.menu
                ? "navbar-main__icon  navbar-main__icon--rotate-down"
                : "navbar-main__icon  navbar-main__icon--rotate"
            }
          >
            <use href="img/sprite.svg#icon-chevron-thin-down" />
          </svg>
        </a>

        <Submenu
          subfirst="Item 1"
          subsecond="Item 2"
          subthird="Item 3"
          state={state.menu}
        />
      </li>

      <li className="navbar-main__item navbar-main__item--3">
        <a onClick={handleSubMenu} href="#" className="navbar-main__link">
          <span>List Item 3</span>{" "}
          <svg
            className={
              state.menu
                ? "navbar-main__icon  navbar-main__icon--rotate-down"
                : "navbar-main__icon  navbar-main__icon--rotate"
            }
          >
            <use href="img/sprite.svg#icon-chevron-thin-down" />
          </svg>
        </a>
        <Submenu
          subfirst="Item 1"
          subsecond="Item 2"
          subthird="Item 3"
          state={state.menu}
        />
      </li>
     </>
    );
}

export default Navbar;

1 Ответ

0 голосов
/ 11 августа 2020

Чтобы повторно использовать одну и ту же функцию для каждого, вам придется изменить то, что вы храните в состоянии. menu - логическое значение, поэтому может иметь только одно из двух значений. Однако, если вы храните уникальный идентификатор для каждого подменю, вы можете изменить, если подменю открыто на основе этого. Например, если у каждого подменю был идентификатор, и вы сохранили этот идентификатор в состоянии, вы можете сравнить этот идентификатор с идентификатором подменю и передать true / false, если оно открыто или нет.

Есть несколько других улучшения, которые вы можете внести в этот компонент, чтобы сделать его менее повторяющимся. Существует много дублирования, которое можно упростить.

import React from "react";
import { useImmer } from "use-immer";
import Submenu from "./Submenu";

const menuItems = [
  {
    id: 'menu1',
    subfirst: "Item 1",
    subsecond: "Item 2",
    subthird: "Meat 3",
  },
  {
    id: 'menu2',
    subfirst: "Item 1",
    subsecond: "Item 2",
    subthird: "Item 3",
  },
  {
    id: 'menu3',
    subfirst: "Item 1",
    subsecond: "Item 2",
    subthird: "Item 3",
  },
];

function Navbar() {
  const [state, setState] = useImmer({ openMenuId: undefined });

  function openSubMenu(menuId) {
    e.preventDefault();
    setState(draft => {
      draft.openMenuId = menuId;
    });
  }

  return (
    <ul style={{ listStyle: 'none' }}>
      {menuItems.map((menuItem, index) => (
        <li className={`navbar-main__item navbar-main__item--${index}`}>
          <a onClick={() => openSubMenu(menuItem.id)} href="#" className="navbar-main__link">
            <span>List item {index}</span>
            <svg
              className={`navbar-main__icon  navbar-main__icon--rotate${state.openMenuId === menuItem.id ? '-down' : ''}`}
            >
              <use href="img/sprite.svg#icon-chevron-thin-down" />
            </svg>
          </a>
          <Submenu
            subfirst={menuItem.subfirst}
            subsecond={menuItem.subsecond}
            subthird={menuItem.subthird}
            isOpen={state.openMenuId === menuItem.id}
          />
        </li>
      ))}
    </ul>
  );
}

export default Navbar;

Это был всего лишь быстрый переход. useImmer, вероятно, будет излишним для этого случая, если вы не планируете добавлять что-то еще в состояние.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...