React-Bootstrap 悬停时打开下拉菜单

React-Bootstrap Open dropdowns menu when hovering

我是 ReactJS 的新手,并且是 React-bootstrap。我的目标是在用户悬停(鼠标悬停)时打开一个下拉菜单。我已经搜索过了,但没有用。 我的解决方案是使用反应钩子来存储和更新数组中 "hoverItem" 的当前状态是真还是假(因为我有 2 个下拉菜单。不仅是 1 个)。

但是没有成功,报错"Error: Too many re-renders. React limits the number of renders to prevent an infinite loop"

<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);
};

这个问题的重点是我不知道如何更新(修改)数组中的元素状态。请告诉我怎么做。谢谢你,很抱歉给我带来的不便英语。

第一个错误: onMouseEnteronMouseLeave 需要函数声明而不是调用,因为你调用 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>