7

I am new to react and still learning my way around. I am creating a single page app where the user is redirected to the login page if he is not logged in. React has a Redirect component and I am not sure how to use it.

Following is my app.js :-

import React, { Component } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import Login from './components/login/login.js'
import Protected from './components/protected/protected.js'

import './App.css';

class App extends Component {

  state = {
    loggedIn: false // user is not logged in
  };

  render() {

    return (
        <Switch>
          <Route path="/protected" component={Protected}/>
          <Route path="/login" component={Login}/>
        </Switch>
    );
  }
}

export default App;

In the above scenario, I want the user to be redirected to the /login page if the state loggedIn is false or else it should go to the /protected page.

Alexis Wilke
  • 15,168
  • 8
  • 60
  • 116
  • 2
    Possible duplicate of [Simple Conditional Routing in Reactjs](https://stackoverflow.com/questions/48497510/simple-conditional-routing-in-reactjs) – saman.shahmohamadi Jan 08 '19 at 12:15

2 Answers2

7

I usually create a PrivateRoute component that checks if the user is logged in (via prop, redux, localstorage or something).

Something like:

const PrivateRoute = ({ isLoggedIn, ...props }) =>
  isLoggedIn
    ? <Route { ...props } />
    : <Redirect to="/login" />

In the router I then use it for my, well, private routes :)

<Switch>
  <PrivateRoute isLoggedIn={ this.state.loggedIn } path="/protected" component={Protected} />
  <Route path="/login" component={Login}/>
</Switch>
0xc14m1z
  • 3,387
  • 1
  • 12
  • 22
  • 1
    how do you pass the current value of isLoggedIn to the component if you have to dispatch an action to check the state - and that is async? – zero_cool Jun 29 '19 at 20:06
  • 1
    You can just connect the root component to redux. By default, `isLoggedIn` will be `false`. When you reach the login page and perform the login, it will be set to `true`. – 0xc14m1z Jul 01 '19 at 09:33
0

you can do the following by redux-saga,

import jwt_decode from 'jwt-decode';

//define you saga in store file here
import {store, history} from './store';

// Check for token
if (localStorage.jwtToken) {
// Set auth token header auth
setAuthToken(localStorage.jwtToken);
// Decode token and get user info and exp
const decoded = jwt_decode(localStorage.jwtToken);
// Set user and isAuthenticated
store.dispatch(setCurrentUser(decoded));

// Check for expired token
const currentTime = Date.now() / 1000;
if (decoded.exp < currentTime) {
    // Logout user
    store.dispatch(logoutUser());
    // Clear current Profile
    store.dispatch(clearCurrentProfile());
    // Redirect to login
    window.location.href = '/login';
}
}
const setAuthToken = token => {
if (token) {
// Apply to every request
axios.defaults.headers.common['Authorization'] = token;
} else {
// Delete auth header
delete axios.defaults.headers.common['Authorization'];
}
};

  // Set logged in user
export const setCurrentUser = decoded => {
return {
  type: SET_CURRENT_USER,
  payload: decoded
 };
};

// Clear profile
const clearCurrentProfile = () => {
return {
  type: CLEAR_CURRENT_PROFILE
};
};

  // Log user out
const logoutUser = () => dispatch => {
// Remove token from localStorage
localStorage.removeItem('jwtToken');
// Remove auth header for future requests
setAuthToken(false);
// Set current user to {} which will set isAuthenticated to false
dispatch(setCurrentUser({}));
};

// render part 
 render() {
    return (
        <Provider store={store}>
              <ConnectedRouter history={history}>
                {/* Switch stops searching for the path once the match is found */}
                 <Switch>
                    {/* <div> */}
                    <Route exact path="/"  component={Landing} />
                    <Route exact path="/signup" component={Signup} />
                    <Route exact path="/login" component={Login} />
                    <Route exact path="/forgotpassword" component={ForgotPassword} />
                    <Route exact path="/not-found" component={NotFound} />
                    <Route exact path="/resetpassword" component={ResetPassword} />
                    {/* Do not pass 'exact' props. It won't match /dashboard/other_url */}
                    <Route path="/dashboard" component={DefaultLayout} />
                    {/* </div> */}
                </Switch>
            </ConnectedRouter>
        </Provider>
    );

}

// .store file if you need
    import { createBrowserHistory } from 'history'
import {createStore, applyMiddleware } from  'redux';
import { routerMiddleware } from 'connected-react-router'
import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
import createSagaMiddleware from 'redux-saga'


import rootReducer from './reducers'
import rootSaga from './sagas/';

export const history = createBrowserHistory();
const sagaMiddleware = createSagaMiddleware()

const myRouterMiddleware = routerMiddleware(history);

const initialState = {};

const middleWare = [myRouterMiddleware,sagaMiddleware];

export const store = createStore(rootReducer(history), 
    initialState,
    composeWithDevTools(applyMiddleware(...middleWare))
);

sagaMiddleware.run(rootSaga);
Ram Budha
  • 170
  • 1
  • 11