Redux详解(一)

翻译 2016年05月30日 12:14:00

启示

Redux由Flux演变而来,但受Elm的启发,避开了Flux的复杂性。
不管你有没有使用过他们,只需几分钟就能上手Redux。

安装

安装稳定版:

npm install --save redux

多数情况下,你还需要使用React绑定库和开发者工具

npm install --save react-redux
npm install --save-dev redux-devtools

要点

应用中所有的state都以一个对象数的形式储存在一个单一的store中。
唯一改变state的办法是触发action,一个描述发生什么的对象。
为了描述action如何改变state树,你需要编写reducers。
就是这样:

/**
 * Created by iqianjin-shisong on 16/5/30.
 */
import { createStore } from 'redux';

/**
 * 这是一个 reducer,形式为 (state, action) => state 的纯函数.
 * 描述了 action 如何把state转变成下一个 state.
 * 
 * state 的形式取决于你, 可以使基本类型,数组,对象
 * 甚至是 Immutable.js 生成的数据结构. 唯一的要点是
 * 当state变化时需要返回全新的对象,而不是修改传入的参数.
 * 
 * 下面的例子使用 'switch' 语句和字符串来做判断, 但你可以写帮助类(helper)
 * 根据不同的约定(如方法映射)来做判断,只要使用你的项目即可
 * 
 * @param state
 * @param action
 * @returns {number}
 */
function counter(state = 0, action) {
    switch (action.type) {
        case 'INCREMENT':
            return state + 1;
        case 'DECREMENT':
            return state - 1;
        default:
            return state;
    }
}

// 来创建 Redux store 来存放应用的状态
// API 是 { subscribe, dispatch, getState }
let store = createStore(counter);

// 可以手动订阅更新, 也可以事件绑定到视图层
store.subscribe(() => 
    console.log(store.getState())
);

// 改变内部 state 唯一方法是 dispatch 一个 action
// action 可以本序列化, 用日记记录和储存下来,后期还可以以回放的方式执行
store.dispatch({type: 'INCREMENT'})
// 1
store.dispatch({type: 'INCREMENT'})
// 2
store.dispatch({type: 'DECREMENT'})
// 1

你应该把要做的修改变成一个普通对象,这个对象被叫做 action,而不是直接修改state。然后编写专门的函数来决定每个 action 如何改变应用的state, 这个函数被叫做 reducer。

如果你以前使用 Flux,那么你只需要注意一个重要的区别。 Redux 没有Dispatcher 且不支持多个store。相反,只有一个单一的store和一个根级的 reducer 函数。随着应用不断变大,你应该把根级的 reducer拆成多个小的reducer, 分别独立的操作 state 树的不同部分,而不是添加新的 stores。这就像一个 React 应用只有一个根级的组件,这个根组件又由很多小组件构成。
用这个架构开发计数器有点杀鸡用牛刀,但它的美在于做复杂应用和庞大系统时邮箱的扩展能力。由于它可以用action 追溯应用的每一次修改,因此才有强大的开发工具。如录制用户会话并回放所有action来重现它。

三大原则


Redux 可以用这三个基本原则来描述:

单一数据源

整个应用的 state 被储存在一颗 object tree 中, 并且这个 object tree 只存在于唯一一个 store 中。
这让同构应用开发变得飞航容易。来自服务端的 state 可以在无需编写更多代码的情况下被序列化并注入到客户端中。由于是单一的 state tree, 调试也变得非常容易。 在开发中, 你可以把应用的 state 保存在本地,从而加快开发速度。此外,受益于单一的 state tree ,以前难以实现的如“撤销/重做”这类功能也变得轻而易举。

console.log(store.getState());

{
  visibilityFilter: 'SHOW_ALL',
  todos: [{
    text: 'Consider using Redux',
    completed: true,
  }, {
    text: 'Keep all state in a single tree',
    completed: false
  }]
}

State是只读的

