J'essaie de transmettre un slug à un composant d'en-tête sans avoir à inclure l'en-tête à chaque sous-composant.
Mon code ressemble à ceci:
slug: "game"
Ce que je veux, c'est que le composant Header sache quel slug a été choisi dans l'une des routes du Switch.
Est-il possible de le faire avec, par exemple, le routage imbriqué?
Meilleur Cordialement, Patrick
Edit:
Ceci est mon composant Header btw:
const Header = (props) => {
console.log(props.match.params)
Je veux donner la possibilité aux liens pour inclure la limace. Par exemple, href = / game doit être href =: slug / game alors.
Et sachez que l'en-tête est chargé avant le changement.
Edit2:
Au moins ceci:
<Grid item>
<Route path={["/:slug", "*"]} component={Header} />
</Grid>
me donnera accès à l'emplacement où se trouve le slug. Mais cela ne semble pas être le moyen le plus propre. De plus, match.params ne contient pas le slug, même avec l'exportation withRouter . Pourquoi?
const Header = (props) => {
const { location } = props;
let pathname = location.pathname
let slug = pathname.split("/")
console.log(slug[1]);
....
export default withRouter(Header);
Cela entraînera la confusion de l'URL après quelques clics, la localisation sera concaténé encore et encore des URLs résultantes comme /myslug,game,player,...
Eh bien, j'ai obtenu la solution finale ci-dessous qui est: p >
Enveloppez l'en-tête à son emplacement spécifique dans Route
const Header = (props) => {
const {match, location, history} = props
console.log(match)
console.log(location)
console.log(history)
....
export default withRouter(Header);
Accédez ensuite à props.match.params dans le composant Header:
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;
3 Réponses :
Essayez d'utiliser useParams () pour récupérer le slug.
Cela ne fonctionne pas car l'en-tête est chargé avant le commutateur. Il n'y a pas encore de slug lors du rendu de l'en-tête.
Vous voudrez peut-être vérifier avec Routeur alors. Je pense que c'est peut-être ce que vous recherchez.
Essayez de faire comme ceci:
<Route
exact
path='/:slug/player'
render={(props) => <PlayerPage {...props}/>}
/>
L ' En-tête n'est pas rendu sur une route, il n'a donc accès à aucun des accessoires de route, en particulier aux paramètres de la route. Il doit également être rendu sur une Route qui correspond à un chemin qui spécifie le paramètre de route "slug".
Transformez l ' En-tête en un Route qui spécifie à la fois un chemin correspondant à tous les un chemin pouvant correspondre à un slug L'ordre est important, spécifiez donc le chemin avec le slug en premier afin qu'il puisse être mis en correspondance avant les routes moins spécifiques (comme les règles pour le Switch).
<Route path={["/:slug", '*']} component={Header} />
h1 >
Les options 1 et 2 me donneront undefined. UseParams () peut simplement restituer le splug qui se trouve dans le routeur, mais pas l'en-tête. L'option 2 n'aura pas de slug dans le match des accessoires (je suppose que pour la même raison). L'option 3 ne fonctionnera pas car elle rompt ma disposition de grille.
Vraisemblablement, votre routeur encapsule votre application , si ce n'est pas le cas, veuillez ajouter les détails importants sur l'emplacement de votre routeur tel quel le composant qui contient les données d'itinéraire, c'est-à-dire le paramètre d'itinéraire "slug".
Il encapsule en fait l'application: `
Cela omettra cependant de rendre mon contenu principal! Et le comportement de rendu diffère selon la position dans le commutateur.
@PatrickHener Réponse mise à jour avec la façon dont le composant Header peut accéder au slug. Les composants Route n'ont pas beaucoup d'aspect visuel, le cas échéant, donc si le rendu de votre En-tête dans une Route perturbe la disposition de la grille, c'est probablement parce que vos composants font des hypothèses sur leurs composants parents. Je suppose qu'il essaie simplement d'hériter de certains CSS.
Switch ne correspond et renvoie que la première correspondance .... ne mettez pas le Header dans votre Switch si vous voulez qu'il soit toujours rendu. L'emballage de Header dans Route sert simplement à accéder aux accessoires de route.
Oh d'accord, je comprends ça. Alors je l'ai emballé à sa position d'origine. Mais là encore, useParams () me donnera une erreur.
Eh bien, je peux alors y accéder via props.match.params. Voilà la solution!
Quelle est / quelle était l'erreur que vous voyiez en utilisant le hook? Si dans une route, le hook et l'accessoire de correspondance devraient fonctionner à peu près de la même manière.
L'erreur était TypeError: Object (...) n'est pas une fonction à la ligne où il y avait const {slug} = useParams ()
Ohh facepalm moi stupide! Je l'ai importé de react pas de react-router-dom. Maintenant, useParams fonctionne aussi.
@PatrickHener Je vois. J'allais dire que vous devez être sur React v16.8 + et sur la version v5 de react-router-dom pour utiliser les hooks.
Utilisez useParams ou obtenez les paramètres à partir de l'itinéraire match prop du
Router.const Header = (props) => {console.log (props.match.params.slug)Cela ne fonctionne pas cependant.TypeError: Impossible de lire la propriété 'params' non définieHeadern'est pas rendu par uneRoute, vous devez donc utiliser le hookuseParamsou le HOCwithRouterpour obtenir les paramètres de correspondance durouteurle plus proche. Ou simplement rendre l 'En-têteen une correspondance à tous lesRoute, c'est-à-dire .