Configuration

There is a second argument to the store that sets configuration. 99% of the time you should not have to worry/care about these options.

const myConfiguredCollection = collection(
{x: 1, y: 2},
{quiet: true, compItems: myCompFunction, compKeys: myCompFunction}
);

Quiet: boolean

For upcoming observation utilities, the "quiet" option blocks the collection from broadcasting feedback to the onChange method.

Comparators: advanced

functions like get, deleteKey, deleteItem, hasKey or hasItem by default use a comparator to see if a value in the collection matches the argument(s) from the call. By default it uses === conmparison. So, an equivalent value will NOT be an equivalent match, if they are compound types.

const mapC = collect(new Map([]));
mapC
.set(1, 'happy')
.set({ x: 1, y: 1 }, 'sad')
.set('Bob', 'angry')
.set(Symbol('unique'), 'lonely');
console.log('mapC=', mapC.value);
console.log('numbers');
console.log('has 1', mapC.hasKey(1));
console.log('objects');
console.log('has {x: 1, y: 1}', mapC.hasKey({ x: 1, y: 1 }));
console.log('strings');
console.log('has "Bob"', mapC.hasKey('Bob'));
console.log('symbols');
console.log('has Symbol("unique")', mapC.hasKey(Symbol('unique')));
/*
mapC= Map(4) {
1 => 'happy',
{ x: 1, y: 1 } => 'sad',
'Bob' => 'angry',
Symbol(unique) => 'lonely'
}
numbers
has 1 true
objects
has {x: 1, y: 1} false
strings
has "Bob" true
symbols
has Symbol("unique") false
*/

Many of these examples fail for complex types (object, Symbol) because a new item reference is created with each line of code.

We can fix this.

the comparator used here is .sameKey. This property can be set in creation or changed at any time.

import toString from 'lodash.tostring';
const mapC = collect(new Map([]), {
compKeys: (item1, item2) => {
try {
item1 = JSON.stringify(item1);
} catch (_e) {
item1 = toString(item1);
}
try {
item2 = JSON.stringify(item2);
} catch (_e2) {
item2 = toString(item2);
}
console.log('comparing', item1, 'and', item2);
return item1 === item2;
},
});
mapC
.set(1, 'happy')
.set({ x: 1, y: 1 }, 'sad')
.set('Bob', 'angry')
.set(Symbol('unique'), 'lonely');
console.log('mapC=', mapC.value);
console.log('numbers');
console.log('has 1', mapC.hasKey(1));
console.log('objects');
console.log('has {x: 1, y: 1}', mapC.hasKey({ x: 1, y: 1 }));
console.log('strings');
console.log('has "Bob"', mapC.hasKey('Bob'));
console.log('symbols');
console.log('has Symbol("unique")', mapC.hasKey(Symbol('unique')));
/*
mapC= Map(4) {
1 => 'happy',
{ x: 1, y: 1 } => 'sad',
'Bob' => 'angry',
Symbol(unique) => 'lonely'
}
numbers
has 1 true
objects
comparing 1 and {"x":1,"y":1}
comparing {"x":1,"y":1} and {"x":1,"y":1}
has {x: 1, y: 1} true
^ ^ ^ ^ This is the important difference --
an object LIKE the compared-to key is registered as present
strings
has "Bob" true
symbols
comparing 1 and undefined
comparing {"x":1,"y":1} and undefined
comparing "Bob" and undefined
comparing undefined and undefined
has Symbol("unique") true
*/

By flattening complex objects to stringy representations, things that "look" the same are considered equivalent.

There are two comparators:

compKeys(key1, key2, collection?) => boolean

demonstrated above; used in Map.get, hasKey, deleteKey

compItems(key1, k2, colletcion>) => boolean

used in hasItem, deleteItem

Temporary comparators

withComp(action : function, comp: {compItems?: function, compKeys?: function}): result of action

You can temporarily assert a comparator for an operation via "withComp". The passed in comparators are used during the execution of the function, then returned to their previous values.

The result of the action, if any, is returned.

Beware - this is a synchronous change; use of async functions or promises will not benefit from the temporary comparators.