Redux - 纯函数

函数是一个过程,它接受称为参数的输入,并产生一些称为返回值的输出。 如果一个函数遵循以下规则,则称为纯函数 −

  • 函数对于相同的参数返回相同的结果。

  • 它的评估没有副作用,即它不会改变输入数据。

  • 局部和全局变量没有变化。

  • 它不像全局变量那样依赖于外部状态。

让我们以一个函数为例,该函数返回作为函数输入传递的值的两倍。一般来说,可以写为:f(x) => x*2。 如果使用参数值 2 调用函数,则输出将为 4,f(2) => 4。

让我们用 JavaScript 编写函数的定义,如下所示−

const double = x => x*2; // es6 arrow function
console.log(double(2));  // 4

这里,double是一个纯函数。

根据Redux的三原则,改变必须通过纯函数,即Redux中的reducer来进行。 现在,出现了一个问题:为什么reducer必须是纯函数。

假设您想要调度一个类型为'ADD_TO_CART_SUCCESS'的操作,通过单击"添加到购物车"按钮将商品添加到您的购物车应用程序。

让我们假设reducer正在向您的购物车添加一个商品,如下所示−

const initialState = {
   isAddedToCart: false;
}
const addToCartReducer = (state = initialState, action) => { //es6 arrow function
   switch (action.type) {
      case 'ADD_TO_CART_SUCCESS' :
         state.isAddedToCart = !state.isAddedToCart; //original object altered
         return state;
      default:
         return state;
   }
}
export default addToCartReducer ;

让我们假设,isAddedToCart 是状态对象上的一个属性,它允许您通过返回布尔值"true 或 false"来决定何时禁用该项目的"添加到购物车"按钮 '。 这可以防止用户多次添加同一产品。 现在,我们不再返回一个新对象,而是像上面那样在状态上改变 isAddedToCart 属性。 现在,如果我们尝试将商品添加到购物车,则什么也不会发生。 添加到购物车按钮不会被禁用。

造成此行为的原因如下 −

Redux 通过新旧对象的内存位置来比较这两个对象。 如果发生任何变化,它期望来自reducer的新对象。 如果没有发生变化,它还期望取回旧对象。 在这种情况下,也是一样的。 由于这个原因,Redux 假设什么都没有发生。

所以,Redux中的reducer必须是纯函数。 以下是不变异的写法 −

const initialState = {
   isAddedToCart: false;
}
const addToCartReducer = (state = initialState, action) => { //es6 arrow function
   switch (action.type) {
      case 'ADD_TO_CART_SUCCESS' :
         return {
            ...state,
            isAddedToCart: !state.isAddedToCart
         }
      default:
         return state;
   }
}
export default addToCartReducer;