Dawn17
Dawn17

Reputation: 8297

User authentication with Axios using React-Redux

I am trying to make a transition to redux in developing my web app.

I realized that after I specify the types in my actions, I can dispatch it to my reducers and the reducers will perform changes based on the types of the actions.

I have two actions that looks like this:

export const doLogin = (username, password) => {
    return {
        type: types.AUTH_LOGIN,
        username,
        password
    };
};

export const doLogout = () => ({
  type: types.AUTH_LOGOUT,
});

I can dispatch these two actions to my reducer that looks like:

const initialState = {
  username: "",
  isLoggedIn: false
};

const authReducer = (state = initialState, action) => {
  switch (action.type) {
    case types.AUTH_LOGIN:
      return {
        ...state, // Preserve states that are unchanged
        username: action.username, // Values to be changed
        isLoggedIn: true
      };
    case types.AUTH_LOGOUT:
      return initialState;
    default:
      return state;
  }
};

My reducer currently just creates a new state username: username, isLoggedin: true and returns it. It has NOTHING to do with actual user authentication.

Before switching to Redux, I did my user authentication by calling an API Post using Axios.

The code looked like:

 axios.post('http://localhost:5000/signin', 
 {
     username:this.state.username, 
     password:this.state.password
 })
     .then(function (response) {

     console.log(response);
     if(response.data.status === "Successful"){
         console.log("Login successfull");
         this.setState({loggedOn:true})
     }

     else{
         console.log("There is no user with the given username and password");
         //alert("Username does not exist");
     }
     }
 )
 .catch(function (error) {

 console.log(error);
 });

I am not sure how and where this has to be incorporated to Redux. Do I have to put it into my reducers, or actions?

Please help.

EDIT

I am already using redux-thunk

store.js

import rootReducer from "../reducers";
import ReduxThunk from "redux-thunk";

const middlewares = [ReduxThunk];
const store = createStore(rootReducer, applyMiddleware(...middlewares));

index.js

import store from "./store";
import { createStore } from 'redux';
import reducers from './reducers';
import { Provider } from 'react-redux';


console.log('init state', store.getState());
store.subscribe(()=>console.log(store.getState()));
store.dispatch(actions.doLogin('sample', '1234'));

actions.doLogin gives me the error Actions must be plain objects. Use custom middleware for async actions.

Upvotes: 0

Views: 3983

Answers (2)

I use the dispatch function as below

export const doLogin = (username, password) => {
    return dispatch => {
        axios.post('http://localhost:5000/signin', {
            username: username,
            password: password
        })
        .then((response)=>{
            dispatch({
                type: AUTH_LOGIN,
                username: response.username
            })
        })
        .catch((error)=>{
            console.log("There is no user with the given username and password");
            //alert("Username does not exist");
        })
    };
};

Upvotes: 3

reisdev
reisdev

Reputation: 3403

The reducers just receive the state change. So, your action should contain the authentication. Then, when it's complete and the user was authenticated, it returns to the reducer. Like this:

export const doLogin = (username, password) => {
     var auth = false
     axios.post('http://localhost:5000/signin', 
     {
         username:this.state.username, 
         password:this.state.password
     }).then(response => {
         console.log(response);
         if(response.data.status === "Successful"){
             console.log("Login successfull");
             auth = true;
         }
         else{
             console.log("There is no user with the given username and password");
             //alert("Username does not exist");
         }
      }).catch(function (error) {
           console.log(error);
      });
      if(auth) return {
             type: types.AUTH_LOGIN,
             username,
             password
      }
};

export const doLogout = () => ({
  type: types.AUTH_LOGOUT,
});

Advise: That's not a good pratice. It's better to maintain the authentication in a script or inside the component. Then, when it's sucessful, it emmits the action to the Redux. I'd tried this a couple times, and noticed that it's not the best way.

Upvotes: 1

Related Questions