H如何在 React 的映射组件上使用 menu 或 popover?
How to use menu or popover on mapping components in React?
我有一个可以自己创建菜单的功能,我想在这些菜单上使用弹出窗口,如下所示。
const popInitialPos = {
mouseX: null,
mouseY: null,
};
const [popState, setPopState] = React.useState<{
mouseX: null | number;
mouseY: null | number;
}>(popInitialPos);
const openPopCategory = (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
setPopState({
mouseX: event.clientX - 2,
mouseY: event.clientY - 4,
});
};
const closePopCategory = () => {
setPopState(popInitialPos);
};
//....some code
{categories?.map( (c)=>{
if( c.id>=5){
return(
<Link to={{pathname:"/list/"+c.id}} className={classes.linkItem} key={c.id}>
<div className={classes.item} onContextMenu={(e)=>openPopCategory(e)}>
<Dns className={classes.icon} />
<Typography className={classes.text}>{c.name}</Typography>
<Typography className={classes.text} style={{marginLeft:"auto"}}>
{todos.filter((todo)=>todo.categories?.includes(c.id)&&todo.completed===false).length ===0 ? null : todos.filter((todo)=>todo.categories?.includes(c.id)&&todo.completed===false).length }
</Typography>
<Menu
keepMounted
open={popState.mouseY !== null}
onClose={closePopCategory}
anchorReference="anchorPosition"
anchorPosition={
popState.mouseY !== null && popState.mouseX !== null
? { top: popState.mouseY, left: popState.mouseX }
: undefined
}
>
<MenuItem onClick={closePopCategory}>{c.name}</MenuItem>
</Menu>
</div>
</Link>
)
}
}
)}
所以在我这样做之后,当我右键单击组件时,不同列表之间的菜单项会相互重叠,我认为这是因为我使用相同的状态来控制菜单,但我想不出一种方法来创建多个状态或功能与 mapping ,我认为这也不是一个好方法。
如果您想将弹出窗口添加到映射组件,通常的方法是什么,因为它是由状态和功能控制的?
如果每个“映射的”反应节点都需要额外的状态,最简单的方法是将整个节点放入其自己的组件中。所以你会做一些事情:
categories?.map(c => <Category key={c.id} category={c} />)
然后在您的新组件中处理状态:
function Category({ category }) {
const [state, setState] = useState(...)
return <Link>
<Menu />
... etc
</Link>
}
我们可以为 MenuWithPopup 创建一个单独的组件,并将状态驻留在其中。这种创建 atomic state
的方式确保
每个菜单项都有一个单独的状态。
const popInitialPos = {
mouseX: null,
mouseY: null,
};
const MenuWithPopup = () => {
const [popState, setPopState] = React.useState<{
mouseX: null | number;
mouseY: null | number;
}>(popInitialPos);
const openPopCategory = (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
setPopState({
mouseX: event.clientX - 2,
mouseY: event.clientY - 4,
});
};
const closePopCategory = () => {
setPopState(popInitialPos);
};
return (
<Link
to={{pathname: '/list/' + c.id}}
className={classes.linkItem}
key={c.id}
>
<div className={classes.item} onContextMenu={(e) => openPopCategory(e)}>
<Dns className={classes.icon} />
<Typography className={classes.text}>{c.name}</Typography>
<Typography className={classes.text} style={{marginLeft: 'auto'}}>
{todos.filter(
(todo) =>
todo.categories?.includes(c.id) && todo.completed === false
).length === 0
? null
: todos.filter(
(todo) =>
todo.categories?.includes(c.id) && todo.completed === false
).length}
</Typography>
<Menu
keepMounted
open={popState.mouseY !== null}
onClose={closePopCategory}
anchorReference="anchorPosition"
anchorPosition={
popState.mouseY !== null && popState.mouseX !== null
? {top: popState.mouseY, left: popState.mouseX}
: undefined
}
>
<MenuItem onClick={closePopCategory}>{c.name}</MenuItem>
</Menu>
</div>
</Link>
);
};
现在我们可以在地图中使用这个组件了
{
categories?.map((c) => {
if (c.id >= 5) {
return <MenuItemWithPopup {pass the necessary props here} />;
}
});
}
我有一个可以自己创建菜单的功能,我想在这些菜单上使用弹出窗口,如下所示。
const popInitialPos = {
mouseX: null,
mouseY: null,
};
const [popState, setPopState] = React.useState<{
mouseX: null | number;
mouseY: null | number;
}>(popInitialPos);
const openPopCategory = (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
setPopState({
mouseX: event.clientX - 2,
mouseY: event.clientY - 4,
});
};
const closePopCategory = () => {
setPopState(popInitialPos);
};
//....some code
{categories?.map( (c)=>{
if( c.id>=5){
return(
<Link to={{pathname:"/list/"+c.id}} className={classes.linkItem} key={c.id}>
<div className={classes.item} onContextMenu={(e)=>openPopCategory(e)}>
<Dns className={classes.icon} />
<Typography className={classes.text}>{c.name}</Typography>
<Typography className={classes.text} style={{marginLeft:"auto"}}>
{todos.filter((todo)=>todo.categories?.includes(c.id)&&todo.completed===false).length ===0 ? null : todos.filter((todo)=>todo.categories?.includes(c.id)&&todo.completed===false).length }
</Typography>
<Menu
keepMounted
open={popState.mouseY !== null}
onClose={closePopCategory}
anchorReference="anchorPosition"
anchorPosition={
popState.mouseY !== null && popState.mouseX !== null
? { top: popState.mouseY, left: popState.mouseX }
: undefined
}
>
<MenuItem onClick={closePopCategory}>{c.name}</MenuItem>
</Menu>
</div>
</Link>
)
}
}
)}
所以在我这样做之后,当我右键单击组件时,不同列表之间的菜单项会相互重叠,我认为这是因为我使用相同的状态来控制菜单,但我想不出一种方法来创建多个状态或功能与 mapping ,我认为这也不是一个好方法。 如果您想将弹出窗口添加到映射组件,通常的方法是什么,因为它是由状态和功能控制的?
如果每个“映射的”反应节点都需要额外的状态,最简单的方法是将整个节点放入其自己的组件中。所以你会做一些事情:
categories?.map(c => <Category key={c.id} category={c} />)
然后在您的新组件中处理状态:
function Category({ category }) {
const [state, setState] = useState(...)
return <Link>
<Menu />
... etc
</Link>
}
我们可以为 MenuWithPopup 创建一个单独的组件,并将状态驻留在其中。这种创建 atomic state
的方式确保
每个菜单项都有一个单独的状态。
const popInitialPos = {
mouseX: null,
mouseY: null,
};
const MenuWithPopup = () => {
const [popState, setPopState] = React.useState<{
mouseX: null | number;
mouseY: null | number;
}>(popInitialPos);
const openPopCategory = (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
setPopState({
mouseX: event.clientX - 2,
mouseY: event.clientY - 4,
});
};
const closePopCategory = () => {
setPopState(popInitialPos);
};
return (
<Link
to={{pathname: '/list/' + c.id}}
className={classes.linkItem}
key={c.id}
>
<div className={classes.item} onContextMenu={(e) => openPopCategory(e)}>
<Dns className={classes.icon} />
<Typography className={classes.text}>{c.name}</Typography>
<Typography className={classes.text} style={{marginLeft: 'auto'}}>
{todos.filter(
(todo) =>
todo.categories?.includes(c.id) && todo.completed === false
).length === 0
? null
: todos.filter(
(todo) =>
todo.categories?.includes(c.id) && todo.completed === false
).length}
</Typography>
<Menu
keepMounted
open={popState.mouseY !== null}
onClose={closePopCategory}
anchorReference="anchorPosition"
anchorPosition={
popState.mouseY !== null && popState.mouseX !== null
? {top: popState.mouseY, left: popState.mouseX}
: undefined
}
>
<MenuItem onClick={closePopCategory}>{c.name}</MenuItem>
</Menu>
</div>
</Link>
);
};
现在我们可以在地图中使用这个组件了
{
categories?.map((c) => {
if (c.id >= 5) {
return <MenuItemWithPopup {pass the necessary props here} />;
}
});
}