如何在 React Native 应用程序中集成 Redux-Saga:初学者教程(第 2 部分)
我们在之前的教程中学习并实现了 redux-form 的基础知识:集成 Redux 表单(第 1 部分)。如果您对 Redux Form 没有基本的了解或者难以在您的应用程序中使用它,您可以访问该教程。现在,是时候加紧介绍 redux 形式的 redux-saga 了。您是否正在寻找一个简单的教程来开始在您的 React Native 应用程序中使用 Redux 中间件?如果是,那么您选择了正确的博客!
在本教程中,我们将使用redux-saga和 redux form在我们的演示应用程序中实现一个身份验证模块。
目标:简单的 Redux-Form 和 React-Saga 示例
在着手实施我们的身份验证模块之前,请观看下面的视频以更好地了解演示应用程序。
教程外卖
我们将主要了解-
Redux 传奇
Redux 形式
该演示将包含一个身份验证模块,我们在其中使用了 redux-form。该模块将有 -
登记
登录
仪表板
使用两个redux-form特性:
Field Array – Field Array 组件用于呈现字段数组。
向导表单——将单个表单分隔到不同输入页面的常见模式是向导。
并且还从登录和注册模块调用了 Firebase REST API。
因此,我们清楚要求和演示将包含的内容。不浪费更多时间,让我们开始构建我们的演示应用程序。
Redux 商店设置
第一步将是建立商店。
要将商店连接到您的应用程序,请打开 app/index.js
应用程序/index.js
从“商店”导入{商店}import { Provider as ReduxProvider } from 'react-redux'
导出默认值 () => (
<ReduxProvider store={store}>
<应用/>
</ReduxProvider>)
所以,现在可以通过我们的整个应用程序访问商店。是时候在我们的应用程序中使用商店了。为此,我们需要做两件事——
注册和登录页面的单独action.js和saga.js文件(我们将在接下来的部分中看到)
一个名为store的文件夹包含三个文件——index.js、reducers.js 和 sagas.js
存储/索引。js
从'redux-saga'导入createSagaMiddleware;从'redux'导入{createStore,applyMiddleware};
从 './reducers' 导入 {combinedReducers};从 './sagas' 导入 rootSaga;
const sagaMiddleware = createSagaMiddleware();常量中间件 = [sagaMiddleware];
const store = createStore(combinedReducers, applyMiddleware(...middlewares));
sagaMiddleware.run(rootSaga);
出口{商店};
存储/reducers.js
从'redux'导入{combineReducers};从'redux-form'导入{reducer as formReducer};
export const combinedReducers = combineReducers({
形式:formReducer,
授权:AuthReducer,});
商店/sagas.js
从'redux-saga/effects'导入{all};从“screens/Login/saga”导入 loginScreenSaga;从“screens/Register/saga”导入 signupScreenSaga;函数* rootSaga() {
yield all([loginScreenSaga(), signupScreenSaga()]);}
导出默认的 rootSaga;
登记
我们会将注册表单分成单独的输入页面,命名为 -
注册页面One.js
注册PageTwo.js
RegisterPageThree.js
这种拆分模式称为向导形式。
注册/index.js
为了将表单分成小表单,我们将使用状态变量页面来跟踪要呈现的页面。
从“反应”中导入反应,{useState}从'react-native'导入{ScrollView}从 './RegisterPageOne' 导入 RegisterPageOne从 './RegisterPageTwo' 导入 RegisterPageTwo从 './RegisterPageThree' 导入 RegisterPageThree
const 注册 = (props) => {
const [页面,设置页面] = useState(1)
const onSubmit = (Values) => console.log(Values)
常量 goToNextPage = () => setPage( page => page + 1 )
常量 goToPrevPage = () => setPage( page => page - 1 )
返回 (
<滚动视图>
{page === 1 && <RegisterPageOne nextPage={goToNextPage} />}
{page === 2 && <RegisterPageTwo nextPage={goToNextPage} prevPage={goToPrevPage} />}
{page === 3 && <RegisterPageThree onSubmit={onSubmit} prevPage={goToPrevPage} />}
</滚动视图>
)}
导出默认注册
注册/RegisterPageOne.js
RegisterPageOne 是我们的第一个组件,它将有两个字段:全名和用户名。
从“反应”导入反应从'react-native'导入{View}从 'redux-form' 导入 { Field, reduxForm }从“组件”导入 { FormInput , CustomButton }从 'utils/Validations' 导入 { usernameRequired , fullnameRequired }
const RegisterPageOne = ({handleSubmit,nextPage}) => {
返回 (
<视图>
<字段
名称=“全名”
组件={FormInput}
验证={[fullnameRequired]}
placeholder="输入全名"
/>
<字段
名称=“用户名”
组件={FormInput}
验证={[需要用户名]}
placeholder="输入用户名"
onSubmitEditing = {handleSubmit(nextPage)}
/>
<自定义按钮
buttonLabel="下一步"
onPress={handleSubmit(下一页)}
/>
</查看>
)}
导出默认的 reduxForm({
形式:'注册表格',
destroyOnUnmount:假,
forceUnregisterOnUnmount:真})(RegisterPageOne)
注册/RegisterPageTwo.js
RegisterPageTwo 是我们的第二个组件,具有三个字段:手机号码、电子邮件和兴趣爱好。爱好的输入使用 FieldArray API 向用户呈现多个输入。我们还将向输入字段添加验证。
从“反应”导入反应从 'react-native' 导入 { StyleSheet, View , Text }从 'redux-form' 导入 { Field, FieldArray, reduxForm }从“组件”导入 {DeleteButton、CustomButton、FormInput}从 'utils/Validations' 导入 { emailRequired, mobileNoRequired, validateEmail, validateMobileno }
const renderHobbies = ({ fields, meta : {error , submitFailed } }) => {
返回(
<视图>
<自定义按钮
buttonLabel={“添加爱好”}
onPress={() => fields.push({})}
/>
{fields.map((爱好,索引)=>(
<查看键={index}>
<字段
姓名={爱好}
placeholder={`爱好#${index + 1 }`}
组件={FormInput}
/>
<DeleteButton onDelete={() => fields.remove(index)} />
</查看>
))}
{ submitFailed && error && <Text>{error}</Text> }
</查看>
)}
const validate = (values,props) => {
常量错误 = {}
if (!values.hobbies || !values.hobbies.length) errors.hobbies = { _error : “至少添加一个爱好” }
别的{
常数 hobbiesArrayErrors = []
values.hobbies.forEach((爱好,索引)=>{
如果 (!hobby || !hobby.length) hobbiesArrayErrors[index] = HOBBY_REQUIRED
})
如果(hobbiesArrayErrors.length)errors.hobbies = hobbiesArrayErrors
}
返回错误}
const RegisterPageTwo = ({prevPage,handleSubmit,nextPage}) => {
返回 (
<视图>
<字段
name="手机号"
组件={FormInput}
placeholder={“输入手机号码”}
验证={[mobileNoRequired,validateMobileno]}
/>
<字段
名称=“电子邮件”
组件={FormInput}
占位符={“输入电子邮件”}
验证={[emailRequired,validateEmail]}
/>
<FieldArray name="hobbies" component={renderHobbies}/>
<CustomButton buttonLabel={“Back”} onPress={prevPage}/>
<自定义按钮
buttonLabel={“下一步”}
onPress={handleSubmit(下一页)}
/>
</查看>
)}
导出默认的 reduxForm({
形式:'注册表格',
证实,
destroyOnUnmount :假,
forceUnregisterOnUnmount : 真})(注册页面二)
注册/RegisterPageThree.js
RegisterPageThree 组件包括两个密码字段。添加了两个密码应匹配的验证。
从“反应”导入反应从'react-native'导入{View}从'react-redux'导入{connect}从 'redux-form' 导入 { Field, formValueSelector, reduxForm }从“组件”导入{CustomButton,FormInput}从 'utils/Validations' 导入 { passwordRequired, validatePassword }
让 RegisterPageThree = ({handleSubmit,onSubmit,prevPage}) => {
const validateConfirmPassword = (密码) =>
密码 && 密码 !== props.password
?验证_确认_密码
: 不明确的
返回 (
<视图>
<字段
名称=“密码”
组件={FormInput}
placeholder={“输入密码”}
验证={[需要密码,验证密码]}
/>
<字段
名称=“确认密码”
组件={FormInput}
placeholder={“重新输入密码”}
validate={[passwordRequired,validateConfirmPassword]}
/>
<CustomButton buttonLabel={“Back”} onPress={prevPage}/>
<CustomButton buttonLabel={“Next”} onPress={handleSubmit(nextPage)}/>
</查看>
)}
RegisterPageThree = reduxForm({
形式:'注册表格',
destroyOnUnmount :假,
forceUnregisterOnUnmount : 真})(注册页面三)
const selector = formValueSelector('register-form')导出默认 RegisterPageThree = connect(state => {
const password = selector(state, '密码')
返回 {密码}})(注册页面三)
注册/action.js
export const signupUser = user => ({
类型:'REGISTER_REQUEST',
有效载荷:用户,});
注册/saga.js
从'redux-saga/effects'导入{put,takeLatest};从“api/Signup”导入 {userSignup};
函数* signupUser({payload}) {
尝试 {
const response = yield userSignup(payload);
yield put({type: 'REGISTER_SUCCESS', response});
} 赶上(错误){
yield put({type: 'REGISTER_FAILURE', error: error.message});
}}
导出默认函数* signupScreenSaga() {
yield takeLatest('REGISTER_REQUEST', signupUser);}
解释
单击提交按钮时,将调用onSubmit ,并发送包含有效负载的signupUser(payload) 。
派遣(注册用户(有效载荷))
从文件Register/action.js中,注册操作类型“REGISTER_REQUEST”将被调度。
然后 saga 中间件将监视“REGISTER_REQUEST”类型的操作。
它将获取该操作的最新遭遇并调用注册 API。
对于成功的调用,它将发送带有响应数据的“REGISTER_SUCCESS”操作。
对于 Fail 调用,它将发送带有错误消息的“REGISTER_FAILURE”操作。
更新减速器
打开store/reducers.js并添加这段代码说明 switch cases。
这个减速器服务于来自登录和注册的操作。这两个模块都派发相似类型的动作-
1. 请求动作:根据这个动作,reducer 将loading变量更新为 true。
2. Success Action:执行此操作后,reducer 将loading变量更新为 false,并将操作的响应存储到user变量。
3. 失败操作:在此操作后,reducer 将加载变量更新为 false 并将来自操作的响应存储到错误变量
存储/reducers.js
const AuthReducer = (state = initialState, action) => {
开关(动作类型){
案例“REGISTER_REQUEST”:
返回 {
...状态,
加载:真实,
};
案例“REGISTER_SUCCESS”:
返回 {
...状态,
用户:action.response,
加载:错误,
};
案例“REGISTER_FAILURE”:
返回 {
...状态,
错误:action.error,
加载:错误,
};
案例'LOGIN_REQUEST':
返回 {
...状态,
加载:真实,
};
案例“LOGIN_SUCCESS”:
返回 {
...状态,
用户:action.response,
加载:错误,
};
案例“LOGIN_FAILURE”:
返回 {
...状态,
错误:action.error,
加载:错误,
};
默认:
返回状态;
}};
登录
登录页面接受两个输入 - 电子邮件和密码。
单击提交按钮时调用登录 API。成功登录后,将出现仪表板屏幕。
登录/index.js
从“反应”导入反应从 'redux-form' 导入 { Field, reduxForm }从'react-redux'导入{useDispatch}从 'react-native' 导入 {View, ScrollView}从 './actions' 导入 { loginUser }从“组件”导入{FormInput,CustomButton}import { passwordRequired, emailRequired, validatePassword , validateEmail } from 'utils/Validations'
const 登录 = (props) => {
const dispatch = useDispatch()
const onSubmit = (values) => dispatch(loginUser(values))
返回 (
<滚动视图>
<字段
名称=“电子邮件”
组件={FormInput}
占位符={“输入电子邮件”}
验证={[emailRequired,validateEmail]}
/>
<字段
名称=“密码”
组件={FormInput}
placeholder={“输入密码”}
验证={[需要密码,验证密码]}
/>
<自定义按钮
buttonLabel={“登录”}
onPress={props.handleSubmit(onSubmit)}
/>
</滚动视图>
)}导出默认的 reduxForm({
形式:'登录形式'})(登录)
登录/action.js
export const loginUser = (user) => ({
输入:“LOGIN_REQUEST”,
有效载荷:用户,});
登录/saga.js
从'redux-saga/effects'导入{put,takeLatest};从“api/登录”导入{userLogin};
函数* loginUser({payload}) {
尝试 {
const response = yield userLogin(payload);
yield put({type: 'LOGIN_SUCCESS', response});
} 赶上(错误){
yield put({type: 'LOGIN_FAILURE', error: error.message});
}}导出默认函数* loginScreenSaga() {
yield takeLatest('LOGIN_REQUEST', loginUser);}
解释
单击提交按钮时,将调用onSubmit ,并发送包含用户电子邮件和密码的loginUser(values) 。
const onSubmit = (values) => dispatch(loginUser(values))
从文件Login/action.js中,将调度登录操作类型“LOGIN_REQUEST” 。
然后 saga 中间件将监视“LOGIN_REQUEST”类型的操作。
它将获取该操作的最新遭遇并调用登录 API。
对于成功的调用,它将发送带有响应数据的“LOGIN_SUCCESS”操作。
对于 Fail 调用,它将发送带有错误消息的“LOGIN_FAILURE”操作。
API调用
api/登录/index.js
const API_KEY = '' //把你的密钥放在这里常量端点= {
登录:`https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${API_KEY}`}
export const userLogin = async (user) => {
const response = await fetch(endpoint.login,{
方法:'POST',
标题:{
'内容类型':'应用程序/json'
},
正文:JSON.stringify({
电子邮件:user.email,
密码:用户.密码,
返回安全令牌:真
})
})
if(!response.ok) throw new Error('出事了!!');
const responseData = await response.json()
返回responseData.email}
仪表板
成功登录后,您将被重定向到仪表板页面。这是 UI 的代码。
仪表板/index.js
从“反应”导入反应;从'react-redux'导入{useSelector};从 'react-native-size-matters' 导入 {scale, verticalScale};从 'react-native' 导入 {Text, StyleSheet, SafeAreaView};
从“utils/Colors”导入颜色;
const 仪表板 = () => {
const userEmail = useSelector(state => state.Auth.user);
返回 (
<SafeAreaView style={styles.screen}>
<Text style={styles.hiText}>你好</Text>
<Text style={styles.name}>{userEmail}</Text>
</安全区域视图>
);};
导出默认仪表板;
useSelector()允许您使用选择器函数从 Redux 存储状态中提取数据,以便我们可以在我们的组件中使用它。如您所见,我们可以从state.Login.user中获取用户电子邮件地址的值。
您可以在Github Repository找到演示应用程序的完整源代码,您可以从中克隆和试用代码。
结论
所以,这是关于在 React Native 应用程序中使用 redux-form 实现 redux-saga。我们已经介绍了使用 redux-form 功能字段数组、向导表单和 redux-middleware 的完整身份验证。您可以访问React Native 教程页面以获取更多此类教程,并克隆 github 存储库进行实验。
如果您正在为您的 React Native 应用程序寻找帮助,请立即联系我们以聘请我们的React Native 开发人员。我们拥有经验丰富且技能娴熟的开发人员,他们拥有 React Native 的基础知识和高级知识。