I want to know how to convert my React code to React Native using AsyncStorage. I have tried the below code but I am getting "undefined" for "isAuthenticated" and also an "error" in "JSON.parse(AsyncStorage.getItem('token')". I want to use the "isAuthenticated" value to show only a particular part of a Component.
React Code:
export const Auth = (state = {
isLoading: false,
isAuthenticated: localStorage.getItem('token') ? true : false,
token: localStorage.getItem('token'),
user: localStorage.getItem('creds') ? JSON.parse(localStorage.getItem('creds')) : null,
errMess: null
}, action) => {
switch (action.type) {
case ActionTypes.LOGIN_REQUEST:
return {...state,
isLoading: true,
isAuthenticated: false,
user: action.creds
};
case ActionTypes.LOGIN_SUCCESS:
return {...state,
isLoading: false,
isAuthenticated: true,
errMess: '',
token: action.token
};
case ActionTypes.LOGIN_FAILURE:
return {...state,
isLoading: false,
isAuthenticated: false,
errMess: action.message
};
case ActionTypes.LOGOUT_REQUEST:
return {...state,
isLoading: true,
isAuthenticated: true
};
case ActionTypes.LOGOUT_SUCCESS:
return {...state,
isLoading: false,
isAuthenticated: false,
token: '',
user: null
};
default:
return state
}
}
My code in React Native:
import * as ActionTypes from './ActionTypes';
// The auth reducer. The starting state sets authentication
// based on a token being in local storage. In a real app,
// we would also want a util to check if the token is expired.
export const auth = (state = {
isLoading: false,
isAuthenticated: false,
token: null,
user: null,
errMess: null
}, action) => {
switch (action.type) {
case ActionTypes.GET_AUTH:
return {
...state,
...action.payload
};
case ActionTypes.LOGIN_REQUEST:
return {
...state,
isLoading: true,
isAuthenticated: false,
user: action.creds
};
case ActionTypes.LOGIN_SUCCESS:
return {
...state,
isLoading: false,
isAuthenticated: true,
errMess: '',
token: action.token
};
case ActionTypes.LOGIN_FAILURE:
return {
...state,
isLoading: false,
isAuthenticated: false,
errMess: action.message
};
case ActionTypes.LOGOUT_REQUEST:
return {
...state,
isLoading: true,
isAuthenticated: true
};
case ActionTypes.LOGOUT_SUCCESS:
return {
...state,
isLoading: false,
isAuthenticated: false,
token: '',
user: null
};
default:
return state
}
}
Thanks in advance.
Edit: This my updated code.
export const getAuth = () => {
return async(dispatch) => {
const [token, creds] = await Promise.all([
AsyncStorage.getItem('token'),
AsyncStorage.getItem('creds')
])
dispatch({
type: ActionTypes.GET_AUTH,
payload: {
isLoading: false,
isAuthenticated: !!token,
token: token,
user: JSON.parse(creds),
errMess: null
}
});
}
}
export const loginUser = (creds) => (dispatch) => {
// We dispatch requestLogin to kickoff the call to the API
dispatch(requestLogin(creds))
return fetch(baseUrl + 'users/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(creds)
})
.then(response => {
if (response.ok) {
return response;
} else {
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
throw error;
})
.then(response => response.json())
.then(response => {
if (response.success) {
async() => {
try {
await AsyncStorage.setItem('token', response.token);
await AsyncStorage.setItem('creds', JSON.stringify(creds));
} catch (error) {
// Error saving data
}
}
// If login was successful, set the token in local storage
//AsyncStorage.setItem('token', response.token);
//AsyncStorage.setItem('creds', JSON.stringify(creds));
// Dispatch the success action
dispatch(fetchSaves());
dispatch(receiveLogin(response));
} else {
var error = new Error('Error ' + response.status);
error.response = response;
throw error;
}
})
.catch(error => dispatch(loginError(error.message)))
};
I think you should leave initialState with default values, use redux-thunk and dispatch an action at the start of the app to get auth data.
const getAuth = () => {
return async (dispatch) => {
const [token, user] = await Promise.all([
AsyncStorage.getItem('token'),
AsyncStorage.getItem('creds')
])
dispatch({
type: 'GET_AUTH',
payload: {
isLoading: false,
isAuthenticated: !!token,
token,
user: JSON.parse(creds),
errMess: null
}
});
}
}
const App = connect({}, {getAuth})(({getAuth}) => {
useEffect(() => {
getAuth();
}, [])
return ...
})
export const auth = async (state = {
isLoading: false,
isAuthenticated: false,
token: null,
user: null,
errMess: null
}, action) => {
switch (action.type) {
case ActionTypes.GET_AUTH:
return {
...state,
...action.payload
};
...
}