[Redux] Reducer Composition with Arrays
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的更多相关文章
- [Redux] Reducer Composition with combineReducers()
Previous, we do composition with objects: const todoApp = (state = {}, action) => { return { todo ...
- redux reducer笔记
踩坑一,reducer过于抽象 reducer写得没那么抽象也不会有人怪你的.^_^ reducer其实只有一个,由不同的reducer composition出来的.所以, reducer的父作用域 ...
- Redux生态系统
生态系统 Redux 是一个体小精悍的库,但它相关的内容和 API 都是精挑细选的,足以衍生出丰富的工具集和可扩展的生态系统. 如果需要关于 Redux 所有内容的列表,推荐移步至 Awesome R ...
- react+redux教程(四)undo、devtools、router
上节课,我们介绍了一些es6的新语法:react+redux教程(三)reduce().filter().map().some().every()....展开属性 今天我们通过解读redux-undo ...
- [React Testing] Redux Reducers
Sometimes we want to test our Redux reducers to make sure they work as expected. In this lesson we w ...
- 深入Redux架构
关于redux 之前写了一篇通过一个demo了解Redux,但对于redux的核心方法没有进行深入剖析,在此重新总结学习,完整的代码看这里.(参考了React 技术栈系列教程) 什么情况需要用redu ...
- redux入门指南
前言:大概一个月没有写博客了,这两天正好是周末,就写点东西来梳理下之前几个月的所写与所得; 大概两个月前,学习了一下 redux ,还是一点难度的,花了我一天的时间来搞明白他, 但是都没怎么记录,今天 ...
- redux (一)
redux 是一个状态管理的库. redux认为页面所有的变化,都是基于状态的改变触发的,所以我们维护一个应用的时候,都是在维护这些状态.而 redux 就是为了维护状态而生的. API create ...
- React从入门到放弃之前奏(3):Redux简介
安装 npm i -S redux react-redux redux-devtools 概念 在redux中分为3个对象:Action.Reducer.Store Action 对行为(如用户行为) ...
随机推荐
- UIScrollView设置了contentSize后还是没办法滚动?
1.最常见的原因是 contentSize 这个属性,比uiscrollview的frame要小, 无需滚动, 自然就滚动不了. scrollenabled 这个属性,标识着是否允许滚动,要言设成ye ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第三章:搜索、高级过滤和视图模型
在这一章中,我们首先添加一个搜索产品的模块以增强站点的功能,然后使用视图模型而不是ViewBag向视图传递复杂数据. 注意:如果你想按照本章的代码编写示例,你必须完成第二章或者直接从www.apres ...
- 2.2.1 创建一个 Path
Demo: import java.nio.file.Path; import java.nio.file.Paths; /** * @author jinxing * @系统 MAC OS X * ...
- 数据库备份工具mysqldump重要参数详解
1. --single-transaction InnoDB 表在备份时,通常启用选项 --single-transaction 来保证备份的一致性,实际上它的工作原理是设定本次会话的隔离级别为:RE ...
- 原生JS 选项卡代码实现
可实现同页面多个选项卡 效果图: 代码实现: HTML部分 <div class="main" id="tabs"> <div class=& ...
- mapreduce (三) MapReduce实现倒排索引(二)
hadoop api http://hadoop.apache.org/docs/r1.0.4/api/org/apache/hadoop/mapreduce/Reducer.html 改变一下需求: ...
- Web分析日志
http://www.docin.com/p-649515490.html http://wenku.baidu.com/link?url=kB-83fbl1Zc3Y6U2BYLj-lKMWShe8Z ...
- ASP.NET 查询客户端请求IP地址
public class CheckIP { #region 获取浏览器版本号 /// <summary> /// 获 ...
- hdu 3912 Turn Right
http://acm.hdu.edu.cn/showproblem.php?pid=3912 这个题我用递归深搜模拟,直接爆栈了.哭啊!为什么! 这个题最主要是能走重复格子,但是方向不一样. 我用的剪 ...
- 【Algorithm】逆序数的分治求解
逆序数的分治求解,时间复杂度O(nlgn).基本思想是在归并排序的基础上加逆序计数. #include <iostream> #include <cstdio> #includ ...