Reputation: 8297
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
Reputation: 76
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
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