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?
My solution until I know better (Not working)
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,...
Final solution
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"