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' 的 action,通过单击“添加到购物车”按钮将商品添加到您的购物车应用程序中。
让我们假设 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 是 state 对象上的一个属性,它允许您通过返回布尔值 “true 或 false” 来决定何时禁用商品的“添加到购物车”按钮。这可以防止用户多次添加同一产品。现在,我们不是返回一个新对象,而是像上面那样修改 state 上的 isAddedToCart 属性。现在,如果我们尝试将商品添加到购物车,则不会发生任何事情。“添加到购物车”按钮不会被禁用。
这种行为的原因如下:
Redux 通过比较两个对象的内存位置来比较旧对象和新对象。如果发生任何更改,它期望 reducer 返回一个新对象。并且如果没有任何更改,它也期望获得旧对象。在这种情况下,它是一样的。由于这个原因,Redux 假设什么也没有发生。
因此,reducer 在 Redux 中必须是纯函数是必要的。以下是在不进行修改的情况下编写它的方法:
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;