5
votes

En-têtes par défaut Axios effacés après l'actualisation de la page dans React.js

Je mets axios.defaults.headers.Authorization = MY_TOKEN dans le composant Login qui est rendu dans le composant Authentication qui vérifie si this.state.loggedin est défini sur true. Si faux, il rend le composant de connexion, s'il est vrai, il rend UserComponent avec BrowserRouter. BrowserRouter lit le chemin "/" et accède au composant Documents. Au cours de cette navigation, la page s'actualise et axios.defaults.headers.Authorization est effacé en renvoyant la valeur indéfinie. Comment puis-je conserver axios.defaults.headers même si la page est actualisée ou dois-je initialiser les en-têtes par défaut chaque fois que le routeur navigue vers un autre composant?

MISE À JOUR

Ajout de code comment le rendu se produit dans Authentication.js

<BrowserRouter>
      <div>
        <UserNavigationComponent {...this.props}>
          <Switch>
            <Route
              exact
              path="/"
              component={UserSubmittedDocumentsContainer}
            />

UserNavigationContainer.js rend les routages (code non complet)

      render() {
      return (
        <UserNavigationContainer
          {...this.props}
          logout={this.onClickLogoutHandler}
        />
      );
     }

Donc en fait quand UserNavigationContainer obtient le rendu, il navigue vers "/" et actualise la page pendant la navigation.


3 commentaires

Si vous souhaitez persister entre les actualisations de la page, placez le jeton dans le stockage local et extrayez-le à partir de là. Vous ne savez pas pourquoi la page entière est actualisée lorsque vous naviguez? Cela ne devrait pas arriver si vous utilisez React Router - c'est le but de React Router en premier lieu d'implémenter le routage côté client.


J'ai ajouté quelques coupes du code sur la façon dont le rendu et la navigation se produisent, donc je ne sais pas si c'est correct.


Pouvez-vous créer un CodeSandbox.io pour que nous puissions y jeter un œil?


3 Réponses :


6
votes

J'ai eu une expérience similaire et voici comment j'ai pu la résoudre

Conserver le jeton dans le stockage local lors de la connexion / inscription de l'utilisateur: la première étape consistait à conserver le jeton utilisateur sur le stockage local une fois la connexion / l'inscription réussie, vous pouvez consulter l'API de stockage local du navigateur ici

Déplacer la logique qui définit l'en-tête d'autorisation vers un composant qui restitue toujours quel que soit le chemin actuel (composant de barre de navigation dans mon cas): Ensuite, il fallait déplacer la logique responsable de la définition de l'en-tête d'autorisation vers mon composant de barre de navigation, ce faisant, il récupère automatiquement le jeton de l'utilisateur actif du stockage local et définit l'en-tête d'autorisation. maintenant, quel que soit le composant rendu par react-router, l'en-tête d'autorisation est constamment défini, ce qui évite d'avoir à le faire pour tous les autres composants.

PS : déplacer la logique ne vous empêche pas de définir initialement l'en-tête d'autorisation dans le composant de connexion, cela ne résout le problème que pour tous les autres composants qui sont rendus.


0 commentaires

1
votes

J'ai rencontré le même problème. J'ai résolu mon problème en définissant les en-têtes communs de la requête dans les fichiers racine. Dans mon cas, il s'agit de index.js.

 setting request headers common globalally

Avez-vous remarqué que je configure app_token depuis localStorage?

Initialement, AuthLayout rend le composant de connexion. Si la connexion réussit, je dois rediriger vers la route d'administration.

Auth.js

Login component

Donc, j'ai prévu pour définir les en-têtes dans le composant de connexion. Si la connexion réussit, je pourrais définir app_token dans les en-têtes de la demande. Tout s'est bien passé jusqu'à ce que j'actualise la page.

Login.js

 réglage app_token à partir de la réponse

Donc, j'ai défini le jeton dans localStorage et l'a utilisé dans le fichier index.js pour définir les en-têtes globalement.

Login.js

 setting localstorage

Je suppose que ce n'est pas une meilleure solution. Eh bien, je pourrais définir les en-têtes globalement et m'authentifier à l'aide du jeton même après l'actualisation de la page.

MISE À JOUR:

Une autre solution simple pour définir l'autorisation dans les en-têtes consiste à avoir un intercepteur .

Étape 1: Créez un fichier appelé interceptor.js. Créez une instance.

import axiosApiInstance from "./interceptor";

let response = await axiosApiInstance.get(
      "/api/***"
    );
    return response;

étape 2: appelez vos API suivantes qui nécessitent des en-têtes d'autorisation comme indiqué ci-dessous.

const axios = require("axios");
const axiosApiInstance = axios.create();

// Request interceptor for API calls
axiosApiInstance.interceptors.request.use(
  async (config) => {
    config.headers = {
      Authorization: `Bearer ${localStorage.getItem("token")}`,
    };
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);

export default axiosApiInstance;

Merci



0
votes

La réponse de Damali est tout à fait correcte, mais je pense également qu'il vaut la peine de développer ceci:

Déplacez la logique qui définit l'en-tête d'autorisation vers un composant qui rend quel que soit le chemin actuel

Pour être honnête, il est difficile de bien comprendre la structure du projet d'OP, car les extraits publiés pour une raison quelconque se rapportent à la logique de routage d'authentification, ce qui n'est pas la question posée. Mais, pour plus de clarté, développez la citation ci-dessus:

Toute logique d'authentification, y compris la définition de l'en-tête axios, doit être encapsulée dans un seul composant (probablement un contexte de réaction). Ce n'est pas aussi simple que de "définir un en-tête et de passer": toute application de niveau production devra:

  • Conserver un état d'authentification (connecté / déconnecté?)
  • Évaluer fréquemment cet état (expiré?)
  • Peut-être conserver et évaluer des informations de connexion plus détaillées (par exemple les rôles)
  • Manipulez le routage et les requêtes API en fonction de ce qui précède

C'est le rôle d'un module d'authentification.

Le module d'authentification doit contrôler l'en-tête d'authentification axios. Cela signifie que nous parlons presque certainement de deux modules distincts:

  1. Un module de service HTTPs (contient et exporte l'instance axios), et
  2. Un module d'authentification

Maintenant: comme OP l'a plus ou moins observé: si le module auth appelle simplement l'instance axios et lui applique un en-tête lors de la connexion, cela ne persistera pas après une actualisation.

Le problème avec la réponse de Damali est que même si votre module d'authentification est toujours rendu (par exemple, il est tout en haut de votre application), la configuration axios ne persistera pas lors de l'actualisation de la page. Une actualisation de la page va forcer un nouveau rendu: l'en-tête aura disparu.

La réponse est d'une simplicité trompeuse: réappliquez l'en-tête chaque fois que l'authentification est requise (ainsi que lors de la connexion). Il existe plusieurs façons de procéder, en voici une seule:

// apiService.js
import Axios from 'axios';
const axios = Axios.create();

export function setDefaultHeader(key, value){
    axios.defaults.headers.common[key] = value;
}
export axios;


// auth.js
import { axios, setDefaultHeader } from '../services/apiService.js';

const tokenKey = 'x-auth-token';
setDefaultHeader(tokenKey, localStorage[tokenKey]);


0 commentaires