React- Bootstrap Открыть выпадающее меню при наведении - PullRequest
0 голосов
/ 03 апреля 2020

Я новичок в ReactJS и реагирую - bootstrap. Моя цель - открыть выпадающее меню, когда пользователь наводит на него курсор мыши. Я уже искал, но это не сработало. Мое решение состоит в использовании реакционных хуков для хранения и обновления текущего состояния "hoverItem" в массиве "true" или "false" (поскольку у меня есть 2 раскрывающихся меню. Не только 1).

Но это не сработало и выдает ошибку «Ошибка: слишком много повторных визуализаций. React ограничивает число визуализаций, чтобы предотвратить бесконечное l oop»

<NavDropdown onMouseEnter={handleOpen(index)} onMouseLeave={handleClose(index)} show={isOpen[index]} title={item.title} id={item.id} key={item.id}>
  {item.sub.map(element => { return (
  <NavDropdown.Item href={element.url} key={element.id} onClick={handleClose}>
    {element.item}
  </NavDropdown.Item>
  ); })}
</NavDropdown>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Состояние обновления:

const [isOpen, setIsOpen] = useState(() => {
  //create an array with n-element and set all elements to false 
    return Array.apply(null, Array(MENU.length)).map(x => false);
  });

const handleOpen = index => {
  let temp = isOpen;
  temp[index] = true;
  setIsOpen(temp);
};

const handleClose = index => {
  let temp = isOpen;
  temp[index] = false;
  setIsOpen(temp);
};

Суть этой проблемы в том, что я не знаю, как обновить (изменить) состояние элемента в массиве. Пожалуйста, скажите мне, как. Спасибо и извините за неудобства Engli sh.

1 Ответ

0 голосов
/ 03 апреля 2020

Первая ошибка: onMouseEnter и onMouseLeave ожидали объявления функции вместо вызова, потому что вы вызываете handleOpen(index), она перерисовывается, затем перерисовывается снова и так далее. .. чтобы исправить ошибку:

onMouseEnter={(e) => handleOpen(index)}

Вторая ошибка :

<NavDropdown.Item href={element.url} key={element.id} onClick={handleClose}>

это вызовет handleClose с событием, ожидаемым index, для исправления :

 onClick={e => handleClose(index) }

Третья ошибка : ваши handleClose и handleOpen обновляют состояние со ссылкой на старое состояние, ожидается новый массив, чтобы исправить:

const handleOpen = index => {
  let temp = [...isOpen];
  temp[index] = true;
  setIsOpen(temp);
};
const handleClose = index => {
  let temp = [...isOpen];
  temp[index] = false;
  setIsOpen(temp);
};

Кроме того, ваше isOpen имя неоднозначно, и неправильная инициализация тоже!

const [isOpen, setIsOpen] = useState(() => {
    return Array.apply(null, Array(MENU.length)).map(x => false);
});

должно быть

const [status, setStatus] = useState(MENU.map(x=> false));

В целом вы можете написать так:

const updateStatus = (value, index) => {
    const clone = [...status];
    clone[index] = value;
    setStatus(clone);
}
<NavDropdown
    onMouseEnter={e => updateStatus(true, index)}
    onMouseLeave={e => updateStatus(false, index)}
    show={status[index]}
    title={item.title}
    id={item.id}
    key={item.id}
>
    {item.sub.map(element =>
        <NavDropdown.Item
            href={element.url}
            key={element.id}
            onClick={e => updateStatus(false, index)}
        >
            {element.item}
        </NavDropdown.Item>
    )}
</NavDropdown>

...