reactjsreduxreact-router-domdispatch

React + Redux dispatching 3 times an action at render of App.js


I'm having some problems with this slice of code, I'm using Redux for state management. The behavior I expect is to use the dispatcher (the one with the comment) once the user is logged in (so just once!) but it is called three times at every render of App.js The action contains an API call, so I got three API calls! I don't get how to make it trigger just once. Any idea of the problem?

import React from 'react';
import {
  Route, Switch, Redirect,
} from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import Login from './components/auth/login';
import Dashboard from './components/Dashboard';    
import * as actions from './store/actions/indexActions';


export default function App() {
   const isAuthenticated = useSelector((state) => state.auth.isAuthenticated);
   const jwt = useSelector((state) => state?.auth?.user?.token);
   const dispatch = useDispatch();
   if (isAuthenticated) {
      dispatch(actions.getRole(jwt));  //THIS DISPATCHER IS CALLED 3 TIMES
   }
   return(
      <Provider store={store}>
         <BrowserRouter basename="/">
            <Switch>
               <Route path="/login" exact>
                  {isAuthenticated ? <Redirect to="/" /> : <Login />}
               </Route>
               <Route exact path="/">
                  {isAuthenticated ? <Dashboard /> : <Redirect to="/login" />}
               </Route>
            </Switch>
        </BrowserRouter>
     </Provider>
   )
}

Solution

  • You currently dispatch it every time the component renders. If you want it to be called only when the user gets logged in, you need to wrap the call in a useEffect like this:

    useEffect(() => 
       if (isAuthenticated) {
          dispatch(actions.getRole(jwt)); 
       }
    }, [isAuthenticated]);
    

    Now, the code inside the useEffect will run only when isAuthenticated changes.