Функция onClick в Map, выполняется только для одного элемента

Есть ли способ, чтобы функция карты выполняла раскрывающееся меню только для одной корзины. Сейчас, если я нажму на один значок меню, каждое раскрывающееся меню появится для каждой карты на карте.

 const [isOpen, setIsOpen] = useState(false);
  {albums.map((album, i) => (
        <Card width = "23rem" height = "16rem" bckImg = {album.bckImgUrl} key = {i}>
          <AlbumtTitle color = {album.color}>{album.name}</AlbumtTitle>
          <LinkButton background = {album.color} to = {`/albums/${album._id}`}>
            See more
          </LinkButton>
          <KebabMenu onClick = {() => setIsOpen(!isOpen)} open = {isOpen}>
            {isOpen ? (
              <Dropdown
                ref = {ref}
                style = {{
                  width: "50px",
                  height: "50px",
                }}
              >
                <li>
                  <Link to = {`editAlbum/${album._id}`}>Edit</Link>
                </li>
                <hr />
                <li>Delete</li>
              </Dropdown>
            ) : (
              <Dots />
            )}
          </KebabMenu>
        </Card>
      ))}

Вы должны хранить состояние isOpen для каждого раскрывающегося списка отдельно. В настоящее время одно состояние isOpen управляет всеми выпадающими списками одновременно.

Vladimir Bogomolov 20.12.2020 22:44

Как хранить отдельно?

Kuba Kluzniak 20.12.2020 22:46
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Раскрытие чувствительных данных
Раскрытие чувствительных данных
Все внешние компоненты, рассмотренные здесь до сих пор, взаимодействуют с клиентской стороной. Однако, если они подвергаются атаке, они не...
Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Руководство ChatGPT по продаже мини JS-файлов
Руководство ChatGPT по продаже мини JS-файлов
JS-файл - это файл, содержащий код JavaScript. JavaScript - это язык программирования, который в основном используется для добавления интерактивности...
2
2
541
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ваше состояние isOpen может быть объектом, который отслеживает открытое состояние для каждого элемента в альбоме:

const [isOpen, setIsOpen] = useState({});

{albums.map((album, i) => (
    <Card width = "23rem" height = "16rem" bckImg = {album.bckImgUrl} key = {i}>
      <AlbumtTitle color = {album.color}>{album.name}</AlbumtTitle>
      <LinkButton background = {album.color} to = {`/albums/${album._id}`}>
        See more
      </LinkButton>
      <KebabMenu
        onClick = {() =>
          setIsOpen({ ...isOpen, [album._id]: !isOpen[album._id] })
        }
        open = {!!isOpen[album._id]}
      >
        {isOpen[album._id] ? (
          <Dropdown
            ref = {ref}
            style = {{
              width: "50px",
              height: "50px",
            }}
          >
            <li>
              <Link to = {`editAlbum/${album._id}`}>Edit</Link>
            </li>
            <hr />
            <li>Delete</li>
          </Dropdown>
        ) : (
          <Dots />
        )}
      </KebabMenu>
    </Card>
  ))}

Хорошо ли, что я изменил вашу константу [isOpen, setIsOpen] = useState ({}); в const [isOpen, setIsOpen] = useState(false);. Я сделал это, потому что он устанавливает состояние при втором щелчке, не замечая этого.

Kuba Kluzniak 20.12.2020 22:54

Это не сработает; это должен быть объект, потому что для каждого Album_id должно быть логическое значение.

Nick 20.12.2020 22:55

@KubaKluzniak это будет работать и игнорировать значение по умолчанию, но это не очень хорошая практика, просто поставьте {} вместо логического значения в качестве начального значения

EugenSunic 20.12.2020 23:00

Хорошо. i Измените его на это: useState({ id: undefined, state: false }); setIsOpen({ [album._id]: !isOpen[album._id] })} и все работает нормально

Kuba Kluzniak 20.12.2020 23:32

Не уверен, почему вы пытаетесь установить такое состояние по умолчанию. Это все еще не репрезентативно того, как это будет выглядеть. В конечном итоге состояние будет выглядеть как {1: true, 2: false, 3: false} и т. д. (при условии, что идентификаторы альбомов равны 1, 2 и 3).

Nick 20.12.2020 23:33

@Nick, потому что при первом щелчке в раскрывающемся списке, когда sate является пустым объектом, сначала ничего не происходит, он начинает работать при втором щелчке.

Kuba Kluzniak 20.12.2020 23:58

Вместо

 {albums.map((album, i) => (...your code...))}

Нужно проверить, есть ли у вас хоть один элемент в альбомах, и если да, то обработать его:

{if (albums.length > 0) {
   return albums.slice(0,1).map((album, i) => (...your code...))
 } else {
   return null // or any other actions you want to take in case there are no albums
 }
}

Для уточнения проверяем длину альбомов, если она не пустая. Если это так, мы берем только первый элемент и обрабатываем его.

Спасибо за предложение, я добавлю это.

Kuba Kluzniak 20.12.2020 22:56

@kuba-kluzniak, пожалуйста, проголосуйте за мой ответ, если он вам помог :)

IvanD 21.12.2020 04:18

Другие вопросы по теме