唯一改变 state 的方法就是触发 state, action 是一个用于描述已发生时间的普通对象。
这确保了视图和网络请求都不能直接修改state,相反他们只能表达想要修改的意图,因为所有的修改都被集中化处理,且严格按照一个接一个的顺序执行,因此不用担心 race condition 的出现。 Action 就是普通对象而已,因此他们可以被日志打印、序列化、储存、后期调试或测试时回放出来。

store.dispatch({
  type: 'COMPLETE_TODO',
  index: 1
});

store.dispatch({
  type: 'SET_VISIBILITY_FILTER',
  filter: 'SHOW_COMPLETED'
});

使用纯函数来执行修改

为了描述 action 如何改变 state tree, 你需要编写 reducers。
Reducer只是一些纯函数,他接受先前的 state 和 action,并返回新的 state。 刚开始你可以只有一个reducer, 随着应用变大,你可以把它拆成多个小的 reducers, 分别独立地操作 state tree 的不同部分,因为 reducer 只是函数,你可以控制他们被调用的顺序,传入附加数据,甚至编写可复用的 reducer 来处理一些通用任务,如分页器。


function visibilityFilter(state = 'SHOW_ALL', action) {
    switch (action.type) {
        case 'SET_VISIBILITY_FILTER':
            return action.filter;
        default:
            return state;
    }
}

function todos(state = [], actioin) {
    switch (actioin.type) {
        case 'ADD_TODO':
            return [...state, {
                text: actioin.text,
                completed: false
            }];
        case 'COMLETE_RODO':
            return [...state.slice(0, action.index),
                Object.assign({}, state[action.index], {
                    completed: true
                }),
                ...state.slice(action.index + 1)
            ];
        default:
            return state;
    }
}

import  { combineReducers, createStore } from 'redux';
let reducer = combineReducers({ visibilityFilter, todos });
let store = createStore(reducer);

就是这样,现在应该明白Redux是怎么回事了。

相关文章推荐

最简单的React和Redux整合的例子

react redux demo

Redux学习笔记

随着JavaScript单页面应用开发的日趋复杂,JavaScript需要管理比之前任何时候都要多的State。State可以包括服务器返回的数据,本地缓存的数据,也可以是本地创建还没有发送给服务器的...

npm ERR!无法安装任何包的解决办法

npm ERR!无法安装任何包的解决办法

解决redux安装慢问题

redux安装慢问题: npm install -g nrm nrm use taobao 安装redux(进入到react项目工程根目录下)  npm install --save react ...

前端学习总结(十九)Redux——管理state数据最优雅的解决方案

一 Redux简介Redux 是 JavaScript 状态容器,提供可预测化的状态管理动机与目的JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 stat...

Reducer 最佳实践,Redux 开发最重要的部分

reducer就是实现(state, action) => newState的纯函数,也就是真正处理state的地方。值得注意的是,Redux并不希望你修改老的state,而且通过直接返回新state...

react-redux中的数据传递

1、connect connect用于连接React组件与 Redux store,其使用方法如下 connect([mapStateToProps], [mapDispatchToProps],...

react+redux框架配置从无到有直到正常运行全流程(下)

本文转载自 前端_Logic 的博文, 原文地址:http://blog.csdn.net/lx376693576/article/details/54602957 写于:2017-1-1...
  • dj513dj
  • dj513dj
  • 2017年02月21日 10:36
  • 2156

redux 及 react-redux基本用法及源码解析

某年某月某日,某师兄说:学一个东西,不能只停留在表面,只知道怎么用是完全不够的, 要清楚的明白,为什么这么做,为什么不那样做,还得从源码开始,虽然起步可能会比较坎坷,毕竟知识储备有限。 点到为止了,所...
  • luke_up
  • luke_up
  • 2017年01月12日 15:52
  • 815

Redux 中 combineReducers 和 createStore的实现原理

最近一直在学习 redux, 感到了深深的难过,都两天了,感觉还是不知道怎么写代码,倒不是不知道是Redux 里面涉及的概念,是不知道什么代码该放在哪里。怎么样组织结构。希望再过两天能更清晰。 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Redux详解(一)
举报原因:
原因补充:

(最多只允许输入30个字)