1
votes

Comment rediriger vers la page de connexion après avoir cliqué sur le bouton de déconnexion sur l'en-tête de la barre de navigation dans React?

Je suis nouveau dans React. J'ai une configuration de routeur de réaction dans App.js comme ceci:

class Header extends Component {
constructor(props) {
    super(props);
    this.state = {
        redirect: false
    }

}
logout = () => {
    sessionStorage.setItem("userToken", '');
    sessionStorage.clear();
    this.setState({ redirect: true });


}
render() {
    if (this.state.redirect) {
        return (
            <Redirect to={'/sign-in'} />
        )
    }


    return (
        <div>

            <Navbar collapseOnSelect expand="md" bg="dark" variant="dark" fixed="top" >
               ......
                        <NavLink to="/management" className="header-link"><FontAwesomeIcon icon="cog" size="lg" /></NavLink>
                        <button type='button' onClick={this.logout}>Log Out</button>
                    </Nav>
                </Navbar.Collapse>
            </Navbar>
        </div>
    );
}
}
export default Header;

Je veux que l'en-tête s'affiche dans chaque page, il y a un bouton de déconnexion à l'en-tête, je veux rediriger vers la page de connexion / connexion après avoir cliqué dessus. Dans mon composant d'en-tête, c'est comme ça:

<BrowserRouter>
    <div className="App">
      <Header />
      <Switch>
        <Route exact path="/" component={Home}>
        </Route>
        <Route exact path="/management" component={Management}>
        </Route>
        <Route exact path="/sign-up" component={SignUpForm}>
        </Route>
        <Route exact path="/sign-in" component={SignInForm}>
        </Route>
        <Route component={Error}>
        </Route>
      </Switch>
    </div>
  </BrowserRouter >

Il y aura des erreurs "Attention: vous avez essayé de rediriger vers la même route que vous êtes actuellement sur:" / sign-in " et la barre de navigation ne disparaîtra que du corps des émissions de connexion. Puis-je savoir quelle est la bonne façon de procéder? J'ai également essayé this.props.history.push ('/ sign-in') mais il n'y a pas d'accessoires .history, probablement parce que l'en-tête n'est pas en route? Dois-je utiliser avec le routeur? Ou devrais-je simplement faire en sorte que chaque en-tête d'importation de page le place à la place dans app.js? ou quelle est la bonne façon de le faire? Merci beaucoup pour votre aide!


0 commentaires

3 Réponses :


1
votes

Vous évoquez ici deux approches. Vous pouvez utiliser le composant d'ordre supérieur 'withRouter' qui permet aux composants d'accéder au objet d'histoire. En utilisant l'objet history qui serait transmis à votre composant comme accessoire, vous pouvez pousser vers l'itinéraire que vous voulez.

Personnellement, j'aime configurer mes liens de déconnexion pour rendre un composant qui héberge la logique de déconnexion et rend une redirection vers la connexion une fois qu'elle est terminée. De cette façon, les utilisateurs peuvent accéder directement au lien de déconnexion s'ils le souhaitent, et vous pouvez y créer un lien depuis n'importe où dans votre application, selon vos besoins, sans avoir à dupliquer la logique.

Dans le routeur de votre navigateur, vous peut ajouter un chemin pour "/ logout" qui rend un composant comme celui-ci (basé sur votre logique):

import React, { Component } from 'react';
import { Redirect } from 'react-router';

export default class LogOut extends Component {
    state = {
        redirect: false,
    };

    componentDidMount() {
        sessionStorage.setItem("userToken", '');
        sessionStorage.clear();
        this.setState({ redirect: true });
    }

    render() {
        return this.state.redirect ?
            <Redirect to={'/sign-in'} /> :
            null;
    }
}

Normalement, je ferais une requête ajax pour effacer une session, puis setState une fois que c'est terminé, mais le vôtre est entièrement côté serveur.


10 commentaires

Merci beaucoup! Je me sens actuellement très confus que mon bouton de déconnexion soit dans mon en-tête et que ce bouton fasse la fonction de déconnexion, mais je ne sais pas comment structurer l'en-tête ou l'itinéraire. L'en-tête apparaît dans chaque page, il semble donc que je ne devrais pas utiliser la redirection dans le retour de rendu de l'en-tête, ou que je ne devrais pas mettre

au-dessus des routes dans app.js? Puis-je savoir comment structureriez-vous la logique? Merci beaucoup!


Merci beaucoup pour votre aide! Je suis super confus avec l'itinéraire et l'authentification ensemble ~


Mis à jour @Ying. J'espère que cela aide!


Merci beaucoup! Ensuite, je viens d'importer le bouton de déconnexion dans mon en-tête, n'est-ce pas? Oh et après avoir cliqué sur le bouton de déconnexion, puis-je savoir comment restituer le corps de la page? Comme je suis dans la page de gestion avec des informations utilisateur, puis je clique sur le bouton de déconnexion de l'en-tête, comment puis-je faire du corps de la page de gestion une page de connexion?


@Ying Vous pourrez le rendre comme si vous étiez le NavLink pour / management, ou n'importe quel lien sauf vers / déconnexion. Votre route gérerait le rendu du composant, par exemple:


Ah merci beaucoup !!! C'est vraiment très utile! : D Ah dernière question, puis-je savoir comment masquer NavLink pour / gestion ou toute la barre d'en-tête si je suis dans la page de connexion?


