Como usar o React Routes with conditions e Redux?

Oct 03 2020

Estou lutando para criar uma autenticação com React Redux e Routes.

Dependendo da variável responsável pela autenticação, o usuário obtém um determinado conjunto de rotas. Mas no momento do carregamento inicial, quando a variável ainda não recebeu um valor da loja redux, as rotas são exibidas para um usuário não conectado, ou seja, a página de registro, e somente então as páginas necessárias.

Acontece que toda vez que você atualizar a página de registro pisca.

Código em routes.js:

export const RotesPage = ({ isAuthenticated }) => {
  if (isAuthenticated) {
    return (
      <div>
        <Switch>
          <Route path="/" exact>
            <MainPage />
          </Route>
          <Route path="/schedule" exact>
            <SchedulePage />
          </Route>
          <Route path="/tasks" exact>
            <TasksPage />
          </Route>
          <Route path="/money" exact>
            <MoneyPage />
          </Route>
          <Redirect to="/" />
        </Switch>
      </div>
    );
  }

  if (!isAuthenticated) {
    return (
      <Switch>
        <Route path="/login" exact>
          <LoginPage />
        </Route>
        <Route path="/register" exact>
          <RegisterPage />
        </Route>
        <Redirect to="/login" />
      </Switch>
    );
  }
};

Código em App.js:

import React, { useEffect } from "react";
import { BrowserRouter as Router } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { loadUser } from "./actions/authAction"; 
import { AppNavbar } from "./layouts/components/AppNavbar";
import { RotesPage } from "./routes";

const App = () => {
  const dispatch = useDispatch(); 
  const auth = useSelector((state) => state.auth);
  const isAuthenticated = auth.isAuthenticated;

  useEffect(() => {
    dispatch(loadUser());
  }, [dispatch]);

  return (
    <Router>
      {isAuthenticated && <AppNavbar />}
      <RotesPage isAuthenticated={isAuthenticated} />
    </Router>
  );
};

export default App;

Como posso corrigir isso?

PS Desculpe se eu descrevo mal, porque estou aprendendo não só linguagens de programação, mas também inglês.

PPS É meu primeiro Q aqui.

Obrigado antecipadamente =)

Respostas

Uma Oct 03 2020 at 00:31

Em seu redux state defina a isLoadingvariável que inicialmente será true, uma vez que você obtenha os dados de autenticação, defina-a como false.

Então, em seu aplicativo, você pode fazer algo como:

  const auth = useSelector((state) => state.auth);
  const isAuthenticated = auth.isAuthenticated;
  const isLoading = auth.isLoading;

<Router>
  {isLoading ? (
    <div>Loading...</div>
  ): (
    <>
      {isAuthenticated && <AppNavbar />}
      <RotesPage isAuthenticated={isAuthenticated} />
    </>
  )}
</Router>