immutant v0.1.10
Immutant
The library allows you to make changes to objects and arrays, including nested structures, without changing the original object. It is fast, well-tested and has simple convenient API.
Installation
npm install immutant
Usage example
import I from 'immutant'
let state, nextState
state = {products: {}, cart: {totals: {}, items: [{id: 1, qty: 1}, {id: 2, qty: 1}, {id: 3, qty: 1}]}}
nextState = I(state).set(5, ['cart', 'items', 1, 'qty']).result // update item by index
// {products: {}, cart: {totals: {}, items: [{id: 1, qty: 1}, {id: 2, qty: 5}, {id: 3, qty: 1}]}}
nextState = I(state).set(5, ['cart', 'items', i => i.id === 2, 'qty']).result // update item by predicate
// {products: {}, cart: {totals: {}, items: [{id: 1, qty: 1}, {id: 2, qty: 5}, {id: 3, qty: 1}]}}
nextState = I(state) // chain updates
.set(7, ['cart', 'items', i => i.id === 2, 'qty'])
.delete(['cart', 'items', i => i.id === 3])
.push({id: 4, qty: 1}, ['cart', 'items'])
.result
// {products: {}, cart: {totals: {}, items: [{id: 1, qty: 1}, {id: 2, qty: 7}, {id: 4, qty: 1}]}}
API
Immutant has only 3 basic and 3 auxiliary methods.
Common path argument can contain strings (for keys), numbers (for indexes) or functions (predicates for searching item in array)
I.set(value: any, path: array)
Works both with objects and arrays.
Update element in flat object:
state = {a: 1, b: 2, c: 3}
nextState = I(state).set(5, ['b']).result
// {a: 1, b: 5, c: 3}
Update element in flat array:
state = [1, 2, 3]
nextState = I(state).set(5, [1]).result
// [1, 5, 3]
Update element in nested object:
state = {a: 1, b: 2, nested: {c: 3, d: 4}}
nextState = I(state).set(5, ['nested', 'd']).result
// {a: 1, b: 2, nested: {c: 3, d: 5}}
Update element in nested array by index:
state = {a: 1, b: 2, nested: [3, 4, 5]}
nextState = I(state).set(7, ['nested', 1]).result
// {a: 1, b: 2, nested: [3, 7, 5]}
Update element in nested array by predicate:
state = {a: 1, b: 2, nested: [3, 4, 5]}
nextState = I(state).set(7, ['nested', i => i === 4]).result
// {a: 1, b: 2, nested: [3, 7, 5]}
Update element in nested object inside array, by index:
state = {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 1}, {id: 3, qty: 1}]}
nextState = I(state).set(3, ['items', 1, 'qty']).result
// {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 3}, {id: 3, qty: 1}]}
Update element in nested object inside array, by predicate:
state = {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 1}, {id: 3, qty: 1}]}
nextState = I(state).set(3, ['items', i => i.id === 2, 'qty']).result
// {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 3}, {id: 3, qty: 1}]}
I.push(value: any, path: array)
Works with arrays only.
state = {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 1}]}
nextState = I(state).push({id: 3, qty: 1}, ['items']).result
// {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 1}, {id: 3, qty: 1}]}
I.delete(path: array)
Works both with objects and arrays.
state = {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 1}, {id: 3, qty: 1}]}
nextState = I(state).set(3, ['items', i => i.id === 2, 'qty']).result
// {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 3}, {id: 3, qty: 1}]}
get(path: array)
Works both with objects and arrays.
state = {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 1}, {id: 3, qty: 1}]}
value = I(state).get(['items', i => i.id === 2, 'qty'])
// 1
copy(path: array)
Shallow copy of object with cloned item located at path.
Works both with objects and arrays.
state = {a: {}, b: {c: {}, d: {}};
nextState = I(state).copy(['b', 'd']).result;
// nextState !== state
// nextState.a === state.b
// nextState.b !== state.b
// nextState.b.c === state.b.c
// nextState.b.d !== state.b.d
chain api
state = {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 1}]}
nextState = I(state)
.set(3, ['items', i => i.id === 2, 'qty'])
.delete(['items', i => i.id === 1])
.push({id: 3, qty: 1}, ['items'])
.set(state.b + 1, ['b'])
.result
// {a: 1, b: 3, items: [{id: 2, qty: 3}, {id: 3, qty: 1}]}
diff(otherObject: object)
Helper method for debug or logging purposes.
let state = {a: 1, b: 2, items: [{id: 1, qty: 1}, {id: 2, qty: 1}], totals: [1, 2, 3]};
let nextState = I(state)
.set(3, ['items', i => i.id === 2, 'qty'])
.push({id: 3, qty: 1}, ['items'])
.set(state.b + 1, ['b'])
.result;
console.log(I(nextState).diff(state));
// [
// { path: '(root)', msg: 'different reference' },
// { path: 'b', msg: 'changed', value: 3 },
// { path: 'items', msg: 'different reference' },
// { path: 'items.1', msg: 'replace', value: { id: 2, qty: 3 } },
// { path: 'items.2', msg: 'add', value: { id: 3, qty: 1 } }
// ]
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago