在材料 UI 中更改选定项的颜色按钮事件。

huangapple go评论72阅读模式
英文:

Change selected item color in material ui list button event

问题

I have sidebar with buttons, when i click on one i want to set color on selected button but it doesn't work properly because sometimes it requires clicking twice to set the color i don't know why. When i set setSelectedIndex(1) but in console.log(selectedIndex) shows 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;
英文:

I have sidebar with buttons, when i click on one i want to set color on selected button but it doesn't work properly because sometimes it requires clicking twice to set the color i don't know why. When i set setSelectedIndex(1) but in console.log(selectedIndex) shows 0

import { Drawer, List, ListItem, ListItemButton, ListItemText, styled, Toolbar } from &#39;@mui/material&#39;
import React, { useState } from &#39;react&#39;
import { useNavigate } from &#39;react-router-dom&#39;;
import { sideItems } from &#39;./SideItems&#39;;
const Sidebar: React.FC = () =&gt; {
const drawerWidth = 240;
const navigate = useNavigate();
const [selectedIndex, setSelectedIndex] = useState(0);
const StyledListText = styled(ListItemText)({
textAlign: &#39;center&#39;,
color: &#39;white&#39;
});
const CustomListButton = styled(ListItemButton)({
&quot;&amp;.Mui-selected&quot;: {
backgroundColor: &quot;#2e8b57!important&quot;
}
});
const handleListItemClick = (event: React.MouseEvent&lt;HTMLDivElement, MouseEvent&gt;, path: string, index: number) =&gt; {
event.preventDefault();
navigate(path);
setSelectedIndex(index);
}
return (
&lt;Drawer
variant=&quot;permanent&quot;
sx={{
width: drawerWidth,
[`&amp; .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: &#39;border-box&#39; }
}}
PaperProps={{
elevation: 12,
sx: {
width: 240,
backgroundColor: &quot;primary.light&quot;
}
}}
&gt;
&lt;Toolbar /&gt;
&lt;List&gt;
{sideItems.map((item, index) =&gt;
&lt;ListItem key={item.id}&gt;
&lt;CustomListButton selected={index === selectedIndex} onClick={(event) =&gt; handleListItemClick(event, item.path, index)}&gt;
&lt;StyledListText primary={item.text} /&gt;
&lt;/CustomListButton&gt;
&lt;/ListItem&gt;
)}
&lt;/List&gt;
&lt;/Drawer&gt;
)
}
export default Sidebar

答案1

得分: 1

大多数情况下,您正在将 &lt;Sidebar/&gt; 作为子组件包含在每个页面组件的 JSX 中,因此每次都会创建一个新实例,而且由于初始的 selectedIndex 值为 0,所以无论您使用 navigate 被重定向到哪个页面组件,它始终选择的是第一个项目,除非您单击另一个按钮来更新新 Sidebar 实例的 selectedIndex 值。

您应该在顶层使用 &lt;Sidebar/&gt;,以便只创建一个实例,这样它就不会丢失其 hooks 值,类似于这样:

function Layout(props) {
  return (
    &lt;Fragment&gt;
      &lt;Sidebar/&gt;
      &lt;main&gt;{props.children}&lt;/main&gt;
    &lt;/Fragment&gt;
  );
}
function MyApp({ Component, pageProps }) {
  return (
    &lt;Layout&gt;
      &lt;Head&gt;
        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
      &lt;/Head&gt;
      &lt;Component {...pageProps} /&gt;
    &lt;/Layout&gt;
  );
}
英文:

Most likely here you are including &lt;Sidebar/&gt; as child component inside the jsx of every page component so each time you are creating a new instance of it and since the initial selectedIndex value is 0 it is always the first item which is selected no matter to which page component you have been redirected with navigate, unless you click on another button to update selectedIndex value of this new Sidebar instance.

What you should do it to use &lt;Sidebar/&gt; on the top level to create only one instance of it, so it does not lose it's hooks values something like this :

function Layout(props) {
return (
&lt;Fragment&gt;
&lt;Siderbar/&gt;
&lt;main&gt;{props.children}&lt;/main&gt;
&lt;/Fragment&gt;
);
}
function MyApp({ Component, pageProps }) {
return (
&lt;Layout&gt;
&lt;Head&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
&lt;/Head&gt;
&lt;Component {...pageProps} /&gt;
&lt;/Layout&gt;
);

答案2

得分: 1

Solutions:

  1. 你可以写一个布尔型的解决方案:
    (更改你的字符串)
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)}></CustomListButton>
  1. 你可以写一个数字型的解决方案:
    (更改你的字符串)
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)}></CustomListButton>
英文:

You can write your question better:

  1. Don't need write in this example:
import { useNavigate } from &#39;react-router-dom&#39;;
import { sideItems } from &#39;./SideItems&#39;;
  1. You must in example write const sideItems
const sideItems = [
{
id: &#39;1&#39;,
text: &#39;lalala&#39;,
path: &#39;lololo&#39;
}
]

Solutions:

  1. You can write solution - boolean:

(change your strings)

const [selectedIndex, setSelectedIndex] = useState(true);
const handleListItemClick = (event: React.MouseEvent&lt;HTMLDivElement, MouseEvent&gt;, path: string, index: number) =&gt; {
event.preventDefault();
setSelectedIndex(!selectedIndex);
}
&lt;CustomListButton selected={selectedIndex} onClick={(event) =&gt; handleListItemClick(event, item.path, index)}&gt;
  1. You can write solution - number:

(change your strings)

const [selectedIndex, setSelectedIndex] = useState(0);
const handleListItemClick = (event: React.MouseEvent&lt;HTMLDivElement, MouseEvent&gt;, path: string, index: number) =&gt; {
event.preventDefault();
setSelectedIndex((prev) =&gt; {
return prev ? 0 : 1
});
}
&lt;CustomListButton selected={!!selectedIndex} onClick={(event) =&gt; handleListItemClick(event, item.path, index)}&gt;

答案3

得分: 1

感谢各位的帮助,我找到了解决方法。
我添加了以下代码:

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>
)}
英文:

Thank, you guys for help I found solution for my case
I added

import { Link } from &#39;react-router-dom&#39;;

and rest looks like

{sideItems.map((item) =&gt;
    &lt;ListItemButton sx={{
        &quot;&amp;.Mui-selected&quot;: {
            backgroundColor: &quot;#2e8b57!important&quot;
        }
    }} key={item.id} component={Link} to={item.path} selected={location.pathname === item.path}&gt;
        &lt;StyledListText primary={item.text} /&gt;
    &lt;/ListItemButton&gt;
)}

huangapple
  • 本文由 发表于 2023年2月6日 03:07:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75354801.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定