I'm making very simple Login app for learning react and react-native also, my goal is get user input, then compare these value to a custom fake api file that contain user and password value, then save in AsyncStorage
(or localStorage
) for authentication . So i search the internet for what i'm going to do, here is the one that match what i'm looking for , but there are few things i really don't understand how this code work. In this code, there are something make me confuse for week, so many question in my head so i really need some help. Here is the code:
First he has a Redux Action like this in his code
//Action.js
export const LoginRequested = (username,password) => {
return {
type: 'LOG_IN_REQUEST',
data: {
username,
password,
},
};
};
export const LoginSuccessed = (data) => {
return {
type: 'LOGIN_SUCCESS',
data,
};
};
export const LoginFailed = (data) => {
return {
type: 'LOG_IN_FAILURE',
data,
};
};
export const Logout = (data) => {
return {
type: 'LOG_OUT',
data
};
};
But what make me confuse is
Question 1: what is data
here? What is this data
used for?
I mean i can understand that in LoginRequested
, data is username and password, so i guess username and password store here, but in loginSuccessed
and LoginFailed
, i don't get it, what is data here
Here is the Reducer
const initialState = {
isLoading: false,
authen: false
};
export const loginReducer = (state = initialState, action) => {
switch (action.type) {
case 'LOG_IN_REQUEST':
{
//console.log('action : LOG IN REQUEST');
return {
isLoading: true,
authen: false
}
}
case 'LOG_IN_SUCCESS':
{
//console.log('action : LOG IN SUCCESS');
return {
isLoading: false,
authen: true
};
}
case 'LOG_IN_FAILURE':
{
//console.log('action : LOG IN FAILURE');
return initialState;
}
case 'LOG_OUT':
{
//console.log('action : LOG OUT');
return initialState;
}
default:
return state;
}
};
And to the reducer, so :
Question 2: what do isLoading
and authen( maybe authentication)
do ?? .
I can understand it present for login status, is that right? but i can't link how he use there code( i see him use 'LOGIN_SUCCESS' once in saga below but i don't get it)
Here is the store:
//store.js
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware)); //rootReducer is a combined reducer file, i don't show it here, but he have only one Reducer like above code
sagaMiddleware.run(rootSaga);
export default store;
I understand this, this is how redux apply middleware.
Now is Saga part
//saga.js
import { Alert } from 'react-native';
import { call, put, takeLatest } from 'redux-saga/effects';
//import axios from 'axios';
import { fetchLoginData } from '../../server/loginApi';
export function* loginMainSaga() {
yield takeLatest('LOG_IN_REQUEST', loginSaga);
}
function* saveDataToStorage(data) {
try {
AsyncStorage.setItem(
'userData',
JSON.stringify({
username: data.username,
password: data.password }))
} catch(e) {
console.log('error save to Storage');
}
};
function* loginSaga(action) {
const response = yield call(fetchLoginData);
const resData = JSON.parse(JSON.stringify(response));
const usernameAuth = String(resData.data[0].username);
const passwordAuth = String(resData.data[0].password);
if (String(action.data.username) === usernameAuth)
{
if (String(action.data.password) === passwordAuth)
{
//console.log('loginSaga LOG_IN_SUCCESS');
yield put({type: 'LOG_IN_SUCCESS'});
saveDataToStorage(action.data);
}
else
{
const error = 'Password is incorrect'
Alert.alert('Failed', error, [{ text: 'Ok', style: 'cancel' }] );
//console.log('loginSaga LOG_IN_FAILURE');
yield put({type: 'LOG_IN_FAILURE'});
}
} else {
const error = 'Username is incorrect'
Alert.alert('Failed', error, [{ text: 'Ok', style: 'cancel' }] );
//console.log('loginSaga LOG_IN_FAILURE');
yield put({type: 'LOG_IN_FAILURE'});
}
}
I can understand that, loginMainSaga()
is to get lastest username
and password
store in redux and compare to the one in Json file by using loginSaga
. SaveDatatoStorage
mean you save username and password to AsyncStorage
.
Question 3 : Is my above logic right ? and action
in loginSaga
function here is a random variable word or point direct to action in redux reducer
?
And the most confuse part is loginScreen:
He split code to different components, just basic style and component of Formik, detail here:
Here is the login screen
function LoginScreen(props) {
const dispatch = useDispatch();
const loginHandler =({username, password}) => {
dispatch(
LoginRequested(username,password)
);
};
const isLoading = useSelector(state => {
//console.log('state.Login.isLoading ' + state.Login.isLoading);
return state.Login.isLoading;
});
return(
<Screen style={styles.container}>
<MaterialCommunityIcons name="wechat" color="black" size={200} />
<Text style={styles.title}>SIGN IN HERE</Text>
<AppForm
initialValues={{username: '', password: ''}}
onSubmit={loginHandler}
validationSchema={validateSchema}>
<AppFormField
name="username"
placeholder="Username"
icon="account"
autoCapitalize="none"
autoCorrect={false}
textContentType="nickname"
width="75%"
></AppFormField>
<AppFormField
name="password"
placeholder="Password"
icon="lock"
autoCapitalize="none"
autoCorrect={false}
secureTextEntry
textContentType="password"
width="75%"></AppFormField>
{isLoading ?
(
<ActivityIndicator size="large" color={'black'} />
) : (
<SubmitBtn title="Sign in" color={'black'} width="75%" />
)}
</AppForm>
<View style={styles.registerContainer}>
<Text style={{color: 'black'}}>Don't have an account?</Text>
<Text style={{color: 'black'}} onPress={() => null}> SIGN UP </Text>
</View>
</Screen>
);
}
I don't understand how can he get user
and password
,
my first question in this file is:
Question 4: Why loginHandler
const have {}
in ({username,password})
, why not use (username,password)
?
And the most thing make me have a headache and can't stop think about it for this week :
Question 5 :How can he get user
and password
when he onSubmit???? He use loginHandler
, but how can he add username
and password
, , how he catch which input was username
, which is password
, if i have 3 form input, how can this handle? is there something special with formik onSubmit
????
Here is the full code : FULL CODE
Please help, your help is very precious for me right now and maybe can solve problem of other newcomer like me. Thank you so so much
type
. For LoginRequested()
the payload is username
and password
. Not all actions need to have a payload however and so for Logout()
you may be able to exclude any paramaters from that action creator.LoginRequested
and logout
), and calculate an update to the store's state. From the code sample you have provided isLoading
and authen
are two boolean properties that are being read from some actions, and stored in the redux store via these reducers. To understand where these values originate, you'll need to debug where actions with these types are created: 'LOG_IN_REQUEST'
type
property that is any random identifier. It's common practice to use a phrase-like string
data type to make it more readable.loginHandler
is being passed as the function that takes the <AppForm />
onSubmit
. The onSubmit
of any HTML based form will pass a set of key-value pairs in an object, and thus loginHandler
must take it's arguments in the format {}
onSubmit
. This function will take the name
of every HTML input element within it's HTML node, and pair it with the respective element's value
. <AppFormField name="username" />
<AppFormField name="password" />