J'essaye de sortir l'état Redux du magasin global et quand j'utilise useSelector dans un WithAuth HOC, je n'obtiens pas l'état approprié. Sur mon état global, il y a deux clés: currentUser et currentUser.isAuthenticated.

Dans mes outils de développement Redux, la clé isAuthenticated montre qu'elle a la valeur true, mais lorsque j'utilise le hook, j'obtiens false.

J'ai jeté un œil à la documentation officielle, mais je n'ai pas pu trouver tout ce qui pourrait m'aider, si je l'ai lu correctement.

Quelqu'un pourrait-il me dire ce que je fais de mal? Je suis nouveau dans l'utilisation des hooks pour Redux. Merci.

withAuth.tsx

import   React,
       { useEffect }          from "react";
import { useSelector }        from "react-redux";
import { useHistory }         from "react-router-dom";
import { Routes }             from "../../constants/RoutesNames";
import { DefaultRootState }   from "../../store/reducers";

interface Props
{
    ComponentToBeRendered: React.FC<unknown>
    props?: any
};

const stateSelector = (state: DefaultRootState) => state.currentUser.isAuthenticated;

const WithAuth : React.FC<Props> = ({ ComponentToBeRendered, props }) =>
{

    const isAuthenticated = useSelector<DefaultRootState, boolean>(stateSelector);
    const history         = useHistory();

    useEffect(() =>
    {
        if (!isAuthenticated)  history.push(Routes.SIGN_IN);

    }, [ isAuthenticated, history ]);

    return (
        <ComponentToBeRendered {...props} />
    )
}

export default WithAuth;

0
StackMatch 7 oct. 2020 à 03:35

2 réponses

Meilleure réponse

Il s'avère que le hook useSelector fait une double prise sur l'état Redux. Si vous console.log (console.log("Got isAuth", isAuthenticated);) à l'intérieur du hook useEffect, vous verrez que le premier journal sera Got isAuth false et le second Got isAuth true.

Je ne sais pas si c'est toute l'histoire, mais pour l'instant j'ai réimplémenté WithAuth pour accepter un élément rendu plutôt qu'un composant à rendre. Et puis je retourne conditionnellement cet élément ou ma page de connexion rendue. Donc,

import   React                from "react";
import { useSelector }        from "react-redux";
import   AuthFlow             from "../../pages/AuthFlow";
import { DefaultRootState }   from "../../store/reducers";

interface Props
{
    ComponentToBeRendered: React.ReactElement;
};

const isAuthenticatedSelector = (state: DefaultRootState) => state.currentUser.isAuthenticated;

const WithAuth : React.FC<Props> = React.memo(({ ComponentToBeRendered }) =>
{

    const isAuthenticated = useSelector<DefaultRootState, boolean>(isAuthenticatedSelector);

    return (
      isAuthenticated ? ComponentToBeRendered : <AuthFlow />
    )
})

export default WithAuth;

Je ne sais pas si c'est la meilleure approche, mais j'ai trouvé une solution de contournement pour le moment. Étrange que useSelector ne puisse pas simplement obtenir l'état Redux correctement à la première exécution. Peut-être que je manque quelque chose que quelqu'un peut me montrer.

=========== MODIFIER ===========

J'ai réfléchi un peu plus à cela et je pense que cette approche pourrait être légèrement meilleure pour diverses raisons

import   React                from "react";
import { useSelector }        from "react-redux";
import   BasicTextLink        from "../../components/BasicLink/BasicLink";
import { Routes }             from "../../constants/RoutesNames";
import { DefaultRootState }   from "../../store/reducers";

interface Props
{
    ElementToBeShown: React.ReactElement;
};

const isAuthenticatedSelector = (state: DefaultRootState) => state.currentUser.isAuthenticated;

const WithAuth : React.FC<Props> = React.memo(({ ElementToBeShown }) =>
{

    const isAuthenticated = useSelector<DefaultRootState, boolean>(isAuthenticatedSelector);

    return (
      isAuthenticated ? ElementToBeShown : <h2>You are not signed in. Please {
        <BasicTextLink baseColor useHoverEffect darkHover to={Routes.SIGN_IN} underline={"hover"}>
          sign in
        </BasicTextLink>
        } first</h2>
    )
});

export default WithAuth;
0
StackMatch 7 oct. 2020 à 19:50

Qu'entendez-vous par la mauvaise valeur? Pourriez-vous ajouter plus d'informations sur le problème?

N'oubliez pas que vous pouvez raccourcir le retour d'une instruction comme celle-ci pour garder le code plus propre:

   const stateSelector = (state: DefaultRootState) => state.currentUser.isAuthenticated
0
Agustin Moles 7 oct. 2020 à 00:41