I have a problem using MUI with react-router-dom v6.
import ListItem from '@mui/material/ListItem';
import { NavLink } from 'react-router-dom';
<List key={index}>
<ListItem
component={NavLink}
sx={{
color: '#8C8C8C',
}}
to={'/home'}
className={({ isActive }) => (isActive ? classes.activeLink : undefined)
>
<ListItemIcon></ListItemIcon>
<ListItemText primary='Home'/>
</ListItem>
</List>
className
not working and show error:
No overload matches this call.
The last overload gave the following error.
Type '({ isActive }: { isActive: any; }) => boolean' is not assignable to type 'string'
The expected type comes from property 'className' which is declared here on type 'IntrinsicAttributes & { button?: false | undefined; } & ListItemBaseProps & { components?: { Root?: ElementType<any> | undefined; } | undefined; componentsProps?: { ...; } | undefined; } & CommonProps & Omit<...>'
The issue is that the className
prop is for the ListItem
, not the component you've specified to be rendered. It's not an extraneous prop and isn't passed along to the NavLink
component.
The solution appears to be to create a custom navlink component with the dynamic className
prop enclosed. Pass your dynamic className
function on a different prop, say activeClassName
, and pass this to the NavLink
's className
prop internally.
Example:
import { NavLink as NavLinkBase } from 'react-router-dom';
const NavLink = React.forwardRef((props, ref) => (
<NavLinkBase
ref={ref}
{...props}
className={props.activeClassName}
/>
));
...
import ListItem from '@mui/material/ListItem';
import { NavLink } from '../path/to/NavLink';
...
<List key={index}>
<ListItem
component={NavLink}
activeClassName={({ isActive }) =>
isActive ? classes.activeLink : undefined
}
sx={{ color: '#8C8C8C' }}
to="/home"
>
<ListItemIcon></ListItemIcon>
<ListItemText primary='Home' />
</ListItem>
</List>
Thanks all, and here is my solution
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemIcon from '@mui/material/ListItemIcon';
import ListItemText from '@mui/material/ListItemText';
import { Theme } from '@mui/material/styles';
import { createStyles, makeStyles } from '@mui/styles';
import React from 'react';
import { NavLink } from 'react-router-dom';
const MyNavLink = React.forwardRef<any, any>((props, ref) => (
<NavLink
ref={ref}
to={props.to}
className={({ isActive }) => `${props.className} ${isActive ? props.activeClassName : ''}`}
>
{props.children}
</NavLink>
));
const useStyles = makeStyles((theme: Theme) =>
createStyles({
activeLink: {
backgroundColor: '#19ABC0',
color: '#FFFFFF',
borderRadius: 8,
'& .MuiSvgIcon-root': {
color: '#FFFFFF',
stroke: '#FFFFFF',
fill: '#19ABC0',
},
},
})
);
function Sidebar() {
const classes = useStyles();
return (
<>
<List>
<ListItem
component={MyNavLink}
sx={{
color: '#8C8C8C',
}}
to={'/home'}
activeClassName={classes.activeLink}
>
<ListItemIcon sx={{ stroke: '#8C8C8C', fill: '#FFFFFF' }}></ListItemIcon>
<ListItemText primary={'Home'} />
</ListItem>
</List>
<List>
<ListItem
component={MyNavLink}
sx={{
color: '#8C8C8C',
}}
to={'/dashboard'}
activeClassName={classes.activeLink}
>
<ListItemIcon sx={{ stroke: '#8C8C8C', fill: '#FFFFFF' }}></ListItemIcon>
<ListItemText primary={'Dashboard'} />
</ListItem>
</List>
</>
);
}
className={({ isActive }) => `${props.className} ${isActive ? props.activeClassName : ''}`}
To use MUI's className and add NavLink's active class.
The className property in a ListItem can only accept a string However on a NavLink, you can define a function that has its state (active or inactive)
You can create a CustomNavLink component that gets the properties from the ListItemButton (using forwardRef) and also have different styles based on its state
If you want to preserve the styling of mui's ListItemButton make sure you add its appropriate mui css classname to the className property of the NavLink. You can then add the different styling classes for whether it's active or not.
const CustomNavLink = forwardRef((props, ref) => (
<NavLink
ref={ref}
{...props}
className={({ isActive }) => (isActive ? props.className + ' Mui-selected' : props.className)}
end
/>
));
Make sure you use the CustomNavLink as the component for ListItemButton and add the to property which will be forwarded to the NavLink
<List>
<ListItem>
<ListItemButton
component={CustomNavLink}
to="/"
>
<ListItemIcon><ListIcon /></ListItemIcon>
<ListItemText primary='Home' />
</ListItemButton>
</ListItem>
</List>
It's bothering me this couple of days.. and what I found to be the least complicated solution is to add;important. to the CSS of .active
<Button component={NavLink} to="/home"> Home </Button>
.active { color: #F07DEA;important; }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.