I'm trying to get Material-UI Breadcrumbs to work with React-Router. There is an example on the MUI site:
import * as React from 'react';
import Box from '@mui/material/Box';
import List from '@mui/material/List';
import Link, { LinkProps } from '@mui/material/Link';
import ListItem, { ListItemProps } from '@mui/material/ListItem';
import Collapse from '@mui/material/Collapse';
import ListItemText from '@mui/material/ListItemText';
import Typography from '@mui/material/Typography';
import ExpandLess from '@mui/icons-material/ExpandLess';
import ExpandMore from '@mui/icons-material/ExpandMore';
import Breadcrumbs from '@mui/material/Breadcrumbs';
import { Link as RouterLink, Route, MemoryRouter } from 'react-router-dom';
interface ListItemLinkProps extends ListItemProps {
to: string;
open?: boolean;
}
const breadcrumbNameMap: { [key: string]: string } = {
'/inbox': 'Inbox',
'/inbox/important': 'Important',
'/trash': 'Trash',
'/spam': 'Spam',
'/drafts': 'Drafts',
};
function ListItemLink(props: ListItemLinkProps) {
const { to, open, ...other } = props;
const primary = breadcrumbNameMap[to];
let icon = null;
if (open != null) {
icon = open ? <ExpandLess /> : <ExpandMore />;
}
return (
<li>
<ListItem button component={RouterLink as any} to={to} {...other}>
<ListItemText primary={primary} />
{icon}
</ListItem>
</li>
);
}
interface LinkRouterProps extends LinkProps {
to: string;
replace?: boolean;
}
const LinkRouter = (props: LinkRouterProps) => (
<Link {...props} component={RouterLink as any} />
);
export default function RouterBreadcrumbs() {
const [open, setOpen] = React.useState(true);
const handleClick = () => {
setOpen((prevOpen) => !prevOpen);
};
return (
<MemoryRouter initialEntries={['/inbox']} initialIndex={0}>
<Box sx={{ display: 'flex', flexDirection: 'column', width: 360 }}>
<Route>
{({ location }) => {
const pathnames = location.pathname.split('/').filter((x) => x);
return (
<Breadcrumbs aria-label="breadcrumb">
<LinkRouter underline="hover" color="inherit" to="/">
Home
</LinkRouter>
{pathnames.map((value, index) => {
const last = index === pathnames.length - 1;
const to = `/${pathnames.slice(0, index + 1).join('/')}`;
return last ? (
<Typography color="text.primary" key={to}>
{breadcrumbNameMap[to]}
</Typography>
) : (
<LinkRouter underline="hover" color="inherit" to={to} key={to}>
{breadcrumbNameMap[to]}
</LinkRouter>
);
})}
</Breadcrumbs>
);
}}
</Route>
<Box
sx={{
bgcolor: 'background.paper',
mt: 1,
}}
component="nav"
aria-label="mailbox folders"
>
<List>
<ListItemLink to="/inbox" open={open} onClick={handleClick} />
<Collapse component="li" in={open} timeout="auto" unmountOnExit>
<List disablePadding>
<ListItemLink sx={{ pl: 4 }} to="/inbox/important" />
</List>
</Collapse>
<ListItemLink to="/trash" />
<ListItemLink to="/spam" />
</List>
</Box>
</Box>
</MemoryRouter>
);
}
But this line:
{({ location }) => {
produces error
Type '({ location }: { location: any; }) => Element' is not assignable to type 'ReactNode'
and this line:
{pathnames.map((value, index) => {
produces error:
'value' is declared but its value is never read.ts(6133) Parameter 'value' implicitly has an 'any' type.
and:
Parameter 'index' implicitly has an 'any' type.
I've investigated similar questions, but either they have the same problem or don't work either. The problems seem to be attributed to out-of-date code.
Can anyone provide a modern solution that works?
valueisn't used so that second issue makes sense. What version of React-Router-DOM are you trying to use? It looks like an older v5 version based on usage. Can you edit to include a complete minimal reproducible example and specify your dependencies' versions. See also if you can create a running CodeSandbox demo that reproduces the issue that readers can inspect live.