Search code examples
reactjsauthenticationhttp-redirectreduxroutes

How can I redirect a user to a user-specific homepage after login ? The user-specific url should contain the _id of the user


class App extends Component {
  componentDidMount() {
    store.dispatch(loadUser());
  }

  render() {
    return (
      <React.Fragment>
        <AppNavbar />
        <div className="App">
          <Switch>
            <Route path="/not-found" component={NotFound} />
            <AuthRoute path="/profile/settings" type="private">
              <Profile />
            </AuthRoute>
            <AuthRoute path="/setup/school" type="private">
              <SchoolDetails />
            </AuthRoute>
            <AuthRoute path="/setup/team" type="private">
              <TeamManagement />
            </AuthRoute>
            <AuthRoute path="/create/teams" type="private">
              <TeamSetup />
            </AuthRoute>
            <AuthRoute path="/register/setup" type="guest">
              <ProfileSetup />
            </AuthRoute>
            <AuthRoute path="/events" type="private">
              <SimpleSlider />
            </AuthRoute>
            <AuthRoute path="/register" type="guest">
              <RegisterModal />
            </AuthRoute>
            <AuthRoute path="/login" type="guest">
              <LoginModal />
            </AuthRoute>

            <AuthRoute exact path="/" type="private">
              <SimpleSlider />
            </AuthRoute>

            <Redirect to="/not-found" />
          </Switch>
        </div>
      </React.Fragment>
    );
  }
}

const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated,
  user: state.auth.user,
});

export default connect(mapStateToProps)(App);

const AuthRoute = (props) => {
  const { isAuthenticated, user, type } = props;

  if (type == "guest" && isAuthenticated) {
    //history.replace(`${lo}/${user._id}`);
    return <Redirect to={`/events/${user._id}`} />;
  } else if (type == "private" && !isAuthenticated)
    return <Redirect to={`/login`} />;
  return <Route {...props} />;
};

const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated,
  userloaded: state.auth.userloaded,
  user: state.auth.user,
});

export default connect(mapStateToProps)(AuthRoute);

const initialState = {
  token: localStorage.getItem("token"),
  isAuthenticated: null,
  userloaded: false,
  isLoading: false,
  user: null,
};

export default function (state = initialState, action) {
  switch (action.type) {
    case USER_LOADING:
      return {
        ...state,
        isLoading: true,
      };
    case USER_LOADED:
      return {
        ...state,
        user: action.payload,
        userloaded: true,
        isAuthenticated: true,
        isLoading: false,
      };
    case LOGIN_SUCCESS:
    case REGISTER_SUCCESS:
      localStorage.setItem("token", action.payload.token);
      return {
        ...state,
        userloaded: true,
        isAuthenticated: true,
        isLoading: false,
        ...action.payload,
      };
    case AUTH_ERROR:
    case LOGIN_FAIL:
    case LOGOUT_SUCCESS:
    case REGISTER_FAIL:
      localStorage.removeItem("token");
      return {
        ...state,
        token: null,
        user: null,
        userloaded: false,
        isAuthenticated: false,
        isLoading: false,
      };
    default:
      return state;
  }
}

export const loadUser = () => (dispatch, getState) => {
  // User loading
  dispatch({ type: USER_LOADING });

  axios
    .get("/api/auth/user", tokenConfig(getState))
    .then((res) =>
      dispatch({
        type: USER_LOADED,
        payload: res.data,
      })
    )
    .catch((err) => {
      dispatch(returnErrors(err.response.data, err.response.status));
      dispatch({ type: AUTH_ERROR });
    });
};

// Register User
export const register =
  ({ name, email, password }) =>
  (dispatch) => {
    // Headers
    const config = {
      headers: {
        "Content-Type": "application/json",
      },
    };

    //Request body
    const body = JSON.stringify({ name, email, password });

    axios
      .post("/api/users", body, config)
      .then((res) =>
        dispatch({
          type: REGISTER_SUCCESS,
          payload: res.data,
        })
      )
      .catch((err) => {
        dispatch(
          returnErrors(err.response.data, err.response.status, "REGISTER_FAIL")
        );
        dispatch({
          type: REGISTER_FAIL,
        });
      });
  };

// Login User
export const login =
  ({ email, password }) =>
  (dispatch) => {
    // Headers
    const config = {
      headers: {
        "Content-Type": "application/json",
      },
    };

    //Request body
    const body = JSON.stringify({ email, password });

    axios
      .post("/api/auth", body, config)
      .then((res) =>
        dispatch({
          type: LOGIN_SUCCESS,
          payload: res.data,
        })
      )
      .catch((err) => {
        dispatch(
          returnErrors(err.response.data, err.response.status, "LOGIN_FAIL")
        );
        dispatch({
          type: LOGIN_FAIL,
        });
      });
  };

// Logout User
export const logout = () => {
  return {
    type: LOGOUT_SUCCESS,
  };
};

// Setup config/headers and token
export const tokenConfig = (getState) => {
  // Get token from localstorage
  const token = getState().auth.token;

  // Headers
  const config = {
    headers: {
      "Content-type": "application/json",
    },
  };

  // If token, add to headers
  if (token) {
    config.headers["x-auth-token"] = token;
  }

  return config;
};

My problem is that whenever a user logs in to my application he gets redirected to the homepage, but my "_id" from the redux store is undefined. First, after refreshing the page he get redirected to the URL including the correct user id. For example, after login => user gets redirected to "/events/undefined" after another manual refresh => the URL changes to "/events/62a6503c9e8a60254ed94ff1"

sidenote: whenever the application gets refreshed the login site shows up for a split second. This is another unintentional behavior.


Solution

  • just for the sake of testing , may be you should try and check for the user object when you redirect ? like so:

    const AuthRoute = (props) => {
      const { isAuthenticated, user, type } = props;
    
      if (type == "guest" && isAuthenticated && user._id) {
        //history.replace(`${lo}/${user._id}`);
        return <Redirect to={`/events/${user._id}`} />;
      } else if (type == "private" && !isAuthenticated)
        return <Redirect to={`/login`} />;
      return <Route {...props} />;
    };
    
    const mapStateToProps = (state) => ({
      isAuthenticated: state.auth.isAuthenticated,
      userloaded: state.auth.userloaded,
      user: state.auth.user,
    });