React Native入门系列文章
第一篇:《小白扫盲篇》
第二篇:《如何编写样式》
第三篇:《如何手动开始写一个组件》
第四篇:《组件间通信》
第五篇:《踩过的坑》
第六篇:《实战写一个电影列表页》
第七篇:《网络通信和缓存处理》
第八篇:《Android打包发布》
redux是一个状态管理器,应用中所有的状态(state),都以一个对象树的形式存在于一个单一的store中。唯一改变state的办法是触发一个action。
一开始接触redux时对于它和react的关系理解很混乱:
我们先讲一下redux是干嘛的,它是解决什么需求的。
先来看看react里面数据是怎样传递的。
这个过程是不能越级的,数据传递总是让人觉得不是很灵活。
所以,如果层次不深,组件之间没有什么共用数据的话,用react自身的setState其实也可以了。可是,当嵌套一深,或者组件间有一些共用数据时就比较麻烦了,于是就有了redux。
redux中的state和react中的state完全不是一回事。react中的state是组件内部自己的状态信息,而redux中的state是redux自己的数据,然后react拿redux的数据来用,其实redux也可以在其他框架下使用,并不是非要跟react一起使用。
简单画个图就像下面这样
这只是一个简单的示意图,实际使用并非如此,这个图示是为了让大家理解react中的数据和readux中的数据是独立的,并没有半毛钱关系。
网上对于redux教程非常多,这里简要介绍一下
store:创建一个store
import { createStore } from 'redux';
const store = createStore(reducer);
用来让外界获取redux数据
store.getState
让外界修改redux中数据
store.dispatch
action:描述我要干啥,一般是一个对象的形式,其中有一个type字段是必须要有的。只有被dispatch的action才有意义,否则它跟一个普通的function没什么区别。
reducer:真正去修改redux的state。
const defaultState = {};
const reducer = (state = defaultState, action) => {
switch (action.type) {
case Type.REQUEST:
return {
...state,
action.request
};
default:
return state;
}
};
我们在平时使用redux时,都是dispatch一个action,而真正去修改state,然后返回一个全新的state的是reducer。
那么怎么去触发一个action呢?
就是前面提到的store.dispatch,把action作为dispatch的参数。
store.dispatch({ type:Type.Request,test:"100" })
这样就可以触发action,执行reducer,返回一个全新的state了。
到此为止,redux自己就折腾完了,而redux自己的数据并没有用,它要把数据交给react用才行,接下来讲一讲怎么把数据交给react来用。
上面我们创建了一个对象store,我们要把这个store对象作为props传给react,那react就可以用了。
这个store只能有一个,也就只能创建一次,也就是说你在最顶层处创建一个store对象,然后再一层一层地传下去,才能让所有组件都能获取这个store对象,调用它的方法。
比如说我要在render函数中显示redux数据,那么我就可以先获取它的数据:
store.getState()
然后把这个数据当做props渲染到组件中就行了。
如果要修改它的数据,那就在JSX中调用
store.dispatch({type:Type.Request,test:"100})
那么这里问题又来了,你调用了store.dispatch之后redux中数据确实变了,可是react并没有什么改变啊。也就是说react中的render函数并没有被触发,就好像react中你直接修改react中的state是没用的,而必须调用react中的setState才能重新渲染。
因此,为了让redux的数据一改变我们就重新渲染,redux提供了一个监听方法
store.subscribe(render)
这个函数就可以监听redux中state的变化,一旦redux中的state发生了变化,render函数就会被调用,页面就会被重新渲染。
上面这个过程就是手动调用的过程,但这样调用有点麻烦,因为要让所有的组件都能应用store中的数据,那么所有组件都要把store当做props传进来,这样太麻烦了。
这个时候就需要去安装一些中间件了,还记得你在你的react-native项目中接入redux时安装的三个库吗?
npm install --save redux
npm install --save react-redux
npm install --save redux-thunk
npm install --save react-navigation
其中,react-redux就是为了简化redux的调用流程(后面我们会一一介绍这几个库都做了什么,为什么要引入这几个库)。
在react-redux中有两个比较关键的概念:Provider和connect方法。
一般我们都将顶层组件包裹在Provider组件之中,这样的话,所有组件就都可以在react-redux的控制之下了,但是store必须作为参数放到Provider组件中去
<Provider store = {store}>
<Container/>
<Provider>
这个组件的目的是让所有组件都能够访问到redux中的数据。
这个比较简单,我们来讲connect方法。
connect(mapStateToProps,mapDispatchToProps)(MyComponent)
这两个参数非常重要,我们来讲下。
字面含义就是把state映射到props中去,意思就是把redux中的数据映射到react中的props中去。
比如一个component想要把网络请求的数据拿来渲染,就可以在这个component中把redux中的response拿过来用
const mapStateToProps = (state) => {
return {
data: state.response
}
}
然后渲染的时候就可以直接使用this.props.data
class Container extends Component {
constructor(props){
super(props);
}
render(){
return(
<div>this.props.data</div>
)
}
}
const mapStateToProps = (state) => {
return {
data: state.response
}
}
export default connect(mapStateToProps)(Container)
这样就可以实现渲染,把redux中的state变成react中的props。
通过上面的分析,相信这个函数也很好理解,就是把各种dispatch变成props直接使用。
const mapDispatchToProps = (dispatch) => {
return {
onClick: () => {
dispatch({
type: Type.REQUEST,
test : "100"
});
}
};
}
更改一下Container组件
class Container extends Component {
constructor(props){
super(props);
}
render(){
return(
<div>this.props.data</div>
<button onClick = {this.props.onClick}>点击</button>
)
}
}
const mapStateToProps = (state) => {
return {
data: state.data
}
}
const mapDispatchToProps = (dispatch) => {
return {
onClick: () => {
dispatch({
type: Type.REQUEST,
data : "100"
});
}
};
}
export default connect(mapStateToProps,mapDispatchToProps)(Container);
这样,当点击按钮后,Container组件就会自动更新,而不需要我们手动去store.subscribe订阅render函数以达到更新页面的目的,这样一来我们就不需要一层层传递store对象了。
这样随处都可以使用、修改redux中的数据的方式很方便,但redux推荐的最佳实践还是在尽可能少的地方使用connect,把逻辑数据相关的都放到容器组件中去处理,把其他的组件都由容器组件所生成的props一层层传递下去然后渲染。
###redux-thunk
redux-thunk是一个比较流行的redux异步action中间件,比如action中有setTimeOut或fetch,那么就应该用redux-thunk。这里就不详细介绍了。
本文适合一些已经对redux有过一定研究,但思路还是比较混乱的小伙伴,这篇文章一定能帮你理清思路。另外欢迎下载集成了redux的react-native的demo。