Reputation: 121
I am implementing login page using react native and redux. Here is my a sample code for my reducer. There are three type; types.SUBMIT_LOGIN, types.CHANGE_USERNAME, types.CHANGE_PASSWORD.
CHANGE_USERNAME and CHANGE_PASSWORD is working fine. But the problem is SUBMIT_LOGIN.I guess it's because of async state changes. There there anyway to change state after using fetch() method??
export default function login(state = initialState, action = {}) {
switch (action.type) {
case types.SUBMIT_LOGIN: {
let loginStatus = false;
if (state.username != null && state.password != null
&& state.username.length > 0 && state.password.length > 0
&& state.username === state.password) {
loginStatus = true;
} else {
let updatedErrMsg = '';
fetch('https://staging-barrie.mpower.ca/mpower/mpp/weblogin2.action?username='+state.username+'&password='+state.password,
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36',
},
}
)
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.result === 'success') {
loginStatus = true;
} else {
loginStatus = false;
updatedErrMsg = 'Incorrect Username or Password.';
}
return {
...state,
isLoggedIn: loginStatus,
errorMsg: updatedErrMsg
};
});
}
return {
...state,
isLoggedIn: loginStatus
};
}
case types.CHANGE_USERNAME:
return {
...state,
username: action.username
};
case types.CHANGE_PASSWORD:
return {
...state,
password: action.password
};
default:
return state;
} }
Upvotes: 0
Views: 70
Reputation: 66
I believe you can achieve this by using Thunk middleware:
https://github.com/gaearon/redux-thunk.
Using this, you can make an async action creator that will eventually dispatch an action to update the state. By creating the action before feeding it into the reducer you should circumvent whatever issue you're having here.
First you'll define a simple action
const submitLogin(loginStatus, errorMessage){
return {
type: SUBMIT_LOGIN,
loginStatus,
errorMessage
}
}
Then you'll create the async action that will eventually dispatch that action, passing in the results of your fetch as arguments
const thunk = ()=>{
return (dispatch, getState)=> {
<async action goes here>
dispatch(submitLogin(loginStatus, errorMessage));
}
}
You can then build a much simpler action in your reducer that updates the state based on the simple action you feed in. You'll want to import the thunk action creator wherever you're using it in your code.
Upvotes: 2
Reputation: 16482
You should avoid using async call inside reducer. You should have a separate method which does async call and when that call is finished, it will dispatch an action (in your case SUBMIT_LOGIN
) accordingly.
Keep a separate function and dispatch an action when request is complete like this
function loginUser () {
let loginStatus = false;
if (state.username != null && state.password != null
&& state.username.length > 0 && state.password.length > 0
&& state.username === state.password) {
loginStatus = true;
} else {
let updatedErrMsg = '';
fetch('https://staging-barrie.mpower.ca/mpower/mpp/weblogin2.action?username='+state.username+'&password='+state.password,
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36',
},
}
)
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.result === 'success') {
loginStatus = true;
} else {
loginStatus = false;
updatedErrMsg = 'Incorrect Username or Password.';
}
// Request is complete so dispatch an action.
dispactch({type: types.SUBMIT_LOGIN, payload: {loginStatus,updatedErrMsg }})
})
}
And keep your reducer clean. It should return a new state according to action.type
export default function login(state = initialState, action = {}) {
switch (action.type) {
case types.SUBMIT_LOGIN:
return {
...state,
isLoggedIn: action.payload.loginStatus,
errorMsg: action.paylod.updatedErrMsg
};
case types.CHANGE_USERNAME:
return {
...state,
username: action.username
};
case types.CHANGE_PASSWORD:
return {
...state,
password: action.password
};
default:
return state;
Upvotes: 1