admin管理员组文章数量:1278786
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?
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?
Share Improve this question edited Feb 24 at 20:53 Drew Reese 203k17 gold badges239 silver badges270 bronze badges asked Feb 24 at 20:31 user3217883user3217883 1,4827 gold badges48 silver badges80 bronze badges 2 |1 Answer
Reset to default 1If you are using React-Router 6 or newer then your code is missing a Routes
component wrapping any/all Route
components, and Route
components can only have React.Fragment
and other Route
components as children. When I copy your code into a running sandbox and get all the dependencies set I see the expected errors about the invalid components usage.
You should refactor the anonymous function into a standalone React component.
Create a new component, i.e. BreadcrumbsComponent
, and use the useLocation
hook to access the current location
value.
const BreadcrumbsComponent = () => {
const { pathname } = useLocation();
const pathnames = pathname.split("/").filter((segment) => segment);
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>
);
};
You could render BreadcrumbsComponent
on a pathless route like <Route element=<BreadcrumbsComponent />} />
but this is pointless, you can simply render BreadcrumbsComponent
directly within the MemoryRouter
.
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 }}>
<BreadcrumbsComponent />
<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>
);
}
本文标签: reactjsMUI Breadcrumb Integration with reactrouterStack Overflow
版权声明:本文标题:reactjs - MUI Breadcrumb Integration with react-router - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741243102a2364363.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
value
isn'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. – Drew Reese Commented Feb 24 at 20:52