preface
Redux/flux requires the return of a new object to trigger data update and re-render. The general recommended method is to use object structure:
return {
...state,
enabled: true,}Copy the code
If you want to change the state. The Settings. Profile. Darkmode, probably will become like this:
return {
...state,
settings: {... State.settings, profile: {... state.settings.profile,darkmode: true,}}}Copy the code
There are two problems:
- If the state object is large (note: the object is large), the process of structuring and copying the state will take a long time
- The above changes
state.settings.profile.darkmode
To take,“Huge” job
How to solve these two possible problems in using Redux is the focus of this article.
Corresponding to this article, this article contains contents:
-
Immutable data
- New data structure
- facebook/immutable-js
- swannodette/mori
- Native JS data form
- rtfeldman/seamless-immutable
- planttheidea/crio
- aearly/icepick
- New data structure
-
Immutable Update utility
- mweststrate/immer
- kolodny/immutability-helper
- mariocasciaro/object-path-immutable
- debitoor/dot-prop-immutable
-
Immutable/Redux interoperability
- gajus/redux-immutable
- eadmundo/redux-seamless-immutable
Conclusion first, 80% to 90% of the scenes, just use immer.
Immutable data
facebook/immutable-js
Repository address: Facebook /immutable-js
Reference reading:
- Intensive reading Immutable structure sharing
- The Implementation of IMmutable.js
- The Implementation mechanism of IMmutable. Js
In short:
- Immutable -js builds new data structures to solve the first problem of slow copying of large structures in a spatial-temporal manner
- And through the
stateMap.setIn(['settings', 'profile', 'darkmode'], true)
To solve the second problem
But the corresponding
- If the object is small, you don’t need immutable-js
- Be aware of the differences and operations between immutable data and native data
swannodette/mori
Warehouse Address:swannodette/mori
Should be left over from history, not to repeat.
rtfeldman/seamless-immutable
Warehouse address: rtfeldman/seamless-immutable
var array = Immutable([1.2.3]);
array.map(value= > [value+2, value+4]);
// returns Immutable([ [ 3, 5 ], [ 4, 6 ], [ 5, 7 ] ])
Immutable.flatMap(array, value => [value+2, value+4]);
// returns Immutable([ 3, 5, 4, 6, 5, 7 ])
Copy the code
Reference reading:
- Seamless -Immutable API
- Seamless -immutable source reading notes
- Immutable; React; Immutable
Frozen immutable groups/objects, backward compatible JS
Immutation-js does not build new data structures. Instead, it extends javascript array and object by freezing some native array and object methods, such as pop and push
planttheidea/crio
Warehouse address: Planttheidea/Crio
An immutable JS Object with an API is essentially a seamless-immutable Object. It inherits the native Array and Object, but also overwrites/encapsulates methods like push and pop. That eventually returns a new CRIo immutable array as well
- CrioArray pop
- CrioArray push
This is different from the native [].push and [1, 2].pop methods. Note that these two methods return the length of the array, which introduces differences that feel more difficult to control and do more harm than good.
// you can assign with crio() directly
const crioArray = crio(['foo']);
const updatedCrioArray = crioArray.push('bar');
const crioObject = crio({foo: 'bar'});
const updatedCrioObject = crioObject.set('bar'.'baz');
// or use the convenience methods
const otherCrioArray = crio.array(['bar']);
const updatedOtherCrioArray = otherCrioArray.push('bar');
const otherCrioObject = crio.object({bar: 'baz'});
const updatedOtherCrioObject = otherCrioObject.set('bar'.'baz');
Copy the code
Reference reading:
- Difference with seamless-immutable?
- Why not just use X immutable library?
aearly/icepick
Warehouse address: aearly/icepick
Another wheel. It’s almost like seamless-immutable. Maybe the difference is that this is a utility function like LoDash. Seamless -immutable is the object-oriented way.
Note that it is internally similar to seamless-immutable, creating new objects via object shallow copy, slice array, and planttheidea/crio via inheritance and re-new.
var coll = {a: 1.b: 2};
var newColl = icepick.assoc(coll, "b".3); // {a: 1, b: 3}
var arr = ["a"."b"."c"];
var newArr = icepick.assoc(arr, 2."d"); // ["a", "b", "d"]
Copy the code
Reference reading:
- Why not just use Immutable.js or mori?
- How does this differ from React.addons.update or seamless-immutable.
Combined with these five libraries, Facebook/imMUTation-js solves the two problems mentioned above, but is relatively heavy.
And these three, because all use native JS data structure, relative, actually solve the second problem above, the significance is not very big.
- rtfeldman/seamless-immutable
- planttheidea/crio
- aearly/icepick
In addition, the number of star in the latter two warehouses is small. Of course, the specific codes are not carefully studied, so specific problems and specific scenarios need to be analyzed to make the corresponding technology selection.
But is it really necessary to introduce immutable data structures if the first problem is not obvious, just to solve the second problem? To remember the corresponding new object, array new method?
Immutable Update utility
This part simply deals with the second problem, without new data structures and data objects. Four libraries are included:
- debitoor/dot-prop-immutable
- kolodny/immutability-helper
- mariocasciaro/object-path-immutable
- mweststrate/immer
Recommend mweststrate/immer directly
dot-prop-immutable
Storage address: debitoor/dot-prop-immutable
Just some helper methods.
var dotProp = require('dot-prop-immutable');
var state = { todos: [] }, index = 0;
// Add todo:
state = dotProp.set(state, 'todos', list => [...list, {text: 'cleanup'.complete: false}])
// or with destructuring assignmentstate = {... state,todos: [...state.todos, {text: 'cleanup'.complete: false}};//=> { todos: [{text: 'cleanup', complete: false}] }
// Complete todo:
state = dotProp.set(state, `todos.${index}.complete`.true)
// or with destructuring assignmentstate = {... state,todos: [
...state.todos.slice(0, index), {... state.todos[index],complete: true},
...state.todos.slice(index + 1)]};//=> { todos: [{text: 'cleanup', complete: true}] }
// Delete todo:
state = dotProp.delete(state, `todos.${index}`)
// or with destructuring assignmentstate = {... state,todos: [
...state.todos.slice(0, index), ... state.todos.slice(index +1)]};//=> { todos: [] }
Copy the code
kolodny/immutability-helper
Warehouse address: Kolodny /immutability- Helper
Just some helper writing ($method)
import update from 'immutability-helper';
const newData = update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [9]}}});const initialArray = [1.2.3];
const newArray = update(initialArray, {$push: [4]}); // => [1, 2, 3, 4]
const collection = [1.2, {a: [12.17.15]}];
const newCollection = update(collection, {2: {a: {$splice: [[1.1.13.14]]}}});
// => [1, 2, {a: [12, 13, 14, 15]}]
const obj = {a: 5.b: 3};
const newObj = update(obj, {b: {$apply: function(x) {return x * 2; }}});// => {a: 5, b: 6}
// This is equivalent, but gets verbose for deeply nested collections:
const newObj2 = update(obj, {b: {$set: obj.b * 2}});
Copy the code
mariocasciaro/object-path-immutable
Storage address: Mariocasciaro /object-path-immutable
Much the same, the helper method, returns a new data object
const newObj1 = immutable.set(obj, 'a.b'.'f')
const newObj2 = immutable.set(obj, ['a'.'b'].'f')
/ / {
// a: {
// b: 'f',
// c: ['d', 'f']
/ /}
// }
// Note that if the path is specified as a string, numbers are automatically interpreted as array indexes.
const newObj = immutable.set(obj, 'a.c.1'.'fooo')
/ / {
// a: {
// b: 'f',
// c: ['d', 'fooo']
/ /}
// }
Copy the code
mweststrate/immer
Warehouse address: Mweststrate /immer
import produce from "immer"
const baseState = [
{
todo: "Learn typescript".done: true
},
{
todo: "Try immer".done: false}]const nextState = produce(baseState, draftState => {
draftState.push({todo: "Tweet about it"})
draftState[1].done = true
})
Copy the code
DraftState is passed to function as a Proxy for the original object.
Function (with side effects) directly changes draftState, and produce returns the new object.
I recommend using immer directly, after all, you are the author of Mobx, after all, you are winning awards. This is a very intuitive way to write it, and it doesn’t need to return.
Reference reading: close reading of immer.js source code
Immutable/Redux interoperability
gajus/redux-immutable
Storage address: Gajus /redux-immutable
A tool that combines IMMUTABLE js with REdux
eadmundo/redux-seamless-immutable
Storage address: eadmundo/redux-seamless-immutable
A tool that combines seamless-immutable with REdux
Since you wouldn’t necessarily use immutation-js for the first problem, the second problem would work just fine with immer, and there’s no need to use either tool.
Other reference
Redux – Ecosystems – Immutable data