demo 地址:

https://github.com/chris6605/react-native-redux

1 >> 什么是redux ? 你的项目需不需要redux?

有个大神说过? 如果你觉得你的项目不需要redux, 那么你就真的不需要去用 redux.

redux 到底是什么呢? 其实就是用来统一管理整个应用 State 的, 将所有的 state 变化进行统一的流程处理, 使应用的 state变化清晰可见.

如图 : 使用redux和不使用组件之间的通信方式的不同 

react-native  redux使用指南

 

 

在React中,数据在组件中是通过 props 单向流动的。数据从父组件流向子组件,由于这个特征,两个兄弟组件之间的通信并不是那么清楚。
React并不建议直接采用组件到组件的通信方式,需要提一点的是, 在使用 redux 之后你就不能直接调用组件的方法了, 比如你写个弹窗有个 show() 方法, 你在使用的地方通过引用 this.xxxDialog.show()是不会起作用的, 需要严格遵守单向数据流的思想. 尽管它有一些特性可以支持这么做(比如先将子组件的值传递给父组件,然后再由父组件在分发给指定的子组件)。这被很多人认为是糟糕的实践方式,因为这样的方式容易出错而且会让代码向“拉面”一样不容易理解。
当然React也没有直接建议如何去处理这种情形, React 官方是这么解释的:

对于非父子关系的组件,你可以自己建立一个全局的事件系统,Flux的模式也是一种可行的方式。

Redux的出现就让这个问题的解决变得更加方便了。

Redux提供一种存储整个应用状态到一个地方的解决方案(可以理解为统一状态层),这个存储所有应用状态的地方称为“store”,组件发生事件时不会再 setState, 而是由 store 分发(dispatch)一个事件(action),  组件将状态的变化通知给store,而不是直接通知其它的组件, store会根据 action 的类型来调用对应的 reducer(纯函数, 告诉 state 该做出什么变化), reducer 会根据 action 的类型, 接收一个旧的 state, 返回一个新的 state,  store 会收集到所有 reducer的state, 最后更新 state,  组件内部依赖的state的变化情况就可以通过订阅 store 来实现。如图所示:

react-native  redux使用指南

 

 


使用Redux,所有的组件都从store里面获取它们依赖的state,同时也需要将state的变化告知store。组件不需要关注在这个store里面其它组件的state的变化情况,Redux让数据流变得更加简单。这种思想最初来自Flux,它是一种和React相同的单向数据流的设计模式。

如果你的页面单一页面, 功能简单, 状态不多变, 没有涉及多个页面之间的交互, 那么你就不用往下看了, 你真的不需要用 redux这么重量级的东西, 但是比如做多语言, 换肤功能, 字体切换也可以考虑用redux.

 

redux 的三原则

1. Single source of truth
单一数据源。整个应用的state,存储在唯一一个object中, 那就是 store, 一个应用有且只有一个 store

2. State is read-only 
状态是只读的。唯一能改变state的方法,就是触发action操作。不要想着再去 setState 了, 用了 redux 之后你改变 state 唯一的方法就是 dispatch 一个 action, action是什么? 别急,下面再说

3.  Changes are made with pure functions
在改变state tree时,用到action,同时也需要编写对应的reducers才能完成state改变操作。并且 reducer 一定要是一个纯函数, 不要在里面做一些乱七八糟的骚操作

2 >> 什么是 Action?   reducer ?   store ? provider? 

Action  动作 :比如登录操作  退出登录操作 添加待办 删除待办都可以定义为一个 action

example:react-native  redux使用指南

 

 
 
 
 
严格的来讲这应该叫做ActionCreactor , 他返回的那个对象才叫 action, action 就是一个纯对象, 描述正在发生的事情, 也就是触发的操作, 比如这个就是描述正在登录的过程, 只不过我传递的有个 data, 里面存的是登录状态, 一会再讲这个data 怎么用, 总之记住一句话, action 就是一个纯对象, 描述正在发生的事件.必须要有一个 type 属性, types 那个就是一个常量, 用来标识和区分你的 action 的类型, 比如是登录还是登出, 是添加还是删除.
 
Store 全局唯一的一个对象 可以看作应用 state 的集合 , 也就是说你在任意组件中都可以通过 store 拿到你想要的 state
react-native  redux使用指南

这就是一个完整的 store 的创建过程, createStore 是redux 里提供的函数, 接受初始状态,  reducer( reducer 可以有多个, 这里是合并多个 reducer 的 RootReducer ),   中间件.

store 有什么用呢? store 就是一个保存着整个 APP 的所有state 的对象, 顾名思义, 就是一个仓库嘛, 在任何一个组件中都可以通过store 来获取任何一个 state,

Reducer  是一个纯函数, 不要在这里做逻辑操作的事情, 他就是根据一个 action 的 type 返回一个新的 state 一定要保证其纯洁性

react-native  redux使用指南

 异步Action

// 异步的Action 需要返回的是一个 function 在 createStore 时由middleWare 做处理 普通的action 直接返回纯对象即可
  info) {
  LoginApi(info);
  }

 

react-native  redux使用指南

 

这其实就是一个 action(只不过是个异步的 action , 如下图上面是一个普通的同步 action  , dispatch 这个 action 马上就执行, 返回新的 state, UI 更新, 但是异步的不同, 不能马上获取新的 state

这里模仿请求的百度, 请求完成登录成功, 异步的 action 返回的不是纯对象了, 而是一个函数, 就是上图那个函数, 另外在创建 store 的时候还要使用middleware 中间件, 这样才能执行异步操作)react-native  redux使用指南

 