@Ying Puisque vous gérez la session par un cookie défini dans le navigateur, vous pouvez vérifier si c'est défini, puis ne rendre le lien que s'il est défini: {isLoggedIn && }. Idéalement, vous empêcheriez également l'utilisateur de naviguer vers l'URL de gestion.


Je vous remercie beaucoup pour votre aide! : D beaucoup appris!


La réponse de @ dhara-charola contient des informations intéressantes sur la façon de protéger vos routes et de gérer l'état !!


J'ai besoin d'un exemple de la façon de définir la structure de la mise en page lorsque non authentifiée, afficher uniquement la page de connexion et, une fois connecté, afficher la page entière avec les menus de la barre latérale, pouvez-vous me montrer un exemple ou un didacticiel montrant cela?



2
votes

Les composants liés à Routes ont accès à l'objet d'historique comme accessoire afin que vous puissiez le muter selon vos besoins, par exemple en vous déconnectant. Puisque votre composant d'en-tête n'a pas accès à l'objet d'historique, vous devrez utiliser un routeur de niveau inférieur pour lui donner accès à l'objet d'historique:

import { Router } from "react-router"
import { createBrowserHistory } from "history"

const history = createBrowserHistory()

<Router history={history}>
  <div className="App">
      <Header history={history} />
      <Switch>
        <Route exact path="/" component={Home}>
        </Route>
        <Route exact path="/management" component={Management}>
        </Route>
        <Route exact path="/sign-up" component={SignUpForm}>
        </Route>
        <Route exact path="/sign-in" component={SignInForm}>
        </Route>
        <Route component={Error}>
        </Route>
      </Switch>
    </div>
</Router>

maintenant à l'intérieur de votre composant d'en-tête, vous pouvez appelez history.push('/login')

voir référence: https://reacttraining.com/react-router/web/api/Router/history-object


2 commentaires

Merci beaucoup! J'ai juste essayé et cela a fonctionné. Puis-je savoir quelle est la différence entre react-router et react-router-dom? Puisqu'il ne me permet pas d'importer BrowserRouter. Et je me rends compte que je peux également utiliser NavLink to = "/ sign-in" pour le bouton de déconnexion, puis-je savoir quelle est la différence entre utiliser NavLink to ou Redirect to? Merci beaucoup!


react-router contient les composants de niveau inférieur, react-router-dom contient des composants spécifiques au navigateur. N'oubliez pas qu'il est important que tout composant que vous avez pointe vers le même objet d'historique afin que votre historique provienne d'une seule source, sinon vous obtiendrez des bogues avec votre historique qui ne se synchronise pas avec le navigateur. Puis-je faire accepter ma réponse? Je vous en prie!



4
votes

Vous pouvez implémenter la connexion / déconnexion avec route en utilisant HOC qui vérifie l'élément de session à chaque changement de route. Si la session a userToken , elle sera redirigée vers un composant donné, sinon elle sera redirigée vers le composant de connexion.

class Header extends Component {

....

logout = () => {
    sessionStorage.removeItem("userToken");
    sessionStorage.clear(); 
}

render() {
    return (
        <div>
          ...
          <button type='button' onClick={this.logout}>Log Out</button>
        </div>
    )
}
}
export default Header;

importez et utilisez comme chemin autorisé. Et conservez tous les autres chemins comme des itinéraires normaux dans lesquels vous ne voulez pas d'autorisation.

<BrowserRouter>
    <div className="App">
        <Header />
        <Switch>
            <PrivateRoute path="/" component={Home} />
            <PrivateRoute path="/management" component={Management} />
            <Route path="/sign-up" component={SignUpForm} />
            <Route path="/sign-in" component={SignInForm} />
            <Route component={Error} />
        </Switch>
    </div>
</BrowserRouter >

Ainsi, pendant que vous vous déconnectez, l'élément de session sera supprimé et automatiquement redirigé vers page de connexion.

import React from "react"
import {Redirect} from "react-router-dom"

export const PrivateRoute = ({component: Component, ...rest}) => (
    <Route {...rest} render={(props) => (
        sessionStorage.getItem('userToken') ? <Component {...props} /> : <Redirect to="/sign-in"/>
    )} />
)


6 commentaires

Je vous remercie beaucoup pour votre aide! : D Donc, ce PrivateRoute redirigera toute la page pour se connecter tant que le jeton utilisateur est supprimé de la session même si l'en-tête n'est pas enveloppé dans , n'est-ce pas? Puis-je savoir pourquoi nous écrivons {component: Component} comme ça? Est-ce que "... reste" est comme path = "/ sign-up"? Et quels sont les accessoires? Merci beaucoup!


Oh je viens d'essayer et cette méthode est tellement bonne! Ensuite, ajoutez simplement un Déconnexion !


Je suis heureux que cette solution fonctionne pour vous. Heureux de vous aider. Et appréciez également votre reconnaissance.


Merci beaucoup! Oh et puis-je savoir quel serait un bon moyen de masquer

lorsque l'utilisateur est dans la page de connexion et la page d'inscription avec cette structure? Merci beaucoup!


Il suffit de mettre le composant '

' dans le composant '' avec le composant mentionné, il sera donc masqué dans la page de connexion / d'inscription et sera vu dans les routes autorisées. Consultez cette stackoverflow.com/questions/55175724/...


Woah, merci beaucoup! Mettez-le simplement dans: export const PrivateRoute = ({component: Component, ... rest}) => ( (sessionStorage.getItem ('userToken')?

: )} />). Cette méthode est vraiment vraiment géniale !!! Appris beaucoup! Merci beaucoup !!! J'apprécie beaucoup! :RÉ