如何处理 redux-saga 并将 Formik 中的用户输入数据保存到 Redux
How to handle redux-saga and save user input data in Formik to Redux
我正在制作非常简单的登录应用程序,用于学习 react 和 react-native,我的目标是获取用户输入,然后将这些值与包含用户和密码值的自定义假 api 文件进行比较,然后存入AsyncStorage
(或localStorage
)进行认证。所以我在互联网上搜索我要做什么,这里是符合我正在寻找的东西,但有几件事我真的不明白这段代码是如何工作的。在这段代码中,有些东西让我困惑了一周,我脑子里有很多问题,所以我真的需要一些帮助。这是代码:
首先他的代码中有这样一个 Redux Action
//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
};
};
但让我困惑的是
问题一: 这里的data
是什么?这个data
是做什么用的?
我的意思是我可以理解在 LoginRequested
中,数据是用户名和密码,所以我猜用户名和密码存储在这里,但在 loginSuccessed
和 LoginFailed
中,我不知道不懂,这里的数据是什么
这里是 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;
}
};
对于reducer,所以:
问题 2: isLoading
和 authen( maybe authentication)
是做什么的?? .
我可以理解为登录状态,对吗?但我无法 link 他如何使用那里的代码(我看到他在下面的传奇中使用了一次 'LOGIN_SUCCESS' 但我不明白)
这是商店:
//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;
我明白了,这就是redux应用中间件的方式。
现在是 Saga 部分
//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'});
}
}
我可以理解,loginMainSaga()
是获取最新的 username
和 password
存储在 redux 中,并使用 [=27 与 Json 文件中的进行比较=]. SaveDatatoStorage
表示您将用户名和密码保存到 AsyncStorage
.
问题三:我上面的逻辑对吗?而loginSaga
函数中的action
这里是一个随机变量字或者直接指向action in redux reducer
?
最令人困惑的部分是 loginScreen:
他将代码拆分为不同的组件,只是 Formik 的基本样式和组件,详细信息 here:
这是登录屏幕
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>
);
}
我不明白他怎么会得到 user
和 password
,
我在这个文件中的第一个问题是:
问题4:为什么loginHandler
const在({username,password})
中有{}
,为什么不用(username,password)
?
最让我头疼的是这周一直在想它:
问题5:他onSubmit的时候怎么得到user
和password
????他使用 loginHandler
,但他如何添加 username
和 password
,如果我有 3,他如何捕捉哪个输入是 username
,即 password
表单输入,如何处理? formik onSubmit
有什么特别之处吗????
完整代码如下:FULL CODE
请帮忙,你的帮助对我现在来说非常宝贵,也许可以解决其他像我这样的新手的问题。非常感谢
- 第一组函数称为动作创建器。他们获取任何数据,并创建一个操作,将该数据与操作
type
打包在一起。对于 LoginRequested()
,有效载荷是 username
和 password
。然而,并非所有动作都需要有效负载,因此对于 Logout()
,您可以从该动作创建者中排除任何参数。
- Reducer 采取动作创建者生成的动作(例如
LoginRequested
和 logout
),并计算存储状态的更新。从您提供的代码示例中,isLoading
和 authen
是从某些操作中读取的两个布尔属性,并通过这些缩减器存储在 redux 存储中。要了解这些值的来源,您需要调试创建这些类型的操作的位置:'LOG_IN_REQUEST'
- 你是正确的,动作有一个
type
属性 是任何随机标识符。通常的做法是使用类似短语的 string
数据类型以使其更具可读性。
loginHandler
作为采用 <AppForm />
onSubmit
的函数传递。任何基于 HTML 的形式的 onSubmit
都会在对象中传递一组键值对,因此 loginHandler
必须采用 {}
[=38 格式的参数=]
- 你是对的,是因为
onSubmit
。此函数将获取其 HTML 节点内每个 HTML 输入元素的 name
,并将其与相应元素的 value
. 配对
<AppFormField name="username" />
<AppFormField name="password" />
我正在制作非常简单的登录应用程序,用于学习 react 和 react-native,我的目标是获取用户输入,然后将这些值与包含用户和密码值的自定义假 api 文件进行比较,然后存入AsyncStorage
(或localStorage
)进行认证。所以我在互联网上搜索我要做什么,这里是符合我正在寻找的东西,但有几件事我真的不明白这段代码是如何工作的。在这段代码中,有些东西让我困惑了一周,我脑子里有很多问题,所以我真的需要一些帮助。这是代码:
首先他的代码中有这样一个 Redux Action
//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
};
};
但让我困惑的是
问题一: 这里的data
是什么?这个data
是做什么用的?
我的意思是我可以理解在 LoginRequested
中,数据是用户名和密码,所以我猜用户名和密码存储在这里,但在 loginSuccessed
和 LoginFailed
中,我不知道不懂,这里的数据是什么
这里是 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;
}
};
对于reducer,所以:
问题 2: isLoading
和 authen( maybe authentication)
是做什么的?? .
我可以理解为登录状态,对吗?但我无法 link 他如何使用那里的代码(我看到他在下面的传奇中使用了一次 'LOGIN_SUCCESS' 但我不明白)
这是商店:
//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;
我明白了,这就是redux应用中间件的方式。
现在是 Saga 部分
//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'});
}
}
我可以理解,loginMainSaga()
是获取最新的 username
和 password
存储在 redux 中,并使用 [=27 与 Json 文件中的进行比较=]. SaveDatatoStorage
表示您将用户名和密码保存到 AsyncStorage
.
问题三:我上面的逻辑对吗?而loginSaga
函数中的action
这里是一个随机变量字或者直接指向action in redux reducer
?
最令人困惑的部分是 loginScreen:
他将代码拆分为不同的组件,只是 Formik 的基本样式和组件,详细信息 here:
这是登录屏幕
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>
);
}
我不明白他怎么会得到 user
和 password
,
我在这个文件中的第一个问题是:
问题4:为什么loginHandler
const在({username,password})
中有{}
,为什么不用(username,password)
?
最让我头疼的是这周一直在想它:
问题5:他onSubmit的时候怎么得到user
和password
????他使用 loginHandler
,但他如何添加 username
和 password
,如果我有 3,他如何捕捉哪个输入是 username
,即 password
表单输入,如何处理? formik onSubmit
有什么特别之处吗????
完整代码如下:FULL CODE
请帮忙,你的帮助对我现在来说非常宝贵,也许可以解决其他像我这样的新手的问题。非常感谢
- 第一组函数称为动作创建器。他们获取任何数据,并创建一个操作,将该数据与操作
type
打包在一起。对于LoginRequested()
,有效载荷是username
和password
。然而,并非所有动作都需要有效负载,因此对于Logout()
,您可以从该动作创建者中排除任何参数。 - Reducer 采取动作创建者生成的动作(例如
LoginRequested
和logout
),并计算存储状态的更新。从您提供的代码示例中,isLoading
和authen
是从某些操作中读取的两个布尔属性,并通过这些缩减器存储在 redux 存储中。要了解这些值的来源,您需要调试创建这些类型的操作的位置:'LOG_IN_REQUEST'
- 你是正确的,动作有一个
type
属性 是任何随机标识符。通常的做法是使用类似短语的string
数据类型以使其更具可读性。 loginHandler
作为采用<AppForm />
onSubmit
的函数传递。任何基于 HTML 的形式的onSubmit
都会在对象中传递一组键值对,因此loginHandler
必须采用{}
[=38 格式的参数=]- 你是对的,是因为
onSubmit
。此函数将获取其 HTML 节点内每个 HTML 输入元素的name
,并将其与相应元素的value
. 配对
<AppFormField name="username" />
<AppFormField name="password" />