React中的动态URL



我正在使用Redux的React项目,我正在使用Rest API,我需要实现一个功能,当我从列表中选择一个项目时,我需要在URL中加载项目ID,并直接到另一个屏幕,其中加载了一个侧边栏的选项。这个项目的导航。例子:布局

我设法在URL中加载项目的Id并在项目的主屏幕中检索此Id,问题是存储项目的Id并在下一个选定的URL中设置此Id,例如:

path: '/project/:id/companies'path: '/project/:id/currencies'path: '/project/:id/settings'

项目列表:

获取项目id并箭头指向url:href={`#/project/${row.id}/main`}

路线:

path: '/project/:id/main',
exact: true,
name: 'projectMain',
component: RequireAuth(ProjectMain),

在main中检索ID

import { useParams } from 'react-router-dom';
...
const { id } = useParams();

问题是在侧边栏中,我加载了一个带有路径的项目列表,我无法在此列表中传递项目id。

互补性

在侧边栏中,我使用useHistory(),问题是路径是静态的,通过'props'导入文件到我的模板中,如你所见:模板

import React from 'react';
import { Grid, makeStyles } from '@material-ui/core';    
import {
AppContent,
AppHeader,
SidebarApp,
} from '../components/index';
import itemsProject from '../components/itemsSidebar/itemsProject';
const useStyles = makeStyles(theme => ({
appContent: {
paddingLeft: 240,
width: '100%',
backgroundColor: theme.palette.background.paper,
},
}));
const ProjectLayout = () => {
const classes = useStyles();
return (
<div className={classes.appContent}>
<AppHeader />
<Grid container direction="row">
<SidebarApp items={itemsProject} />
<AppContent />
</Grid>
</div>
);
};    
export default ProjectLayout;

栏:

/* eslint-disable react/jsx-no-duplicate-props */
import React from 'react';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import Divider from '@material-ui/core/Divider';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
import Collapse from '@material-ui/core/Collapse';
import {
alpha,
Box,
Card,
ListSubheader,
makeStyles,
Typography,
} from '@material-ui/core';
import { useHistory, useLocation, useParams } from 'react-router-dom';
import translate from '../providers/i18n/translate';
const useStyles = makeStyles(theme => ({
sidebar: {
background: theme.palette.background.dark,
width: 240,
height: '100vh',
border: '1px solid rgba(0, 0, 0, 0.1)',
display: 'flex',
flexDirection: 'column',
position: 'absolute',
paddingTop: 64,
top: 0,
left: 0,
},
sidebarItem: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
},
sidebarItemContent: {
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
overflow: 'hidden',
display: 'flex',
alignItems: 'center',
width: '100%',
},
sidebarItemIcon: {
marginRight: 6,
},
sidebarItemText: {
width: '100%',
},
sidebarItemExpandArrow: {
fontSize: '1.2rem !important',
},
sidebarItemExpandArrowExpanded: {
fontSize: '1.2rem !important',
color: theme.palette.primary.main,
fontWeight: 'bold',
},
active: {
background: alpha(theme.palette.primary.light, 0.2),
},
}));
function SidebarItem({ depthStep = 10, depth = 0, expanded, item, ...rest }) {
const [collapsed, setCollapsed] = React.useState(true);
const { label, items, Icon, onClick: onClickProp } = item;
const classes = useStyles();
const history = useHistory();
const location = useLocation();
function toggleCollapse() {
setCollapsed(prevValue => !prevValue);
}
function onClick(e) {
if (Array.isArray(items)) {
toggleCollapse();
}
if (onClickProp) {
onClickProp(e, item);
history.push(item.path);
}
}
let expandIcon;
if (Array.isArray(items) && items.length) {
expandIcon = !collapsed ? (
<>
<ExpandLessIcon className={classes.sidebarItemExpandArrowExpanded} />
</>
) : (
<ExpandMoreIcon className={classes.sidebarItemExpandArrow} />
);
}
return (
<>
<ListItem
className={classes.sidebarItem}
onClick={onClick}
button
dense
className={location.pathname === item.path ? classes.active : null}
{...rest}
>
<div
style={{ paddingLeft: depth * depthStep }}
className={classes.sidebarItemContent}
>
{Icon && (
<Icon
className={classes.sidebarItemIcon}
fontSize="small"
color="primary"
/>
)}
<div className={classes.sidebarItemText}>{label}</div>
</div>
{expandIcon}
</ListItem>
<Collapse in={!collapsed} timeout="auto" unmountOnExit>
{Array.isArray(items) ? (
<List disablePadding dense>
{items.map((subItem, index) => (
<React.Fragment key={`${subItem.name}${index}`}>
{subItem === 'divider' ? (
<Divider style={{ margin: '6px 0' }} />
) : (
<SidebarItem
depth={depth + 1}
depthStep={depthStep}
item={subItem}
/>
)}
</React.Fragment>
))}
</List>
) : null}
</Collapse>
</>
);
}
function Sidebar({ items, depthStep, depth, expanded }) {
const classes = useStyles();
const { key } = useParams();
return (
<Card elevation={0} className={classes.sidebar}>
<List
disablePadding
dense
subheader={
<ListSubheader component="div" id="nested-list-subheader">
{translate('sidebarMenuSettings')}
<Typography>
<Box>{key}</Box>
</Typography>
</ListSubheader>
}
>
{items.map((sidebarItem, index) => (
<React.Fragment key={`${sidebarItem.name}${index}`}>
{sidebarItem === 'divider' ? (
<Divider style={{ margin: '6px 0' }} />
) : (
<SidebarItem
depthStep={depthStep}
depth={depth}
expanded={expanded}
item={sidebarItem}
/>
)}
</React.Fragment>
))}
</List>
</Card>
);
}
export default Sidebar;

侧边栏列表项

function onClick(e, item) {}
const itemsProject = [
{
name: 'companies',
label: translate('sidebarProjectCompanies'),
Icon: CompanyIcon,
path: '/project/:id/companies',
onClick,
}
{
name: 'currencies',
label: translate('sidebarProjectCurrencies'),
Icon: CurrencyIcon,
path: '/project/:id/currencies',
onClick,
}
];
export default itemsProject;

如何在侧边栏列表项上传递ID变量?

谢谢你的帮助!

你可以这样使用ES6模板字面值。

path: `/project/${id}/companies`

既然已经定义了路径,那么只需要使用useHistory并导航到新的链接

import { useHistory } from 'react-router';
...

const history = useHistory();
...
// call this whenever you want to navigate
history.push(`/project/${id}/currencies`);

最新更新