0

I have been working on a react project and I ran into a problem about 4 days ago. When I try to open a link in a new tab, it redirects to the home/BASE url. Please I need assistance fixing the bug.

render route method

export const renderRoutes = (routes = []) => (
  <Suspense fallback={<Loader />}>
    <Switch>
      {routes.map((route, i) => {
        const Guard = route.guard || Fragment;
        const Layout = route.layout || Fragment;
        const Component = route.component;

        return (
          <Route
            key={i}
            path={route.path}
            exact={route.exact}
            render={(props) => (
              <Guard>
                <Layout>
                  {route.routes
                    ? renderRoutes(route.routes)
                    : <Component {...props} />}
                </Layout>
              </Guard>
            )}
          />
        );
      })}
    </Switch>
  </Suspense>
);

Picture of Guest Route

Picture of the Admin Route

GuestGuard

const GuestGuard = (props) => {
  console.log(props, BASE_URL)
  if (props.isLoggedIn) {
    console.log(BASE_URL)
    return <Redirect to={BASE_URL} />;
  }

  return (
    <React.Fragment>
      {props.children}
    </React.Fragment>
  );
};

GuestGuard.propTypes = {
  isLoggedIn: PropTypes.bool.isRequired
}

const mapStateToProps = (state) => ({
  isLoggedIn: state.auth.isLoggedIn
})

export default connect(mapStateToProps, )(GuestGuard);

AuthGuard

const AuthGuard = ({ children, isLoggedIn }) => {
    // console.log(children, 393)
    if (!isLoggedIn) {
        return <Redirect to="/auth/signin-1" />;
    }
    console.log("LOGGED IN", children.props)
    return (
        <React.Fragment>
            {children}
        </React.Fragment>
    );
};

AuthGuard.propTypes = {
    isLoggedIn: PropTypes.bool.isRequired
  }

const mapStateToProps = (state) => ({
    isLoggedIn: state.auth.isLoggedIn
})

export default connect(mapStateToProps, )(AuthGuard);

App (the provider is from react-redux)

const App = () => {
  useEffect(() => {
    store.dispatch(init());
  }, [])
  return (
    <Provider store={store}>    
        <Router basename={BASENAME}>          
          <React.Fragment>
            {renderRoutes(routes)}            
          </React.Fragment>
        </Router>
    </Provider>
  );
};

export default App;

init method called in the useEffect

export const init = () => (dispatch) => {
    try {
      const serviceToken = window.localStorage.getItem('serviceToken');        
      if (serviceToken) {
        setSession(serviceToken);
        axios.get('http://localhost:8000/api/auth/user', tokenConfig())
        .then(response => {         
          const user = response.data;
          dispatch({
            type: ACCOUNT_INITIALISE,
            payload: {
              isLoggedIn: true,
              user
            }
          })
        }).catch(err=>{
          dispatch({
            type:LOGOUT
          })
        })
      } else {
        dispatch({
          type: ACCOUNT_INITIALISE,
          payload: {
            isLoggedIn: false,
            user: null
          }
        });
      }
    } catch (err) {
      console.error(err);
      dispatch({
        type: ACCOUNT_INITIALISE,
        payload: {
          isLoggedIn: false,
          user: null
        }
      });
    }
  };

store (in the same dir as App.js)

import {createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers/index'

const initialState = {};

const middleware = [thunk];

const store = createStore(
    rootReducer,
    initialState,
    compose(
      applyMiddleware(...middleware),
      window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    )
  );

export default store;

auth reducer

const initialState = {
  isLoggedIn: false,
  isInitialised: false,
  user: null
};
  
export default function (state = initialState, action) {
  switch (action.type) {
    case ACCOUNT_INITIALISE: {
        const { isLoggedIn, user } = action.payload;
        return {
            ...state,
            isLoggedIn,
            isInitialised: true,
            user
        };
    }
    case LOGIN: {
        const { user } = action.payload;
        return {
            ...state,
            isLoggedIn: true,
            user
        };
    }
    case LOGOUT: {
        localStorage.removeItem('serviceToken');
        return {
            ...state,
            isLoggedIn: false,
            user: null
        };
    }
    default: {
        return { ...state };
    }
}
  }
Fornow
  • 69
  • 1
  • 9

1 Answers1

1

I think you need to debug the application flow here. Below appears to be root cause, When link opens in new tab, it is protected by authGuard and the "init method called in the useEffect" is calling api asynchronously. So authGuard gets isloggedIn false the first time and redirects to "/auth/signin-1". Meantime, isloggedIn sets as true and guestGuard redirects to Login page.

You have below option here: Do not load your router unless you get response from api. Display a loader while you get response.

Hope you get the bug here and this answer helps you to fix same.

Aman
  • 11
  • 2