废话都说的差不多了, 相信你对 redux大概有个了解了, 起码对 action reducer store 这三个概念有个印象, action 就是描述一件事情发生的对象, reducer 就是个纯函数, 接受旧的 state 和一个 action, 返回一个新的 state 到 store, store 就是全局唯一的一个仓库,存储着应用所有的 state

 

Provider

provider主要有两个功能 

  • 在原应用组件上包裹一层,使原来整个应用成为Provider的子组件
  • 接收Redux的store作为props,通过context对象传递给子孙组件上的connect

context可以使子孙组件直接获取父级组件中的数据或方法,而无需一层一层通过props向下传递。context对象相当于一个独立的空间,父组件通过getChildContext()向该空间内写值;定义了contextTypes验证的子孙组件可以通过this.context.xxx,从context对象中读取xxx字段的值。

总而言之,Provider模块的功能很简单,从最外部封装了整个应用,并向connect模块传递store。

而最核心的功能在connect模块中。

connect的作用:

1、connect通过context获取Provider中的store,通过store.getState()获取整个store tree 上所有state。
2、connect模块的返回值wrapWithConnect为function。
3、wrapWithConnect返回一个ReactComponent对象Connect,Connect重新render外部传入的原组件WrappedComponent,并把connect中传入的mapStateToProps, mapDispatchToProps与组件上原有的props合并后,通过属性的方式传给WrappedComponent

 

下面进入实战

1. 创建你的项目, 新建如下文件夹

constants actions reducers store pages 

这里说一下 不做异步请求的话 就不用像我那样用中间件 action 返回函数, 直接return 一个对象, 只有一个 type字段就OK  项目的在 Github 上自己可以看一下

 

 2 npm install  react-redux  redux   redux-logger(这个会打印你的所有 state和 action变化 , 建议使用)    redux-thunk(中间件, 用于异步操作)    react-navigation(如果你要做多个页面跳转就install)

react-native  redux使用指南

3. 新建一个 Root.js

react-native  redux使用指南

用 provider 包住你的 APP, 这样所有的组件就都可以获取到 store 的 state 变化了 注意要传递 store

然后就是把 Root.js 当成 App.js一样, 放到你的 index.js里即可

4. 接下来就是编写 action  reducer  store 了

举个简单的加减的同步操作的例子

 actionCreactor: 函数返回一个 action

react-native  redux使用指南

 reducer:

react-native  redux使用指南

这里要提一下, reducer 可以有很多个, 拆分 reducer 对一个不同的操作, 然后用combineReducers 合并所有的 reducer 到 rootReducer, 如下图:

我个人习惯叫 xxxReducer , 在组件中使用的时候, 可以 state.xxxReducer.xxx 便于区分

 react-native  redux使用指南

5. 在 page里怎么使用 

example登录的操作

react-native  redux使用指南

下面登录就这么简单了只需要一句 this.props.loginAction() , 登录的逻辑在 loginRequest 里, 发起登录操作即可, 也算可以给 page解耦, react-native  redux使用指南

 

 

 

这里要注意一下 bindActionCreactors 他的作用是把 dispatch 函数无感知的传递给子组件, 在子组件里就可以 dispatch 一个 action, 当然你也可以通过 props 把dispatch 函数传递给子组件, 只是不优雅, 该函数接受两个参数, 第一个参数可以是函数或者对象,一般是一个 actionCreactor, 返回的也是一个函数或者对象, 第二个参数是 dispatch,

bindAction: {login_doing: ƒ, login_done: ƒ, login_err: ƒ, login_out: ƒ, requireLogin: ƒ}
* {
addTodo : text => dispatch(addTodo('text'));
removeTodo : id => dispatch(removeTodo('id'));
}
相当于 dispath 一个 action
 

这里有个 connect 函数 他的作用就是把当前组件和 store 连接, 然后就可以获取 store 里的 state, store 中的 state 在 dispatch一个 action 之后, 在 reducer 的作用下产生新的 state 返回到 store, 这时你的组件也能接收到新的 state, 不过是以 props 的形式, 如上 connect 函数接受两个参数, 第一个参数接受两个参数分别是 mapStateToProps (名字就表示了他的意思, 你需要获取的 state 会通过props 的形式传递到你的当前组件) matchDispatchToProps 这个是你需要的dispatch 的 action , 我更喜欢直接在发生事件的时候去this.props.dispatch(action),  当然这种不规范, 你们还是用matchDispatchToProps 然后就能直接 this.props.loginAction()就 OK 了

 

这个是那个简单的同步操作加减的, count就是那个 state, 这里已经通过 mapStateToProps 获取了, 所以使用的时候就可以this.props.count , 当你 dispatch一个 action 的时候, reducer 会改变他的值, 返回到 store , 最后通过 connect, store 会把这个改变后的 state 更新到这里react-native  redux使用指南

 

react-native  redux使用指南

 

 

当然在其他地方也可以dispatch 这个 action, 这里的 count 也会变化, 当然在其他地方也可以获取到这个 count, 这就是他的强大之处, 任何地方都能获取到 store 中存储的 所有的state, 在任何地方都可以 dispatch 一个你想要 dispatch 的 action, 可以跨组件的操作和数据传递提供了很大的便利性和可维护性, 所以这也是他适用于逻辑复杂的应用的原因 

 下面附上那个 redux-logger 的日志 里面有store 里详细的 state 变化  以及发起的每一个 action 所以说对于解决 bug 调试起来很省事

react-native  redux使用指南

 

是不是一目了然, 你触发了哪个 action , 改变了什么状态以及最终的状态, 传递的数据都清晰明了,

总结一下吧, redux 很强大, 也很易用, 下面是一个流程图

react-native  redux使用指南

store 就是仓库

action 就是描述事件发生的对象

reducer 就是事件发生之后如何改变state 的一个纯函数

 

 

 

 

 

 

相关文章: