Redux 介绍
本文主要是对 Redux 官方文档 的梳理以及自身对 Redux 的理解。
单页面应用的痛点
对于复杂的单页面应用,状态(state)管理非常重要。state 可能包括:服务端的响应数据、本地对响应数据的缓存、本地创建的数据(比如,表单数据)以及一些 UI 的状态信息(比如,路由、选中的 tab、是否显示下拉列表、页码控制等等)。如果 state 变化不可预测,就会难于调试(state 不易重现,很难复现一些 bug)和不易于扩展(比如,优化更新渲染、服务端渲染、路由切换时获取数据等等)。
Redux 就是用来确保 state 变化的可预测性,主要的约束有:
state 以单一对象存储在 store 对象中
state 只读
使用纯函数 reducer 执行 state 更新
state 为单一对象,使得 Redux 只需要维护一棵状态树,服务端很容易初始化状态,易于服务器渲染。state 只能通过 dispatch(action) 来触发更新,更新逻辑由 reducer 来执行。
Actions、Reducers 和 Store
action 可以理解为应用向 store 传递的数据信息(一般为用户交互信息)。在实际应用中,传递的信息可以约定一个固定的数据格式,比如: Flux Standard Action。
为了便于测试和易于扩展,Redux 引入了 Action Creator:
function addTodo(text) {
return {
type: ADD_TODO,
text,
}
}
store.dispatch(addTodo(text))
dispatch(action) 是一个同步的过程:执行 reducer 更新 state -> 调用 store 的监听处理函数。如果需要在 dispatch 时执行一些异步操作(fetch action data),可以通过引入 Middleware 解决。
reducer 实际上就是一个函数:(previousState, action) => newState
。用来执行根据指定 action 来更新 state 的逻辑。通过 combineReducers(reducers) 可以把多个 reducer 合并成一个 root reducer。
reducer 不存储 state, reducer 函数逻辑中不应该直接改变 state 对象, 而是返回新的 state 对象(可以考虑使用 immutable-js)。
store 是一个单一对象:
管理应用的 state
通过
store.getState()
可以获取 state通过
store.dispatch(action)
来触发 state 更新通过
store.subscribe(listener)
来注册 state 变化监听器通过
createStore(reducer, [initialState])
创建
在 Redux 应用中,只允许有一个 store 对象,可以通过 combineReducers(reducers) 来实现对 state 管理的逻辑划分(多个 reducer)。
Middleware
middleware 其实就是高阶函数,作用于 dispatch 返回一个新的 dispatch(附加了该中间件功能)。可以形式化为:newDispatch = middleware1(middleware2(...(dispatch)...))
。
// thunk-middleware
export default function thunkMiddleware({ dispatch, getState }) {
return next => action =>
typeof action === 'function' ? action(dispatch, getState) : next(action)
}
通过 thunk-middleware 我们可以看出中间件的一般形式:中间件函数接受两个参数参数: dispatch 和 getState(也就是说中间件可以获取 state 以及 dispatch new action
)。中间件一般返回 next(action)
(thunk-middleware 比较特殊,它用于 dispatch 执行异步回调的 action)。store 的创建过程如下:
const reducer = combineReducers(reducers)
const finalCreateStore = applyMiddleware(promiseMiddleware, warningMiddleware,
loggerMiddleWare)(createStore)
const store = finalCreateStore(reducer)
异步 Actions
单页面应用中充斥着大量的异步请求(ajax)。dispatch(action) 是同步的,如果要处理异步 action,需要使用一些中间件。
redux-thunks 和 redux-promise 分别是使用异步回调和 Promise 来解决异步 action 问题的。
Redux 和传统 Flux 框架的比较
图来自 UNIDIRECTIONAL USER INTERFACE ARCHITECTURES
Redux 和 React
Redux 和 React 是没有必然关系的,Redux 用于管理 state,与具体的 View 框架无关。不过,Redux 特别适合那些 state => UI
的框架(比如:React, Deku)。
可以使用 react-redux 来绑定 React,react-redux
绑定的组件我们一般称之为 smart components
,Smart and Dumb Components 在 react-redux
中区分如下:
Location | Use React-Redux | To read data, they | To change data, they | |
---|---|---|---|---|
“Smart” Components | Top level, route handlers | Yes | Subscribe to Redux state | Dispatch Redux actions |
“Dumb” Components | Middle and leaf components | No | Read data from props | Invoke callbacks from props |
简单来看:Smart component` 是连接 Redux 的组件(@connect),一般不可复用。Dumb component 是纯粹的组件,一般可复用。
两者的共同点是:无状态,或者说状态提取到上层,统一由 redux 的 store 来管理。redux state -> Smart component -> Dumb component -> Dumb component(通过 props 传递)。在实践中,少量 Dumb component 允许自带 UI 状态信息(组件 unmount 后,不需要保留 UI 状态)。
值得注意的是,Smart component 是应用更新状态的最小单元。实践中,可以将 route handlers 作为 Smart component,一个 Smart component 对应一个 reducer。
Redux 介绍的更多相关文章
- Redux介绍及基本应用
一.Redux介绍 Redux的设计思想很简单,就两句话: Web应用是一个状态机,神力与状态是一一对应的 所有的状态,保存在一个对象里面 二.Redux基本概念和API Store Store就是 ...
- redux介绍与入门
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Helvetica } p.p2 { margin: 0.0px 0.0px 0.0px 0. ...
- Redux 学习(1) ----- Redux介绍
Redux 有三个基本的原则: 1,单一状态树,redux 只使用一个javascript 对象来保存整个应用的状态. 状态树样式如下: const state = { count: 0 } 2,状态 ...
- redux 介绍及配合 react开发
前言 本文是 Redux 及 Redux 配合 React 开发的教程,主要翻译自 Leveling Up with React: Redux,并参考了 Redux 的文档及一些博文,相对译文原文内容 ...
- 基于 React.js + Redux + Bootstrap 的 Ruby China 示例 (转)
一直学 REACT + METEOR 但路由部分有点问题,参考一下:基于 React.js + Redux + Bootstrap 的 Ruby China 示例 http://react-china ...
- Redux学习(2) ----- 异步和中间件
Redux中间件,其实就是一个函数, 当我们发送一个action的时候,先经过它,我们就可以对action进行处理,然后再发送action到达reducer, 改变状态,这时我们就可以在中间件中,对a ...
- redux详解
redux介绍 学习文档:英文文档,中文文档,Github redux是什么 redux是一个独立专门用于做状态管理的JS库(不是react插件库),它可以用在react, angular, vue等 ...
- 读redux源码总结
redux介绍 redux给我们暴露了这几个方法 { createStore, combineReducers, bindActionCreators, applyMiddleware, compos ...
- 3.1 开始使用 redux
前面我们介绍了 flux 架构以及其开源实现 redux,在这一节中,我们将完整的介绍 redux: redux 介绍 redux 是什么 redux 概念 redux 三原则 redux Store ...
随机推荐
- 用于文件系统的C库函数
9/20/2017 学<LINUX C编程实战>中 1.打开 File *fopen(const char *path , const char * mode); fopen实现打开指定的 ...
- Mybatis-Oralce批量插入方法
mybatis-Oralce 中批量插入方法一:<insert id="insertBatchSelective" parameterType="java.util ...
- ArcGIS 网络分析[8] ArcObjects二次开发之底层网络分析开发
基于现有的线要素类.转弯要素类(在地理数据库的要素数据集中),要用AO做两件事: 1. 创建网络数据集(使用Geodatabase类库) 2. 执行网络分析(使用NetworkAnalyst类库) 在 ...
- Spark源码剖析(六):Worker原理与源码剖析
上篇文章我们剖析了Master的原理和源码,知道了当Master使用资源分配算法将资源分配完成后,就会给对应的Worker发送启动Driver或者Executor的消息,那么Worker收到这些消息后 ...
- CSS3 使用选择器在页面插入内容
使用选择器来插入文字 h2:before{ content:'COLUMN'; color:white: background-color:orange: padding:1px 5px; } 注意点 ...
- Python函数篇(7)-正则表达式
1.正则表达式 正则表达式为高级的文本模式匹配,抽取,与/或文本形式的搜索和替换功能提供了基础,简单的来说,正则表达式是由一些字符和特殊符号组成的字符串.Python通过标准库中的re模块来支持正 ...
- 找回Git中丢失的Commit
在使用Git的过程中,有时候会因为一些误操作,比如reset.rebase.merge等.特别是在Commit之后又执行了git reset --hard HEAD强制回滚本地记录以及文件到服务器版本 ...
- requireJS(版本是2.1.15)学习教程(一)
一:为什么要使用requireJS? 很久之前,我们所有的JS文件写到一个js文件里面去进行加载,但是当业务越来越复杂的时候,需要分成多个JS文件进行加载,比如在页面中head内分别引入a.js,b. ...
- 4、公司经营的业务来源 - CEO之公司管理经验谈
公司经营的业务来源为公司的运作资金提供了帮助,一般来说,整个公司的领导层为公司的经营做管理,而业务员就为公司的业务提供来源,然后建设部为业务开展做建设. 一.总经理: 公司的总经理主要负责公司运作经营 ...
- Fiddler中使用AutoResponder创建规则替换线上文件
Fiddler 的AutoResponder tab允许你从本地返回文件,而不用将http request 发送到服务器上. 1.AutoResponder规则实例 (1) 打开博客园首页,把博客园的 ...