一、不借用第三方库实现Redux异步
场景建立:先来个很常见的场景,在Http请求之前我们一般会用loading组件来表示数据正在请求,等Http请求结束就关闭loading。下图所示的是Http请求的3种状态:
上述场景如果不使用redux状态管理器,我们会使用react的state或hooks特性来实现;如果使用redux该怎么实现呢?
redux是通过dispatch()方法去触发reducer机制去改变state的。一般情况下,正常的HTTP请需要执行dispatch()三次。如下所示:
dispatch({type:"LOAD_ACTION_START"}); //开始请求
dispatch({type:"LOAD_ACTION_SUCCESS"}); //请求成功
dispatch({type:"LOAD_ACTION_ERROR"}); //请求失败
大概的实现流程如下代码所示:
class DemoView extends Component {
getHttpData=()=>{ //获取HTTP请求——核心代码
Store.dispatch(LOAD_ACTION_FUNS(LOAD_ACTION_START));
setTimeout(()=>{ //模拟http请求
const res={ //模拟服务器返回的数据
flag:"success",
msg:"",
datas:[
{
title:"请求成功"
},{
title:"请求成功"
},{
title:"请求成功"
}
]
}
if(res["flag"] == "success"){ //请求成功
Store.dispatch(LOAD_ACTION_FUNS(LOAD_ACTION_SUCCESS,{datas:res['datas']}));
}else{ //请求失败
Store.dispatch(LOAD_ACTION_FUNS(LOAD_ACTION_SUCCESS,{msg:res['msg']}));
}
},3000);
}
render(){
//忽略
return null;
}
}
从上面代码可知,如果单纯使用redux也可以实现异步redux。不过不建议这么做。react属于UI以构建 UI 为主的的库。尽量将数据逻辑与View分离,简化View层面的逻辑。可以借助第三库实现View层或数据层的分离,降低耦合度。有利于代码梳理;
二、借用第三方库实现Redux异步
- react-redux:属于将react项目与redux进行绑定关联的第三方库;
- redux-chunk:可以将dispatch()的参数定义为函数的中间件;
Redux中间件:中间件一般用来处理action对象。而action对象通过dispatch()方法派发给reducer处理。在进入reducer之前那阶段称之为中间件管道。也就是通过在中间管道之间执行一系列中间件功能以达到增强action功能,最终进入reducer处理;
react-redux主要提供Provider组件和connect()方法;如果没有用Provider组件包裹根组件,connect()方法也无效
- Provider组件:使你的react应用能够访问到redux;
- connect()方法:将你的react组件和redux关联起来;
//Provider组件的用法
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
)
//connect()方法的用法
import React, { Component } from 'react';
import {View,Text,Button,FlatList} from "react-native";
import {connect} from "react-redux";
//这里封装了redux异步写法
import {MeSettingAction} from "../../redux/mesetting";
class MeSettingView extends Component{
componentDidMount(){
this.props.initUserInfo();
}
render(){
//使用connect(mapStateToProps)中userInfo
const userInfo=this.props.userInfo;
return (
<View style={styles.mAddBox}></View>
);
}
}
export default connect((state)=>{ //mapStateToProps
return {
userInfo:state['userInfo']
}
},(dispatch)=>{ //mapDispatchToProps
return {
initUserInfo:()=>dispatch(MeSettingAction())
}
})(MeSettingView);
import {HttpAjax,} from "../utils";
const initState={
type:0, //是否请求成功的状态->0:未开始;1:正在请求;2:请求成功;3:请求失败
msg:"", //请求后的描述
datas:[] //请求返回的数据
};
export const MeSettingReducer=(state=initState,action)=>{
switch(action['type']){
case "MESETTING_START":
return {...state,type:1};
case "MESETTING_SUCCESS":
return {...state,type:2,datas:action['payload']};
case "MESETTING_ERROR":
return {...state,type:3,datas:action['payload']};
default:
return state;
}
}
export const MeSettingAction=()=>{
return async (dispatch)=>{
//开始请求
dispatch({type:"MESETTING_START"});
const url="";
const sendData={};
return new Promise((resolve,reject)=>{
HttpAjax(url,sendData,'get').then((res)=>{
const result=JSON.parse(res);
if(result['flag'] == "success"){
//请求成功
dispatch({type:"MESETTING_SUCCESS",payload:result['datas']});
}else{
//请求失败
dispatch({type:"MESETTING_ERROR",payload:result['msg']});
}
resolve(result);
}).catch((err)=>{
//请求失败
dispatch({type:"MESETTING_ERROR",payload:"请求失败"});
reject(err);
});
})
}
}