前言
Redux
是一个状态管理工具,提供可预测化的状态管理。在应用中,我们经常使用state
和props
来管理组件的数据流,以及组件与组件之间的数据传递,然后更新UI
,通常情况下,如果应用不大,代码规范优秀,业务逻辑处理得当,那么使用state
和props
没有任何问题,我们也用不着所谓的Redux
来管理应用的状态。
但是,随着应用的逐渐庞大,业务逻辑变得越来越复杂,这时候,我们发现,有些组件与组件之间的值的传递(props
)会变得很困难,修改了这个组件,另一个组件也要保持同步、刷新等等操作,我们会使用block
、Notification
、缓存
等操作来保持应用的最新状态,一不小心,容易出错,在这种情况下,有一个好的工具来替我们来管理整个应用的状态,那就太棒了,而Redux
正是帮我们做这一复杂逻辑的一个状态管理工具,让我们可以独立地在任何地方获取到整个应用的状态。
概念
- action
action
就是一个普通的对象,用来描述某一种行为。
- reducer
reducer
是一个纯函数,用来计算、合并在产生行为后的state
数据,返回一个全新的state
到store
。之所以叫纯函数,是因为在reducer
函数中,只做数据的合并、处理操作,不会调用任何API
,也不会改变外部的state
数据。
- store
store
是一个存储整个应用的state树
,它保存了整个应用的状态信息,重要的是,任何应用,有且只有一个store
。
安装
在使用之前,我们需要安装的三方库如下:
- redux
1 | npm install --save redux |
- react-redux
1 | npm install --save react-redux |
react-redux
是redux
的官方react
绑定库,提供一些组件关联函数、状态传递provider
等。
- redux-thunk
1 | npm install redux-thunk |
redux-thunk
是一个Middleware
,与redux
组合可调用异步函数。
使用
效果图:
注:假设你已经熟悉创建
React Native
工程,如何创建这里不再详细说明,若不懂的话可移步到:React Native官网 或者 React Native中文网。
工程目录结构
注:目录可根据自己需要,并不是觉得,只要你觉得方便、合理、低耦合即可。
代码实现
Action目录
- ActionType.js
1 | export const ADD_NAME = 'ADD_NAME'; |
用于描述action
的类型,也就是某种行为,一般建议用字符串常量。
- NameAction.js
1 | import {ADD_NAME} from "./ActionType"; |
这个文件主要用于创建action
对象,根据Redux
标准,每一个对象,必须有一个type
字段,用于描述要触发的类型。
Reducer目录
- NameReducer.js
1 | import {ADD_NAME} from "../Action/ActionType"; |
创建reducer
函数即nameReducer
,接受先前的state
,默认有一个初始值;第二个参数是action
,也就是当触发操作后接受到的action
对象,里面包含了类型type
和数据(数据是非必须的,根据需要看是否传入)。
如果找不到类型,默认返回先前的state
状态。
- index.js
1 | import {combineReducers} from 'redux'; |
通过redux
提供的combineReducers
将所有的reducer
组合成一个rootReducer
(这里为了方便,只写了一个reducer
)。
Store目录
- Store.js
1 | import {createStore} from 'redux'; |
store
的职责是维持整个应用的状态,创建store
也很简单,直接使用Redux
提供的函数createStore
,传入上一步创建的rootReducer
即可,这样,redux
相关的东西准备得差不多了,接下来该在我们的组件里面,绑定我们的store
、触发action
就好了。
Component目录
- Home.js
1 | import React, {Component} from 'react'; |
在这个组件中,最重要的一个步骤是使用react-redux
提供的connect
函数,将Home
组件和我们的redux
关联起来,这样就可以获取到store
中的state
,触发action
。
mapStateToProps: 主要用于将store
中的state
映射到当前组件的props
,这样的话,我们就可以在组件中通过this.props
的形式获取需要的数据。state.nameReducer.data
中的nameReducer
就是Reducer目录
下的index.js
里面的nameReducer
,最终其实就是NameReducer.js
文件中的纯函数nameReducer
,里面的data
也就是从store
取出来的最新state
数据,在render
函数里面,我们使用this.props.data
拿到最新的列表数据。
mapDispatchToProps: 主要用于将dispatch(action)
操作映射到当前的Home
组件中,我们可以看到,在_addName
点击事件里面,使用了this.props.addName(data);
,这个this.props.addName
就是mapDispatchToProps
的功劳。dispatch(addName(data))
中的addName
就是之前我们创建的action
对象(你也可以理解成一个函数),即:
1 | export const addName = data => ({ |
这样的话,当我们点击按钮来调用_addName
的使用,通过dispatch
来触发addName()
这个action
,然后触发nameReducer
,最后通过this.props.data
获取到最新的state
数据来刷新UI
。
- styles.js
这里面都是存储组件里面的样式,使组件里面更加关注业务逻辑。
1 | import {StyleSheet} from 'react-native'; |
App.js
1 | import React, {Component} from 'react'; |
App.js
是最重要的一个节点,因为它是我们的根组件,我要要使用Redux
并在全局的其他子组件获取到state
,那么就要在根组件的最外层包括一个Provider
容器,不必担心,这个在react-redux
中已经给我们准备好了,我们要做的就是直接导入使用即可。
这里的Store
也就是我们之前通过createStore(rootReducer)
创建的并且唯一的一个store
,它在全局起着至关重要的作用,因为我们所有的数据都是存放在这个store
中,它维持的是一棵完整的state
树,有了它,你可以在其他任意组件通过connect
获取到当前store
中存储的数据和状态。
小结
- action是一个对象,用于描述某一个动作或行为,可以传入数据
- reducer是一个纯函数,主要用于处理
state
数据,返回全新的state
数据 - store整个应用中只有一个,维持着所有的
state
数据,我们可以在任意组件通过connect
获取
本文虽然引入了
redux-thunk
,由于篇幅有限,并未使用,放在下一篇文章中进行讲解。
本文源码:RN_ReduxDemo