In the previous lesson we created a reducer that can handle two actions, adding a new to-do, and toggling an existing to-do. Right now, the code to update the to-do item or to create a new one is placed right inside of the to-dos reducer.

This function is hard to understand because it makes us two different concerns, how the to-do's array is updated, and how individual to-dos are updated. This is not a problem unique to Redux. Any time a function does too many things, you want to extract other functions from it, and call them so that every function only addresses a single concern.

In this case, I decided that creating and updating a to-do in response to an action is a separate operation, and needs to be handled by a separate function called to-do. As a matter of convention, I decided that it should also accept two arguments, the current trait and the action being dispatched, and it should return the next trait.

But in this case, this trait refers to the individual to-do, and not to the least of to-dos. Finally, there is no magic in Redux to make it work. We extracted the to-do reducer from the to-dos reducer, so now we need to call it for every to-do, and assemble the results into an array.

While this is not required in this particular example, I suggest that you always have the default case where you return the current trait to avoid all [inaudible 1:36] in the future. The part described in this lesson is pervasive in Redux's development, and is called reducer composition.

Different reducers specify how different parts of the trait tree are updated in response to actions. Reducers are also normal JavaScript functions, so they can call other reducers to delegate and abstract a way of handling of updates of some parts of this tree they manage.

This pattern can be applied many times, and while there is still a single top level reducer managing the state of your app, you will find it convenient to express it as many reducers call on each other, each contribution to a part of the applications trait tree.

let todo = (state, action) => {
switch(action.type){
case 'ADD_ITEM':
return {
text: action.text,
id: action.id,
completed: false
};
case 'TOGGLE_ITEM':
if(state.id !== action.id){
return state;
}else{
return {
...state,
completed: !state.completed // will overwirte the state object's completed prop
};
}
default:
return state;
}
} let todos = (state = [], action) => { switch(action.type){
case 'ADD_ITEM':
return state = [
...state,
todo(undefined, action)
];
case 'TOGGLE_ITEM':
return state.map( (t) => todo(t, action))
default:
return state;
}
}; let testTodo_addItem = () => {
let stateBefore = [];
let action = {
type: 'ADD_ITEM',
text: 'Learn Redux',
id: 0
};
let stateAfter = [
{
text: 'Learn Redux',
id: 0,
completed: false,
}
]; deepFreeze(stateBefore);
deepFreeze(action); expect(
todos(stateBefore, action)
).toEqual(stateAfter);
}; let testTodo_toggleItem = () => {
let stateBefore = [
{
text: 'Learn Redux',
id: 0,
completed: false
},
{
text: 'Learn Angular2',
id: 1,
completed: false
}
];
let action = {
type: 'TOGGLE_ITEM',
id: 1
}; let stateAfter = [
{
text: 'Learn Redux',
id: 0,
completed: false
},
{
text: 'Learn Angular2',
id: 1,
completed: true
}
]; deepFreeze(stateBefore);
deepFreeze(action); expect(
todos(stateBefore, action)
).toEqual(stateAfter);
} testTodo_toggleItem(); console.log("All tests passed!");

[Redux] Reducer Composition with Arrays的更多相关文章

  1. [Redux] Reducer Composition with combineReducers()

    Previous, we do composition with objects: const todoApp = (state = {}, action) => { return { todo ...

  2. redux reducer笔记

    踩坑一,reducer过于抽象 reducer写得没那么抽象也不会有人怪你的.^_^ reducer其实只有一个,由不同的reducer composition出来的.所以, reducer的父作用域 ...

  3. Redux生态系统

    生态系统 Redux 是一个体小精悍的库,但它相关的内容和 API 都是精挑细选的,足以衍生出丰富的工具集和可扩展的生态系统. 如果需要关于 Redux 所有内容的列表,推荐移步至 Awesome R ...

  4. react+redux教程(四)undo、devtools、router

    上节课,我们介绍了一些es6的新语法:react+redux教程(三)reduce().filter().map().some().every()....展开属性 今天我们通过解读redux-undo ...

  5. [React Testing] Redux Reducers

    Sometimes we want to test our Redux reducers to make sure they work as expected. In this lesson we w ...

  6. 深入Redux架构

    关于redux 之前写了一篇通过一个demo了解Redux,但对于redux的核心方法没有进行深入剖析,在此重新总结学习,完整的代码看这里.(参考了React 技术栈系列教程) 什么情况需要用redu ...

  7. redux入门指南

    前言:大概一个月没有写博客了,这两天正好是周末,就写点东西来梳理下之前几个月的所写与所得; 大概两个月前,学习了一下 redux ,还是一点难度的,花了我一天的时间来搞明白他, 但是都没怎么记录,今天 ...

  8. redux (一)

    redux 是一个状态管理的库. redux认为页面所有的变化,都是基于状态的改变触发的,所以我们维护一个应用的时候,都是在维护这些状态.而 redux 就是为了维护状态而生的. API create ...

  9. React从入门到放弃之前奏(3):Redux简介

    安装 npm i -S redux react-redux redux-devtools 概念 在redux中分为3个对象:Action.Reducer.Store Action 对行为(如用户行为) ...

随机推荐

  1. C#敏感关键词过滤代码

    System.Text.StringBuilder sb = new System.Text.StringBuilder(text.Length);             string filter ...

  2. Oracle order by case when 多条件排序

    ORACLE sql 排序 根据两个条件排序,根据id号由小到大排序,同时country字段是北京的排最前面前面,其次上海,..大连,最后是其他城市,怎么写? 写法如下:select * from p ...

  3. Linux下安装php加速组件XCache

    这里选择的是稳定版本的1.2.2版本,2.0版本的不稳定.wget http://xcache.lighttpd.net/pub/Releases/1.2.2/xcache-1.2.2.tar.gzt ...

  4. XML样本(格式没区别,但是一个有结果 一个没结果)

    xml样本01<orderlist>        <order>        <orderid>1</orderid>        <ord ...

  5. ACE的Socket初步

    Tcp通信过程一般为如下步骤: 服务器绑定端口,等待客户端连接. 客户端通过服务器的ip和服务器绑定的端口连接服务器. 服务器和客户端通过网络建立一条数据通路,通过这条数据通路进行数据交互. 常用AP ...

  6. JavaScript 目标装配式编程(Target Assemble Programming)

    TAP概述 脚本中一切皆对象,若还以传统模式思考编程模式,那简直是对不起脚本解释器的强大支持:我们应该以最接近人类操作方式的来表达人的意图. 更接近工作实践的方式,比如游戏中,一个人物一个角色,人物的 ...

  7. 纯蓝ICON_学习教程

  8. oracle行转列和列转行

    目录[-] 一.行转列 1.1.初始测试数据 1.2. 如果需要实现如下的查询效果图: 1.3.延伸 二.列转行 1.1.初始测试数据 1.2. 如果需要实现如下的查询效果图: 一.行转列 1.1.初 ...

  9. jquery ajax (2)实例 .GET

    1js 代码 $(function(){ $("#send").click(function(){ $.get("get3.php", { username : ...

  10. 转:Zend_Cache的使用

    一.Zend_Cache快速浏览 Zend_Cache 提供了一个缓存任何数据的一般方法. 在Zend Framework中缓存由前端操作,同时通过后端适配器(File, Sqlite, Memcac ...