Open SampsonKY opened 4 years ago
纯函数是这样一种函数,即相同的输入,永远会得到相同的输出,而且没有任何可观察的副作用。
可观察的副作用
例子
function priceAfterTax(productPrice) { return (productPrice * 0.20) + productPrice;}
用处
reducer 就是一个纯函数,接受旧的 state 和 action,返回新的 state
redux 可以提供可预测化的状态管理。在一个应用中,所有的 state 都是以一个对象树的形式存在在一个单一的 store 中,唯一改变 state 的方法就是触发 action,而 reducer 就是用来编写专门的函数决定每个 action 如何改变应用的 state。
reducer的几种写法
直接返回一个对象
case 'TOGGLE': return { ...state, completed: !state.completed }
使用 Object.assign()返回一个对象
case 'TOGGLE': return Object.assign({},state,completed: !state.completed)
使用 Immutable.js 返回一个新对象
case 'TOGGLE': return state.updateIn(['completed'], ()=>!state.getIn('completed'))
为什么 reducer 必须是纯函数
修改传入的参数。如果直接修改 state的话,那么在reducer修改的那个时间内,redux里面依赖的历史数据的功能就没办法实现了。而且如果改变传入的state或state里面的key值,那么在react之前就应用了该state,它是无法判断该state是否有变化,从而不会更新。
不能调用非纯函数。如果调用非纯函数的话,相同的 action 可能导致不同的结果,这样 reducer 的处理过程是不可预料的。
不能执行有副作用的操作,涉及到后台,同样的 action 可能会出现不同的结果,会导致不可预料。其次是 API 的调用,因为 API 要请求一个异步函数,想让这个异步函数的返回结果应用到 state 上,但由于 reducer 新的 state(同步)是在异步请求完成之前返回的,所以异步函数无法影响到新的 state
redux源码:
通过源代码,我们发现,var nextStateForKey = reducer(previousStateForKey, action), nextStateForKey就是通过 reducer 执行后返回的结果(state),然后通过hasChanged = hasChanged || nextStateForKey !== previousStateForKey来比较新旧两个对象是否一致,此比较法,比较的是两个对象的存储位置,也就是浅比较法,所以,当我们 reducer 直接返回旧的 state 对象时,Redux 认为没有任何改变,从而导致页面没有更新。
var nextStateForKey = reducer(previousStateForKey, action)
hasChanged = hasChanged || nextStateForKey !== previousStateForKey
为什么这么设计
因为比较两个 javascript 对象中所有的属性是否完全相同,唯一的办法就是深比较,然而,深比较在真实的应用中代码是非常大的,非常耗性能的,需要比较的次数特别多,所以一个有效的解决方案就是做一个规定,当无论发生任何变化时,开发者都要返回一个新的对象,没有变化时,开发者返回就的对象,这也就是 redux 为什么要把 reducer 设计成纯函数的原因。
纯函数以及为什么要用纯函数
Reducer 为什么必须是纯函数?
纯函数是什么
可观察的副作用
例子
用处
redux 中的 reducer
redux 可以提供可预测化的状态管理。在一个应用中,所有的 state 都是以一个对象树的形式存在在一个单一的 store 中,唯一改变 state 的方法就是触发 action,而 reducer 就是用来编写专门的函数决定每个 action 如何改变应用的 state。
reducer的几种写法
直接返回一个对象
使用 Object.assign()返回一个对象
使用 Immutable.js 返回一个新对象
为什么 reducer 必须是纯函数
修改传入的参数。如果直接修改 state的话,那么在reducer修改的那个时间内,redux里面依赖的历史数据的功能就没办法实现了。而且如果改变传入的state或state里面的key值,那么在react之前就应用了该state,它是无法判断该state是否有变化,从而不会更新。
不能调用非纯函数。如果调用非纯函数的话,相同的 action 可能导致不同的结果,这样 reducer 的处理过程是不可预料的。
不能执行有副作用的操作,涉及到后台,同样的 action 可能会出现不同的结果,会导致不可预料。其次是 API 的调用,因为 API 要请求一个异步函数,想让这个异步函数的返回结果应用到 state 上,但由于 reducer 新的 state(同步)是在异步请求完成之前返回的,所以异步函数无法影响到新的 state
redux源码:
通过源代码,我们发现,
var nextStateForKey = reducer(previousStateForKey, action)
, nextStateForKey就是通过 reducer 执行后返回的结果(state),然后通过hasChanged = hasChanged || nextStateForKey !== previousStateForKey
来比较新旧两个对象是否一致,此比较法,比较的是两个对象的存储位置,也就是浅比较法,所以,当我们 reducer 直接返回旧的 state 对象时,Redux 认为没有任何改变,从而导致页面没有更新。为什么这么设计
因为比较两个 javascript 对象中所有的属性是否完全相同,唯一的办法就是深比较,然而,深比较在真实的应用中代码是非常大的,非常耗性能的,需要比较的次数特别多,所以一个有效的解决方案就是做一个规定,当无论发生任何变化时,开发者都要返回一个新的对象,没有变化时,开发者返回就的对象,这也就是 redux 为什么要把 reducer 设计成纯函数的原因。
参考
纯函数以及为什么要用纯函数
Reducer 为什么必须是纯函数?