I am trying to pass a slug to a header component without having to include the header to each and every subcomponent.
My code looks like this:
const App = () => {
return (
<>
<Grid container direction="column">
<Grid item>
<Header />
</Grid>
<Grid item container>
<Grid item xs={false} md={2} />
<Grid item xs={12} md={8}>
<Switch>
<Route exact path="/" component={IntroPage} />
<Route exact path="/:slug" component={StartPage} />
<Route path="/:slug/index" component={StartPage} />
<Route path="/:slug/player" component={PlayerPage} />
<Route path="/:slug/game" component={GamePage} />
<Route path="/:slug/scoreboard" component={ScoreboardPage} />
<Route path="/:slug/controller" component={ControllerPage} />
<Route path="/:slug/settings" component={SettingsPage} />
<Route path="/:slug/credits" component={CreditsPage} />
<Route component={PageNotFound} />
</Switch>
</Grid>
<Grid item xs={false} md={2} />
</Grid>
<ToastContainer autoClose={3000} hideProgressBar />
</Grid>
<Grid container direction="column">
<Footer />
</Grid>
</>
);
};
export default App;
What I want is the Header component to know what slug was chosen in one of the routes within the Switch.
Is there a possibility to do this with for example nested routing?
Best regards, Patrick
Edit:
This is my Header component btw:
const Header = (props) => {
console.log(props.match.params.slug)
const classes = useStyles();
const [open, setOpen] = useState();
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<div className={classes.root}>
<AppBar
position="static"
className={clsx(classes.appBar, { [classes.appBarShift]: open })}
>
<Toolbar>
<IconButton
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
className={clsx(classes.menuButton, open && classes.hide)}
>
<MenuIcon />
</IconButton>
<Typography>Placeholder Banner</Typography>
</Toolbar>
</AppBar>
<Drawer
variant="persistent"
anchor="left"
open={open}
className={classes.drawer}
classes={{ paper: classes.drawerPaper }}
>
<div className={classes.drawerHeader}>
<IconButton onClick={handleDrawerClose}>
<CloseIcon />
</IconButton>
</div>
<Divider />
<List>
<ListItem component="a" href="/" button key="start">
<ListItemIcon>
<HomeIcon fontSize="large" />
</ListItemIcon>
<ListItemText>Start</ListItemText>
</ListItem>
<ListItem component="a" href="/game" button key="game">
<ListItemIcon>
<SportsEsportsIcon fontSize="large" />
</ListItemIcon>
<ListItemText>Game Setup</ListItemText>
</ListItem>
<ListItem component="a" href="/player" button key="player">
<ListItemIcon>
<PersonIcon fontSize="large" />
</ListItemIcon>
<ListItemText>Player Setup</ListItemText>
</ListItem>
<ListItem component="a" href="/settings" button key="settings">
<ListItemIcon>
<SettingsIcon fontSize="large" />
</ListItemIcon>
<ListItemText>Settings</ListItemText>
</ListItem>
<ListItem component="a" href="/credits" button key="credits">
<ListItemIcon>
<InfoIcon fontSize="large" />
</ListItemIcon>
<ListItemText>Credits</ListItemText>
</ListItem>
</List>
</Drawer>
</div>
);
};
export default Header;
I want to give the links the ability to include the slug. For example href=/game
needs to be href=:slug/game
then.
And please be aware that header is loaded before the switch.
Edit2:
At least this:
const Header = (props) => {
const {match, location, history} = props
console.log(match)
console.log(location)
console.log(history)
....
export default withRouter(Header);
will give me access to the location which has the slug. But this appears to not be the cleanest way. Also match.params does not hold the slug, even with withRouter
export. Why is that?
const Header = (props) => {
const { location } = props;
let pathname = location.pathname
let slug = pathname.split("/")
console.log(slug[1]);
....
export default withRouter(Header);
This will cause that the url gets confused after a few clicks cause location will be concatenated again and again resulting ins urls like /myslug,game,player,...
Well I got the final solution from below which is:
Wrap the Header in its specific location into Route
<Grid item>
<Route path={["/:slug", "*"]} component={Header} />
</Grid>
Then access props.match.params in Header component:
const Header = (props) => {
console.log(props.match.params)
this will give:
slug: "game"
The Header
isn't being rendered on a route so it doesn't have access to any of the route-props, specifically, the route parameters. It also needs to be rendered on a Route that matches a path that specifies the "slug" route parameter.
Render the Header
into a Route
that specifies both a match all path and a path that can match with a slug. Order matter so specify the path with slug first so it can be matched before less specific routes (same as the rules for the Switch
).
<Route path={["/:slug", '*']} component={Header} />
Try using useParams() to get the slug.
Try do like this:
<Route
exact
path='/:slug/player'
render={(props) => <PlayerPage {...props}/>}
/>
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.