J'ai ce problème où, l'utilisateur doit être redirigé vers les tableaux de bord respectifs lors d'une connexion réussie. Supposons que l'utilisateur possède des comptes dans deux profils "p1" et "p2". Après le succès de la connexion, je crée une API de récupération pour voir si l'utilisateur a des entrées dans les profils correspondants.

1) Dites si un utilisateur a des entrées dans p1, je dois le rediriger vers le tableau de bord "p1";

2) si des entrées dans p2, alors redirigez-le vers le tableau de bord "p2".

3) Si aucune entrée n'est présente ni dans p1 ni p2, alors redirigez vers la page de configuration où il peut faire quelques entrées.

4) Si dans les deux profils, l'utilisateur sera invité à sélectionner un tableau de bord respectif

Maintenant, dans mon cas, le code que j'ai écrit ne fonctionne pas comme prévu. Même si je n'ai pas de compte dans "p2" mais que j'ai des comptes dans "p1", cela m'amène à la page de configuration. Quelqu'un peut-il aider ce qui ne va pas dans ce code?

Notez que la récupération d'appel fonctionne très bien! Cela me donne un éventail d'articles. Si aucun élément n'est présent, il renvoie un tableau vide

// On login 
  handleLogin = async () => {
        // after successful signin
        await Promise.all([
          this.setDashboard("p1"),
          this.setDashboard("p2"),
        ]);
        this.navigateToDashboards();
  };

   setDashboard = async (profile) => {
    let response, value;
    let type = profile;
    if (type === "p1") {
      response = await this.fetchUserAccounts(type);
      value = !!response && response.length ? true : false;
      this.setState({ isP1: value });
    } else {
      response = await this.fetchUserAccounts(cloudType);
      value = !!response && response.length ? true : false;
      this.setState({ isP2: value });
    }
  };

  fetchUserAccounts = async (type) => {
    try {
      let response = await fetch({
        url: "/fetch/entries",
        method: "POST",
        body: {
          profile: type,
        }
      );
      return response.json();
    } catch (error) {
      console.log(error);
    }
  };


    navigateToDashboards = () => {
    let { isP1, isP2 } = this.state;
    if (isP1 && isP2) {
      // CODE FOR PROMPTING WHICH DASHBOARD TO GO
    } else if (!isP1 && !isP2) {
      this.props.history.push("/configpage"); 
    } else if (isP1) {
      this.props.history.push("/p1dashboard");
    } else if (isP2) {
      this.props.history.push("/p2dashboard");
    }
  };

0
vjr12 7 nov. 2019 à 18:26

2 réponses

Il y a quelques problèmes avec le code que vous avez écrit ci-dessus et ils vont probablement plus loin que nous ne pouvons le voir dans l'extrait de code - pourquoi avoir la logique pour le type de tableau de bord côté client au lieu de l'envoyer depuis le serveur?

Il existe également cloudType qui n'est pas spécifié dans la méthode setDashboard.

Je ne sais pas ce que vous essayez de réaliser, donc je suppose - vous devriez probablement utiliser fetchUserAccounts à l'intérieur componentDidMount et enregistrer la réponse dans l'état.

J'ai trouvé quelque chose comme ça avec un TODO: dans le code:

class X extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      p1: null,
      p2: null,
    };
  }

  async componentDidMount() {
    const [p1, p2] = await Promise.all([
      this.fetchUserAccounts('p1'),
      this.fetchUserAccounts('p1'),
    ]);
    // NOTE: setState has a second parameter, which is a callback – this way you make sure that the state has been updated – read more here:
    // https://reactjs.org/docs/react-component.html#setstate
    this.setState(s => ({ ...s, p1, p2 }), this.navigateToDashboards);
  }

  fetchUserAccounts = async (type) => {
    try {
      let response = await fetch({
        url: "/fetch/entries",
        method: "POST",
        body: {
          profile: type,
        },
      });
      return response.json();
    } catch (error) {
      console.log(error);
    }
  };

  navigateToDashboards = () => {
    const { history } = this.props;
    const { p1, p2 } = this.state;
    // TODO: Implement your logic how you decide 
    if (isP1 && isP2) {
      // CODE FOR PROMPTING WHICH DASHBOARD TO GO
      return;
    }
    if (isP1) return history.push('/p1dashboard');
    if (isP2) return history.push('/p2dashboard');
    return history.push('/configpage');
  }
}

Si cela ne fonctionne pas, regardez au moins la structure du code. Il y a des endroits où vous n'avez pas besoin de l'instruction else. Utilisez la version de fonction de setState. Utilisez la description d'objet / tableau. Vous devriez également probablement lire ce qui est false et true dans le monde JS sur la base des lignes !!response && response.length ? true : false; - ou peut-être qu'il y a quelque chose que je manque ici.

0
Ancinek 7 nov. 2019 à 16:07

Le problème est que vous utilisez async / await incorrectement.

await fonctionne sur les promesses: vous lui faites une promesse et il attend qu'il soit résolu / rejeté. Si vous ne lui faites pas de promesse, c'est comme si vous lui passiez une promesse immédiatement résolue.

Votre fonction setDashboard ne renvoie pas de promesse, donc ce qui se passe est que ce code:

await Promise.all([
          this.setDashboard("p1"),
          this.setDashboard("p2"),
        ]);

Se résout en fait immédiatement, mais les fonctions setDashboard ne sont pas exécutées avant this.navigateToDashboards();. Pourquoi? car ils sont définis comme asynchrones, ce qui les place dans la boucle d'événements. Vient ensuite le await, mais il se résout immédiatement car les fonctions à l'intérieur ne renvoient pas de promesse (enfin, c'est le cas, car c'est asynchrone, mais c'est comme écrire return promise.resolve() comme première ligne - donc le await ne fait rien que de placer la fonction dans la boucle d'événement) - et le code continue de s'exécuter de manière synchrone jusqu'à ce qu'il atteigne la fin de la fonction (par exemple, en exécutant this.navigateToDashboards();, et ne passe ensuite qu'à la boucle d'événement et exécutez les fonctions setDashboards.

Sur le même sujet, la ligne response = await this.fetchUserAccounts(type); a également une attente redondante, car fetchUserAccounts() ne renvoie pas de promesse.

Pour utiliser correctement async / wait- assurez-vous que votre fonction async renvoie une promesse, par exemple:

setDashboard = async (profile) => {
 return new Promise( resolve, reject => {
    let response, value;
    let type = profile;
    if (type === "p1") {
      response = await this.fetchUserAccounts(type);
      value = !!response && response.length ? true : false;
      this.setState({ isP1: value });
      resolve();
    } else {
      response = await this.fetchUserAccounts(cloudType);
      value = !!response && response.length ? true : false;
      this.setState({ isP2: value });
      resolve();
    }
  })
};

Comme pour fetchUserAccount:

fetchUserAccounts = async (type) => {
  return new Promise( resolve, reject => {
    try {
      let response = await fetch({
        url: "/fetch/entries",
        method: "POST",
        body: {
          profile: type,
        }
      );
      resolve(response.json());
    } catch (error) {
      console.log(error);
      reject(error);
    }
  }
};

Notez que vous devrez désormais gérer les refus de promesse à l'aide de .catch, sinon vous obtiendrez unhandled promise rejection error.

-1
Gibor 7 nov. 2019 à 15:52