Je suis en train de créer une application React.
Si un utilisateur saisit une URL incorrecte, le composant NoMatch
s'affiche (ce qui est bien).
Le défi est que lorsqu'un utilisateur tape une URL existante, deux composants sont représentés. Le composant NoMatch
et le composant attendu apparaissent tous les deux.
Remarque: J'ai trouvé quelques questions à ce sujet sur stackoverflow , mais aucune des solutions travaillé pour moi. J'utilise un
et un react-router-dom
.
App.js
const PrivateRoute = ({component: Component, auth, ...rest}) => ( <Route {...rest} render={props => auth.isAuthenticated ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: "/login", state: {from: props.location} }} /> ) } /> );
PrivateRoute.js
<Provider store={store}> <Router> <Switch> <Route exact path="/login" component={Login}/> <Fragment> <Navigationbar/> <div className="main-part"> <Sidebar/> <main className="content shrunk-sidebar"> <PrivateRoute path="/" exact component={Home}/> <PrivateRoute path="/files" exact component={Files}/> <PrivateRoute path="/new_app" exact component={NewApp}/> <PrivateRoute path="/applications/:app_name" exact component={Application} /> <PrivateRoute path="*" component={NoMatch}/> </main> </div> </Fragment> </Switch> </Router> </Provider>
Une idée de ce que je fais mal et que je n'obtiens pas le résultat que je souhaite?
3 Réponses :
Une façon consiste à ajouter un composant d'encapsulation pour les chemins "corrects", qui vérifie que si le chemin est l'un des chemins corrects, vous rendez ses enfants, sinon le composant de rendu. Exemple rapide:
if (this.props.location.pathname === '/' || this.props.location.pathname === '/some-page') { return this.props.children; } else { return <NoMatch />; }
Ensuite, dans la vérification du chemin du composant d'emballage:
<WrappingComponent> <Route component={Home} exact path='/' /> <Route component={SomePage} path='/some-page' /> </WrappingComponent>
Supprimer le chemin de celui-ci
<Provider store={store}> <Router> <Switch> <Route exact path="/login" component={Login}/> <Fragment> <Navigationbar/> <div className="main-part"> <Sidebar/> <main className="content shrunk-sidebar"> <PrivateRoute path="/" exact component={Home}/> <PrivateRoute path="/files" exact component={Files}/> <PrivateRoute path="/new_app" exact component={NewApp}/> <PrivateRoute path="/applications/:app_name" exact component={Application} /> <PrivateRoute component={NoMatch}/> </main> </div> </Fragment> </Switch> </Router> </Provider>
Switch
ne fonctionne que pour ses enfants directs, lorsque vous ajoutez quelque chose comme un Fragment
à l'intérieur, Switch perd son effet sur les composants Route
à l'intérieur.
Dans votre cas, vous pouvez simplement déplacer le Switch
à l'intérieur pour contenir le tableau de composants PrivateRoute
pour le faire fonctionner
<Provider store={store}> <Router> <Switch> <Route exact path="/login" component={Login}/> <Fragment> <Navigationbar/> <div className="main-part"> <Sidebar/> <main className="content shrunk-sidebar"> <Switch> <PrivateRoute path="/" exact component={Home}/> <PrivateRoute path="/files" exact component={Files}/> <PrivateRoute path="/new_app" exact component={NewApp}/> <PrivateRoute path="/applications/:app_name" exact component={Application}/> <PrivateRoute path="*" component={NoMatch}/> </Switch> </main> </div> </Fragment> </Switch> </Router> </Provider>
J'ai légèrement modifié votre réponse pour que le code fonctionne pour moi.