0
votes

React Hook Set: État causant une boucle infinie

Voici mon code, j'essaie d'appeler setState à l'intérieur de mon bouton de déconnexion car ce bouton ne s'affiche que lorsque Auth0 isLoggedIn est vrai. Cela semble provoquer une boucle infinie, je suppose que l'API Auth0 est appelée à chaque fois. Je suis ce tutoriel: https://www.youtube.com/watch?v=35lXWvCuM8o La seule différence est que j'essaie d'appeler setState sans fonction onClick, quelqu'un peut-il m'expliquer le problème et un correctif, merci en avance!

Je comprends que je peux utiliser localStorage pour maintenir une session d'utilisateurs connectés, mais je le fais uniquement pour apprendre React Hooks,

import React, { useState, useContext, useCallback} from 'react';
    import { useAuth0 } from '@auth0/auth0-react';
    import { ValueContext } from './ValueContext'

    const LogoutButton = () => {
 
    const [login, setLogin] = useContext(ValueContext);


  const { logout, isAuthenticated } = useAuth0();
  const updateLogin = () => {
    setLogin({loggedIn:'false'});
  };

  return (
    
    isAuthenticated && (
      <>
      <button onClick={() => logout()}>
        Log Out
      </button>
      
      <h1>{login.loggedIn}</h1>
     {updateLogin()}
   
          
         
       
      
    
      </>
      
    )


0 commentaires

4 Réponses :


0
votes

Vous appelez updateLogin() dans votre fonction de rendu, vous définissez donc loggedIn: true chaque rendu. Ne placez pas de fonctions ou de journaux de console directement à l'intérieur de la fonction de retour, placez-les dans le corps de la fonction principale LogoutButton si vous le devez. Mais updateLogin() ne doit être appelé qu'à l'intérieur de certains onPress.


10 commentaires

J'ai changé mon bouton pour ceci: <button onClick = {() => logout (), updateLogin ()}> Log Out </button>


mais maintenant j'obtiens une boucle infinie de rendus.


Je ne comprends pas ce que vous essayez d'accomplir ici. Je ne sais pas comment fonctionne Auth0, mais je suppose que vous ne voulez pas appeler la logout et updateLogin (qui vous connecte juste) dans le même bouton.


J'essaie d'appeler la fonction de connexion d'auth0 qui authentifie l'utilisateur via auth0. en même temps que l'utilisateur s'authentifie, je souhaite mettre à jour une variable globale `` connecté '' via le contexte afin de pouvoir sérénader mes autres composants pour donner à l'utilisateur un nouvel accès à certaines choses auxquelles il ne pouvait pas accéder lorsqu'il n'était pas connecté, ce qui est pourquoi j'ai initialement essayé d'appeler updateLogin () par lui-même sans onClick


Alors pourquoi appelez-vous la logout d'Auth0 si vous essayez de connecter l'utilisateur à Auth0?


Veuillez vérifier le code mis à jour, j'essaie de déconnecter l'utilisateur avec la déconnexion Auth0, en même temps, mettez à jour ma valeur globale connectée sur `` false '' afin que les autres composants soient rendus pour donner accès uniquement à ce qu'un utilisateur peut accéder lorsqu'il êtes déconnecté


Vous avez toujours le {updateLogin()} intérieur d'une méthode de rendu. Il va continuer à mettre à jour l'état, puis se déclencher à nouveau sur le prochain rendu. Mettez logout() intérieur du corps de votre fonction updateLogin et appelez-le dans le onPress du bouton.


Je l'ai fait, et je peux voir les mises à jour de l'état global, mais il semble qu'une fois la déconnexion via auth0 se produit, l'état global se réinitialise à la valeur pré-mise à jour, sur le didacticiel que j'ai suivi, Dev ed parle d'utiliser prevState pour mettre à jour le contexte global, mais il met à jour un tableau et je mets à jour une seule valeur globale de chaîne, connaissez-vous un moyen de mettre à jour en utilisant prevState pour une chaîne?


J'ai republié la question avec le code que vous avez suggéré, mais je ne sais pas comment empêcher la valeur de se réinitialiser à false, stackoverflow.com/questions/64627375/...


Déterminez où la valeur est définie sur false. Je pense que vous vous confondez avec différents concepts ici. Vous avez accès à la valeur de "prevState" dans la valeur actuelle de login .



0
votes

Vous appelez updateLogin () chaque fois que le composant est rendu. Cela définit la variable d'état connecté. Cela entraînera le rendu du composant à nouveau et le processus continuera à tourner.


0 commentaires

0
votes

La seule différence est que j'essaye d'appeler setState sans fonction onClick

C'est une grande différence! setState ne doit pas être appelé dans le corps principal de la fonction de rendu, ou du moins, l'appeler conditionnellement. Sinon, vous obtiendrez setState -> render -> setState -> render -> ... c'est sans fin.

Vous pouvez essayer ceci:

    let alreadySet = false;
....
{
    if(!alreadySet){
      alreadySet = true;
      updateLogin()
    }
}

Remarquez ceci

    let alreadySet = false;

    const LogoutButton = () => {
    const [login, setLogin] = useContext(ValueContext);
    const { logout, isAuthenticated } = useAuth0();
    const updateLogin = () => {
      setLogin({loggedIn:'false'});
    };

    if(!alreadySet){
      alreadySet = true;
      updateLogin()
    }

    return ( 
    isAuthenticated && (
      <>
      <button onClick={() => logout()}>
        Log Out
      </button>   
      <h1>{login.loggedIn}</h1>
      </>
    )

Cela signifie que connecté ne sera mis à jour qu'une seule fois. C'est ce que tu veux? Si ce n'est pas le cas. Vous pouvez mettre à jour votre question avec plus de détails :)


4 commentaires

J'ai ajouté l'extrait de code auquel vous faites référence et j'obtiens maintenant un message d'erreur: profondeur maximale de mise à jour dépassée. Cela peut se produire lorsqu'un composant appelle à plusieurs reprises setState dans componentWillUpdate ou componentDidUpdate. updateLogin src / components / LogoutButton.js: 14 11 | const {déconnexion, isAuthenticated} = useAuth0 (); 12 | const updateLogin = () => {13 | /* Se déconnecter(); * /> 14 | setLogin ({connecté: 'faux'}); | ^ src / composants / LogoutButton.js: 22 19 | laissez déjàSet = false; 20 | si (! déjàSet) {21 | déjàSet = vrai; | updateLogin () | }


Ok, j'ai déjà changé l'extrait de code Tolet = false; if (! alreadySet && isLoggedIn) {alreadySet = true; updateLogin ()}


Maintenant, l'application fonctionne et affiche correctement le bouton de connexion, mais une fois que je clique sur Connexion et que le bouton de déconnexion est rendu, j'obtiens à nouveau une boucle infinie de setLogin, donc je dois comprendre comment l'empêcher de mettre à jour le déjà faux, des idées?


Hey Josh, désolé pour la réponse tardive, nous devrions déplacer "let alreadySet = false;" en dehors de la fonction LogoutButton



0
votes

Si vous devez utiliser updateLogin lorsque isAuthenticated vaut true, vous pouvez ajouter le hook useEffect.

comme ça

useEffect(()=>{ if (isAuthenticated){
   setLogin({loggedIn:'false'});
}},[isAuthenticated, setLogin] );


0 commentaires