在react-native中使用redux

http://www.jianshu.com/p/2c43860b0532

redux是什么?

redux是一个用于管理js应用状态的容器。redux出现时间并不是很长,在它出现之前也有类似功能的模块出现,诸如flux等等。redux设计的理念很简单,似乎最初这个开发团队就有让redux可以方便融入在server,browser,mobile client端的打算。目前在github上redux-*的第三方中间件、插件越来越多。如果react项目中想使用redux,那么就有react-redux插件来完成配合。而作为开发者,可以使用这些优秀的第三方资源来开发/优化已有的项目,也是一件很欢乐的事。

设计的动机

在redux.js.org里有关于编写redux的动机描述(our code must manage more state than ever before),在现实的生活中,单页应用越来越多,而且需要维护的状态也越来越复杂,诸如维护数据更新、UI更新、本地数据存储等这些都是我们在js应用常常需要处理的情景,当然这里多数都会涉及到异步处理。而redux本身就是为了解决这些问题,而是将所有的变化进行统一流程处理,会使我们的程序状态变化清晰可见。redux最终目的就是让状态(state)变化变得可预测。

使用的三原则

  • 1,Single source of truth
    单一数据源。整个应用的state,存储在唯一一个object中,同时也只有一个store用于存储这个object.
  • 2,State is read-only
    状态是只读的。唯一能改变state的方法,就是触发action操作。action是用来描述正在发生的事件的一个对象。
  • 3,Changes are made with pure functions
    在改变state tree时,用到action,同时也需要编写对应的reducers才能完成state改变操作。

在上面的三原则中,我们看到了store,action,reducer这些词,那就先说说redux是怎么进行应用状态(state)维护管理的呢。

redux状态管理的流程

  • action是用户触发或程序触发的一个普通对象。
  • reducer是根据action操作来做出不同的数据响应,返回一个新的state。
  • store的最终值就是由reducer的值来确定的。(一个store是一个对象,reducer会改变store中的某些值)

    redux流程.png

上图简单画了下redux状态改变的流程。action -> reducer -> 新store -> 反馈到UI上有所改变
下面再给个具体实例:


redux登录实例.png

store用于维护状态的容器,包括了应用的多个状态,比如说用户是否登录、用户信息、用户任务等等。action是一个普通对象,用于指明是哪种操作,这样才能在reducers中进行识别。而众多reducer是负责返回新的state的函数。在实际应用中,你需要将store或store的某个值绑定到界面,这样更新store的时候,该页面可以监听到值的更新,然后进行一些页面更新操作/跳转操作等。

redux在实际使用中需要用到的高级部分

redux设计如此简洁,以至于并没有进行异步处理的功能。但是留下了middleware这个概念。可以自己编写符合需要的中间件。目前第三方的中间件基本可以完成一个复杂应用的架构设计。那就先说一说,怎么去处理异步请求呢。
首先推荐redux-thunk,可以看到它的源码很简洁。就是判断action是否是函数,如果是函数进行递归式的操作。所以在redux中的异步,只能出现在action中,而且还需要有中间件的支持。

 export default function thunkMiddleware({ dispatch,getState }) { return next => action => { if (typeof action === 'function') { return action(dispatch,getState); } return next(action); }; } // redux-thunk的源码export default function thunkMiddleware({ dispatch,getState); } return next(action); }; } // redux-thunk的源码

同步action与异步action最大的区别是:
同步只返回一个普通action对象。而异步操作中途会返回一个promise函数。当然在promise函数处理完毕后也会返回一个普通action对象。thunk中间件就是判断如果返回的是函数,则不传导给reducer,直到检测到是普通action对象,才交由reducer处理。

实例说说redux的使用。

实例代码在github上查看地址。该实例只演示了登录过程,是比较基础的redux使用案例。


目录结构

项目相关代码均在js目录下。目录中可以看到actions,reducers,store等子目录。

实例action


actions/user.js

