我正在尝试将Material-UI面包屑与react-router一起使用。如何以编程方式检测当前路线。
在Material-UI网站上有一个有关如何使用它的示例,但是它需要使用静态的BreadcrumbNameMap。我已经尝试使用HOC“ withRouter”拆分路径名,但是它不起作用。
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Breadcrumbs, Link, Paper, Typography} from "@material-ui/core";
import { withRouter } from "react-router-dom";
import { useTranslation } from "../Translate";
const useStyles = makeStyles(theme => ({
root: {
justifyContent: "center",
flexWrap: "wrap",
},
paper: {
padding: theme.spacing(1, 2),
},
}));
const breadcrumbNameMap = {
"/inbox": "Inbox",
"/inbox/important": "Important",
"/trash": "Trash",
"/spam": "Spam",
"/drafts": "Drafts",
};
function SimpleBreadcrumbs(props) {
const classes = useStyles();
console.log("Breadcrumbs", props);
const { location } = props;
const pathnames = location.pathname.split("/").filter(x => x);
console.log("pathnames", pathnames);
return (
<div className={classes.root}>
<Paper elevation={0} className={classes.paper}>
<Breadcrumbs aria-label="Breadcrumb">
<Link color="inherit" href="/">
Home
</Link>
{pathnames.map((value, index) => {
const last = index === pathnames.length - 1;
const to = `/${pathnames
.slice(0, index + 1)
.join("/")}`;
console.log("last", last, "to", to);
const path = value.split("-");
console.log("path", path);
// Convert first char of string to uppercase
path.forEach((item, i) => {
// Only capitalize starting from the second element
if (i > 0) {
path[i] =
path[i].charAt(0).toUpperCase() +
path[i].slice(1);
}
});
// return (
// <Typography color="textPrimary" key={to}>
// {useTranslation(path.join(""))}
// </Typography>
// );
// // return (
// // <Typography color="textPrimary" key={to}>
// // {pathnames[to]}
// // </Typography>
// // );
return last ? (
<Typography color="textPrimary" key={to}>
{breadcrumbNameMap[to]}
</Typography>
) : (
<Link color="inherit" to={to} key={to}>
{useTranslation(path.join(""))}
</Link>
);
})}
</Breadcrumbs>
</Paper>
</div>
);
}
export default withRouter(SimpleBreadcrumbs);
如果浏览器中的URL指向“ http://example.com/level1/level2”,则我希望面包屑的输出为:
首页/ 1级/ 2级
如果浏览器中的URL为“ http://example.com/level1/”,我希望:
首页/ 1级
翻译也可以在以后添加。我包括它是为了显示最终的预期结果。
答案 0 :(得分:1)
仅当面包屑上的标签不同时,才需要面包屑名称映射,然后链接URL(例如,路径“ / level1”在面包屑中显示为“级别1”。
这里是与React Router集成的Material UI Breadcrumb示例的修改版本。
在这里尝试完整的程序 https://codesandbox.io/s/dark-architecture-sgl12?fontsize=14
https://sgl12.codesandbox.io/level1/level2
import React from 'react';
import Breadcrumbs from '@material-ui/core/Breadcrumbs';
import Typography from '@material-ui/core/Typography';
import { Link as RouterLink } from 'react-router-dom';
import { Route, BrowserRouter as Router } from 'react-router-dom';
function SimpleBreadcrumbs() {
return <Route>
{({ location }) => {
const pathnames = location.pathname.split('/').filter(x => x);
return (
<Breadcrumbs aria-label="Breadcrumb">
<RouterLink color="inherit" to="/">
Home
</RouterLink>
{pathnames.map((value, index) => {
const last = index === pathnames.length - 1;
const to = `/${pathnames.slice(0, index + 1).join('/')}`;
return last ? (
<Typography color="textPrimary" key={to}>
{value}
</Typography>
) : (
<RouterLink color="inherit" to={to} key={to}>
{value}
</RouterLink>
);
})}
</Breadcrumbs>
);
}}
</Route>
}
export default function App() {
return <div>
<Router>
<SimpleBreadcrumbs />
<Route path='/' exact component={Home}></Route>
<Route path='/level1' exact component={Level1}></Route>
<Route path='/level1/level2' exact component={Level2}></Route>
</Router>
</div>
}
答案 1 :(得分:0)
我决定发布一个单独的答案,而不是对您的代码Meera进行注释。谢谢您的帮助。我修改了地图功能的主体部分,并添加了翻译功能。可悲的是,它对我来说无法通过react hooks功能使用,因此这就是为什么我将其转换为类组件。
我的组件现在看起来像这样:
import React, { PureComponent } from "react";
import * as PropTypes from "prop-types";
import { Breadcrumbs, Link, Paper, Typography } from "@material-ui/core";
import { connect } from "react-redux";
import { Route, Link as RouterLink } from "react-router-dom";
import { LanguageActions } from "../../redux/actions";
/**
* This component has to be a class component to be able
* to translate the path values dynamically.
* React hooks are not working in this case.
*/
class SimpleBreadcrumbs extends PureComponent {
render = () => {
const { translate } = this.props;
const LinkRouter = props => <Link {...props} component={RouterLink} />;
return (
<Paper elevation={0} style={{ padding: "8px 16px" }}>
<Route>
{({ location }) => {
const pathnames = location.pathname
.split("/")
.filter(x => x);
return (
<Breadcrumbs aria-label="Breadcrumb">
<LinkRouter
color="inherit"
component={RouterLink}
to="/"
>
Home
</LinkRouter>
{pathnames.map((value, index) => {
const last = index === pathnames.length - 1;
const to = `/${pathnames
.slice(0, index + 1)
.join("/")}`;
// Split value so the string can be transformed and parsed later.
const path = value.split("-");
// Convert first char of string to uppercase.
path.forEach((item, i) => {
// Only capitalize starting from the second element.
if (i > 0) {
path[i] =
path[i]
.charAt(0)
.toUpperCase() +
path[i].slice(1);
}
});
return last ? (
<Typography
color="textPrimary"
key={to}
>
{translate(path.join(""))}
</Typography>
) : (
<LinkRouter
color="inherit"
to={to}
key={to}
>
{translate(path.join(""))}
</LinkRouter>
);
})}
</Breadcrumbs>
);
}}
</Route>
</Paper>
);
};
}
// To be able to translate every breadcrumb step,
// translations have to be passed down to this component.
// Otherwise the component does not get notified
// if user decides to switch language
const connector = connect(
({ translations }) => ({ translations }),
dispatch => ({
translate: key => dispatch(LanguageActions.translate(key)),
})
);
SimpleBreadcrumbs.propTypes = {
translate: PropTypes.func,
};
SimpleBreadcrumbs.defaultProps = {
translate: () => {},
};
export default connector(SimpleBreadcrumbs);
答案 2 :(得分:0)
我已经编辑了Meera的出色代码,以解决我面临的一些问题: 我想要标题大小写的链接,而不是小写的。我添加了useLocation钩子,并进行了其他一些更改。
import React from 'react'
import { useLocation, Link as RouterLink } from 'react-router-dom'
import { Breadcrumbs, Typography, Link } from '@material-ui/core'
function toTitleCase(str) {
return str.replace(/\b\w+/g, function (s) {
return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase()
})
}
export default function () {
let location = useLocation()
const pathnames = location.pathname.split('/').filter((x) => x)
return (
<Breadcrumbs aria-label='Breadcrumb'>
<Link color='inherit' component={RouterLink} to='/'>
Home
</Link>
{pathnames.map((value, index) => {
const last = index === pathnames.length - 1
const to = `/${pathnames.slice(0, index + 1).join('/')}`
return last ? (
<Typography color='textPrimary' key={to}>
{toTitleCase(value)}
</Typography>
) : (
<Link color='inherit' component={RouterLink} to='/' key={to}>
{toTitleCase(value)}
</Link>
)
})}
</Breadcrumbs>
)
}