0

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

但它不起作用并出现错误“错误:重新渲染过多。React 限制渲染次数以防止无限循环”

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

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

4

1 回答 1

3

第一个错误: 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>

于 2020-04-03T09:03:08.600 回答