actions/user.js目录中定义了用户登录操作的action creator

  • 第22行的logIn
    logIn是一个异步action,注意函数内部的写法与redux-thunk的定义要相同。
  • 第38行的skipLogin
  • 第47行logOut
    这些creator,产生的action状态有LOGGED_DOING,LOGGED_IN,LOGGED_ERROR,LOGGED_OUT四种状态。
    第8行变量testUser,第15行变量skipUser分别是模拟针对普通登录成功后(这里用的是fetch www.baidu.com,真实情况下需换成真实的登录接口)的用户对象,跳过登录后默认的用户对象。
    接下来再看看reducers怎么去处理这些action?

实例reducer


reducers/user.js

reducers/user.js中:

  • 第5行的initialState定义了最开始的应用状态(即用户未登录的情况下的state)。
  • 第13行,对每个传过来的action进行switch,每个action都需要返回一个state对象,如果不需要变动,则返回原对象(switch中的default返回值)。需要变动,则返回一个新的state,可以看到当type为LOGGED_DOING,LOGGED_OUT时,返回的对象跟原始对象都会有一些字段的差别。

reducers/index.js

reducers/index.js中:

  • 第5行combineReducers是将应用的state进行组合。
  • 目前demo中只有用户信息,所以只看到第6行userStore这一个key,在一个业务复杂的应用里,需要保存很多应用和用户交互产生的信息(比如说用户聊天列表等信息)。

实例store

再来看看store的处理:


store/index.js

store/index.js中定义了store的行为(包括中间件):

  • 第23行的applyMiddleware会将中间件应用在redux action过程中。
  • 第10行自定义一个logger中间件,该中间件的目的是打印出当前的触发的action以及出发后的state变化。
  • 第27行,33行 使用了redux-persist这个第三方插件来将store对象存储到本地,以及从本地恢复数据到store中,比如说保存登录信息,下次打开应用可以直接跳过登录界面。

程序入口

上面是定义。下面再来看如何在程序中使用:


程序入口index.js


在入口文件index.js中:

  • 第27行,需要将store作为属性传递给Provider组件中。
  • 第28行,可以看到的是真正渲染出的东西是<Root/>标签返回的东西。

那就来看看root.js里的内容。


root.js


root.js中:

  • 第48行的render主要实现了Navigator导航器的处理,并用自定义的一个Router(第27行)进行封装了下。
  • 第59行,在末尾的select函数,是将store中的某些值复制到当前组件的props中,注意这里需要用connect函数进行绑定,否则store变化,不会反馈到Root组件中。isLoggedIn这个变量便被复制到当前的Root组件中,在Root内部方法中可以访问。
  • 第16行,constructor里,会对登录状态进行判断,如果检测到已经登录了,则会修改Navigator初始的路由设置(第10行设置的),使应用直接显示MainPage

登录页面。

那再看看登录页面pages/login.js中的用户操作:


pages/login.js - 1

pages/login.js - 2

pages/login.js - 3

上面的3个图片是整个pages/login.js的源码。

  • 第160行,指定了该组件会与store的哪些值进行连接。分别是isLoggedIn,user,status
  • 第129行,定义了TextonPress操作。handleLogin是绑定的操作方法,方法内容见第60行。在71行时,会触发logIn这个action。
  • 触发logIn后,会先进入LOGGED_DOING状态,此时说明在登录中。在第42行,有对该状态进行监听,如果为该状态,会将弹窗弹出,提醒为loading态。
  • 第33行,在shouldComponentUpdate中,对即将变化的nextProps进行与目前的props进行对比。比如说logIn执行登录完成后,第35行检测到isLoggedIn为true,则执行toMain函数(即跳转到主页中)。

看下最终的demo交互效果。


demo交互效果

推荐:
RNTools是一个分享React Native文章、实例代码以及第三方模块的平台。RNTools官网链接 RNTools应用下载



文/巨巨(简书作者) 原文链接:http://www.jianshu.com/p/2c43860b0532 著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom