我有带有按钮的侧边栏,当我单击一个按钮时,我想在选定的按钮上设置颜色,但它无法正常工作,因为有时需要单击两次才能设置颜色,我不知道为什么。当我设置 setSelectedIndex(1) 但在 console.log(selectedIndex) 中显示 0
import { Drawer, List, ListItem, ListItemButton, ListItemText, styled, Toolbar } from '@mui/material'
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom';
import { sideItems } from './SideItems';
const Sidebar: React.FC = () => {
const drawerWidth = 240;
const navigate = useNavigate();
const [selectedIndex, setSelectedIndex] = useState(0);
const StyledListText = styled(ListItemText)({
textAlign: 'center',
color: 'white'
});
const CustomListButton = styled(ListItemButton)({
"&.Mui-selected": {
backgroundColor: "#2e8b57!important"
}
});
const handleListItemClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>, path: string, index: number) => {
event.preventDefault();
navigate(path);
setSelectedIndex(index);
}
return (
<Drawer
variant="permanent"
sx={{
width: drawerWidth,
[`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: 'border-box' }
}}
PaperProps={{
elevation: 12,
sx: {
width: 240,
backgroundColor: "primary.light"
}
}}
>
<Toolbar />
<List>
{sideItems.map((item, index) =>
<ListItem key={item.id}>
<CustomListButton selected={index === selectedIndex} onClick={(event) => handleListItemClick(event, item.path, index)}>
<StyledListText primary={item.text} />
</CustomListButton>
</ListItem>
)}
</List>
</Drawer>
)
}
export default Sidebar
最有可能的是,您将
<Sidebar/>
作为子组件包含在每个页面组件的 jsx 中,因此每次您创建它的新实例时,由于初始 selectedIndex
值为 0,因此它始终是选择的第一个项目无论您使用 navigate
重定向到哪个页面组件,除非您单击另一个按钮来更新此新 selectedIndex
实例的 Sidebar
值。
您应该如何在顶层使用
<Sidebar/>
来创建它的一个实例,这样它就不会丢失它的 hooks
值,如下所示:
function Layout(props) {
return (
<Fragment>
<Siderbar/>
<main>{props.children}</main>
</Fragment>
);
}
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<Component {...pageProps} />
</Layout>
);
你可以更好地写你的问题:
import { useNavigate } from 'react-router-dom';
import { sideItems } from './SideItems';
const sideItems = [
{
id: '1',
text: 'lalala',
path: 'lololo'
}
]
解决方案:
(改变你的琴弦)
const [selectedIndex, setSelectedIndex] = useState(true);
const handleListItemClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>, path: string, index: number) => {
event.preventDefault();
setSelectedIndex(!selectedIndex);
}
<CustomListButton selected={selectedIndex} onClick={(event) => handleListItemClick(event, item.path, index)}>
(改变你的琴弦)
const [selectedIndex, setSelectedIndex] = useState(0);
const handleListItemClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>, path: string, index: number) => {
event.preventDefault();
setSelectedIndex((prev) => {
return prev ? 0 : 1
});
}
<CustomListButton selected={!!selectedIndex} onClick={(event) => handleListItemClick(event, item.path, index)}>
谢谢你们的帮助,我找到了适合我的案例的解决方案 我添加了
import { Link } from 'react-router-dom';
休息看起来像
{sideItems.map((item) =>
<ListItemButton sx={{
"&.Mui-selected": {
backgroundColor: "#2e8b57!important"
}
}} key={item.id} component={Link} to={item.path} selected={location.pathname === item.path}>
<StyledListText primary={item.text} />
</ListItemButton>
)}
这会起作用。基本上,selected 属性告诉“&.Mui-selected”它是选定的。我将 selectedIndex 设置为 -1,因此没有选择任何内容。当调用 onClick 时,我将 selectedIndex 更新为所选行。在 ListItemButton 小部件中,仅当 {props.index === props.onSelectedIndex} 时,selected 才会设置为 true。当选择新的 ListItemButton 时,它的选择设置为 true,而旧的 ListItemButton 现在设置为 false。至于“&.Mui-selected”,它将选定的ListItemButton更改为新的背景颜色红色。使用默认的黑色字体,如果人们认为在代码审查后很难阅读红底黑字,我可能会将其更改为白色等颜色。
在功能 Row 中我添加了一个列表行,重要的部分是 sx 设置和 selected= 行。
function Row(props) {
return (
<ListItem disablePadding>
<ListItemButton
sx={{
height: '1.5rem',
border: 1,
"&.Mui-selected": {
backgroundColor: "red",
},
"&.Mui-focusVisible": {
backgroundColor: "#2e8b57",
color: 'white',
},
":hover": {
backgroundColor: "#2e8b57",
color: 'white',
}
}}
onClick={(e) => props.onClick(e, props.index, props.data["name"], props.data["id"])}
selected={props.index === props.onSelectedIndex}
>
<ListItemText primary={props.data["name"]}/>
</ListItemButton>
</ListItem>
);
}
这是主要功能部分:
const [selectedIndex, setSelectedIndex] = useState(-1);
const selectedSnapShot = (e, index, name, id) => {
e.preventDefault();
setSelectedIndex(index);
}
现在调用 Row 将项目添加到列表中
{
data && data['snapshotList'].map((item, index) => {
return (<Row key={"s" + index} data={item} index={index} onClick={selectedSnapShot} onSelectedIndex={selectedIndex}/>)
})
}
当您将鼠标悬停在一条线上时,它的颜色会更改为绿底白字,当您选择一条线时,颜色会永久更改为红底黑字。