Redux和React组件的异步交互
http://blog.csdn.net/github_26672553/article/details/77716004
前面一篇我们完成了一个简单的点赞功能。
页面点击事件处理函数中,我们是通过dispatch()
方法,目的是要修改state。
addClick(){
//修改state
store.dispatch({
type:"INFO_CLICK"
})
this.setState({ //更新state
infoData:store.getState()
})
}
但这里并不是异步的,是同步代码。dispatch
之后就离开重新获取state了。
1、在实际开发中,我们肯定是多组件开发的,那么就意味着我们前面在组件里直接store
是不可以的。
我们可以可以组件的属性,把store
对象传递给组件。
<InfoDetail Store={store} />
2、这样我们就可以通过组件属性的方式获取需要的数据了
<h2>新闻标题:{this.props.Store.getState().title}</h2>
<span>点击量:{this.props.Store.getState().clicknum}</span>
this.props.Store.dispatch(); //
3、既然我们可以通过this.props.Store来获取存在store对象
中的数据,那么我们构造函数constructor里也不需要去初始化state了;addClick()
代码简化如下:
addClick(){
this.props.Store.dispatch({
type:"INFO_CLICK"
})
}
但是问题来了:我们需要更新state啊
// 组件生命周期函数
// 组件挂载之前执行
componentWillMount() {
this.props.Store.subscribe(()=>{
this.forceUpdate(); //强制更新渲染页面
});
}
调用store的subscribe()
方法,在该方法中更新。
说好的 异步呢
官方给我们提供了一个中间件redux-thunk
。
安装:
npm install redux-thunk
基本原理:中间件拦截我们写的一个Thunk函数,执行异步处理完成后,进行dispatch我们正常的Action,从而继续同步更新state
1、动手吧
import {createStore, applyMiddleware} from "redux";
import thunk from "redux-thunk";
let store = createStore(InfoReduce,applyMiddleware(thunk));
注意其中的变化。
2、有了上面的变化(设置依赖),使用this.props.Store.dispatch()的时候就不必传入一个对象了,可以传入一个函数(Thunk函数)
this.props.Store.dispatch(setClickNum(101));
3、下面就要重点编写这个Thunk函数了
新建一个actions.js,我们把这类函数都写在这个文件里
import axios from "axios";
export let setClickNum = function (id) { //这是一个thunk函数
return function (dispatch) {
axios
.get("http://localhost/newsdetail.php","id="+id)
.then((response)=>{
//response.data.clicknum 服务端返回的点赞数
console.log(response.data);
dispatch(InfoAction.setClickNum(response.data.clicknum)); //这句就是正规调用dispatch(action)
})
}
}
class InfoAction{
static setClickNum(clicknum){
return {
type:"INFO_CLICK",
num:clicknum
}
}
}
从代码可以看出:我们在setClickNum()
函数里用了axios
插件从服务端获取数据;成功获取到数据之后使用dispatch()
调用action;在InfoAction
类的方法实现了和Reducer的交互(也就是前篇文章中的InfoReduce.js),可以看到我们传递了type和num2个数据。
4、当然我们的InfoReduce.js代码也要改变了:
//测试数据
let info = {
title:"测试标题",
clicknum:0
};
// 把数据通过参数船体
export default (state = info, action)=>{
if (action.type == "INFO_CLICK"){
// Object.assign()生成新的对象
return Object.assign({},state,{clicknum:action.num});
}
return state;
}
通过action
参数获取传递的数据。