[Redux] Avoiding Array Mutations with concat(), slice(), and ...spread
For Redux, you cannot use mutable methods like push, splice. Need to use immutable methods such as concat, slice and ...spread
Html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> <script src="https://wzrd.in/standalone/expect@latest"></script> <script src="https://wzrd.in/standalone/deep-freeze@latest"></script> </head> <body> </body> </html>
push() vs concat()
push: modify the array;
concat: return a new array;
console.clear(); const addCounter = (list)=>{ list.push(0); return list; } const testAddCounter = ()=>{ const beforeList = []; const afterList = [0]; deepFreeze(beforeList); expect( addCounter(beforeList) ).toEqual(afterList); } testAddCounter(); console.log("All tests passing.."); /** "error" "TypeError: Can't add property 0, object is not extensible at addCounter (fegewebemu.js:5:8) at testAddCounter (fegewebemu.js:15:10) at fegewebemu.js:18:1" */ console.clear(); const addCounter = (list)=>{ let res = list.concat(0); return res; } const testAddCounter = ()=>{ const beforeList = []; const afterList = [0]; deepFreeze(beforeList); expect( addCounter(beforeList) ).toEqual(afterList); } testAddCounter(); console.log("All tests passing.."); // passing
Using ...spread:
console.clear(); const addCounter = (list)=>{ return [...list, 0]; } const testAddCounter = ()=>{ const beforeList = []; const afterList = [0]; deepFreeze(beforeList); expect( addCounter(beforeList) ).toEqual(afterList); } testAddCounter(); console.log("All tests passing.."); // Passing
splice() vs slice()
splice: modfiy array;
slices: return new array;
console.clear(); const removeCounter= (list, index)=>{ list.splice(index, 1); return list; } const testRemoveCounter = ()=>{ const beforeList = [0 ,10,20]; const afterList = [0, 20]; deepFreeze(beforeList); expect( removeCounter(beforeList, 1) ).toEqual(afterList); } testRemoveCounter(); console.log("All tests passing.."); /** "error" "TypeError: Cannot add/remove sealed array elements at removeCounter (fegewebemu.js:5:8) at testRemoveCounter (fegewebemu.js:15:10) at fegewebemu.js:17:1" */ console.clear(); const removeCounter= (list, index)=>{ return list.slice(0, index) .concat(list.slice(index+1)); } const testRemoveCounter = ()=>{ const beforeList = [0 ,10,20]; const afterList = [0, 20]; deepFreeze(beforeList); expect( removeCounter(beforeList, 1) ).toEqual(afterList); } testRemoveCounter(); console.log("All tests passing.."); // Passing
ES6:
console.clear(); const removeCounter= (list, index)=>{ return [ ...list.slice(0, index), ....list.slice(index + 1) ]; } const testRemoveCounter = ()=>{ const beforeList = [0 ,10,20]; const afterList = [0, 20]; deepFreeze(beforeList); expect( removeCounter(beforeList, 1) ).toEqual(afterList); } testRemoveCounter(); console.log("All tests passing.."); // Passing
Modify one element in array:
console.clear(); const incrementCounter = (list, index) => { list[index]++; return list; }; const testIncrementCounter = ()=>{ const beforeList = [0 ,10,20]; const afterList = [0, 11, 20]; deepFreeze(beforeList); expect( incrementCounter(beforeList, 1) ).toEqual(afterList); } testIncrementCounter(); console.log("All tests passing.."); /** "error" "Error: Expected [ 0, 10, 20 ] to equal [ 0, 11, 20 ] at Object.assert [as default] (https://wzrd.in/standalone/expect@latest:489:9) at Expectation.toEqual (https://wzrd.in/standalone/expect@latest:70:26) at testIncrementCounter (fegewebemu.js:16:43) at fegewebemu.js:18:1" */ console.clear(); const incrementCounter = (list, index) => { let res = list.slice(0, index) .concat(++list[index]) .concat(list.slice(index+1)); return res; }; const testIncrementCounter = ()=>{ const beforeList = [0 ,10,20]; const afterList = [0, 11, 20]; deepFreeze(beforeList); expect( incrementCounter(beforeList, 1) ).toEqual(afterList); } testIncrementCounter(); console.log("All tests passing.."); // Passing
ES6:
console.clear(); const incrementCounter = (list, index) => { return [ ...list.slice(0, index), ++list[index], ...list.slice(index+1) ]; }; const testIncrementCounter = ()=>{ const beforeList = [0 ,10,20]; const afterList = [0, 11, 20]; deepFreeze(beforeList); expect( incrementCounter(beforeList, 1) ).toEqual(afterList); } testIncrementCounter(); console.log("All tests passing.."); // Passing