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);
};
这个问题的重点是我不知道如何更新(修改)数组中的元素状态。请告诉我怎么做。谢谢你,很抱歉给我带来的不便英语。
第一个错误: 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>
我是 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);
};
这个问题的重点是我不知道如何更新(修改)数组中的元素状态。请告诉我怎么做。谢谢你,很抱歉给我带来的不便英语。
第一个错误: 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>