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éfinie
Header
n'est pas rendu par uneRoute
, vous devez donc utiliser le hookuseParams
ou le HOCwithRouter
pour obtenir les paramètres de correspondance durouteur
le plus proche. Ou simplement rendre l 'En-tête
en une correspondance à tous lesRoute
, c'est-à-dire