什么是reducer
2020年7月2日 • ... • ☕️ 2 min read
reducer的概念之前就有,不过近年来随着redux的使用为我们所熟知。那么reducer是什么呢?
通常情况下,reducer会接受两个参数:当前状态(累加值)和一个action(当前值),然后返回一个新的状态。
(state, action) => newState
基本上,我在三个地方使用reducer(或其概念):数组、react的useReducer和redux的reducer。
数组方法Array.prototype.reduce
reduce会在数组的每个元素上依次调用回调方法,并最终返回一个值。用法为
const arr = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
arr.reduce(reducer); // output 10
可以看到,reduce接受一个函数作为reducer,这个函数就是reduce方法的关键。
reducer接受4个参数:累加器、当前值、当前下标、原始数组。
reducer(accumulator, currentValue[, index[, array]] )
必要的两个参数是:累加器(state)和当前值(action)。
开始在元素上依次执行reducer:
当前下标 | 累加器(state) | 当前值(action) | result |
---|---|---|---|
0 | 0 | 1 | 1 |
1 | 1 | 2 | 3 |
2 | 3 | 3 | 6 |
3 | 6 | 4 | 10 |
可以看出,state每次都是不一样的(可以想到,内部有个循环,核心功能是当次函数的输出,作为下次函数的输入)。
用map模拟一下,流程差不多是这样(忽略state和action意外的参数):
Array.prototype._reduce = function (fn) {
let res = 0;
this.map((item, index) => {
res = fn(res, item);
});
return res;
}
const arr = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
arr._reduce(reducer); // output 10
react中的useReducer
一样的思路。
const [state, dispatch] = useReducer(reducer, initialArg, init);
useReducer接受一个reducer和初始化函数,返回当前的state和分发函数(dispatch)。这里的state只能通过dispatch来更改,没有具体的setXxx函数。
reducer是核心函数,接受两个参数:state和action。
摘取官方范例:
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState); return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
state存储在hooks的内部来控制。相当于批量处理了useState,并伸出统一的dispatch方法,通过该方法实际操作state。
注意,dispatch除了type,还可以携带其他参数(如累加具体数值),扩展性更强。
如果把这个结构放在app的最外层,将state作为context传入整个app,那么就是一个简单的redux替代品,如。
redux的reducer
-> 文档在此