Open kurdin opened 9 years ago
Hello @kurdin. You cannot pass parameters to a monkey. Monkeys should remain pure reduction of parts of the tree's state. This said, your problem actually has three solutions:
// Using lodash `indexBy`
// https://lodash.com/docs#indexBy
// Using this monkey
monkey({
cursors: {
boxes: ['boxes']
},
get: function(boxes) {
return indexBy(boxes, 'id');
}
});
tree.get('getBoxes', desiredId);
var cursorForSpecificBox = tree.select('boxes', function(box) {
return box === desiredId;
});
// or using the object notation shorthand
var cursorForSpecificBox = tree.select('boxes', {id: desiredId});
// note that those tricks also work with `get`
I hope this will help you.
Thanks for examples. Now I see that this can be done in different ways.
Another question about monkey:
from docs:
The dynamic nodes are lazy and won't actually be computed before you get them (plus they will only compute once before they need to change, so if you get the same dynamic node twice, the computation won't rerun).
but when I just define monkey and create Baobab tree, I can see that monkey function is executed. If I change Baobab array with push, monkey function fires again for each item in the array. is it normal, it does not sound like lazy.
Here is the code:
var state = {
boxes: [
{id: 1437507218061, top: 33, left: 155, width: 300, height: 300},
{id: 1437507218062, top: 33, left: 355, width: 10, height: 400}
],
getBoxIds: Baobab.monkey({
cursors: {
boxes: ['boxes']
},
get: function(data) {
console.log('data.boxes in get', data.boxes);
return data.boxes.map(function(b) {
console.log('b.id', b.id);
return b.id;
});
}
})
};
var State = new Baobab(state);
console.log('pre getBoxIds id');
console.log('State getBoxIds id', State.get('getBoxIds'));
console.log('post getBoxIds id');
State.select('boxes').push({id: 1437507218064, top: 33, left: 155, width: 300, height: 300});
console.log('State another getBoxIds id', State.get('getBoxIds'));
console output
data.boxes in get [Object, Object]
b.id 1437507218061
b.id 1437507218062
data.boxes in get [Object, Object]
pre getBoxIds id
State getBoxIds id [1437507218061, 1437507218062]
post getBoxIds id
data.boxes in get [Object, Object, Object]
b.id 1437507218061
b.id 1437507218062
b.id 1437507218064
data.boxes in get [Object, Object, Object]
State getBoxIds id 2 [1437507218061, 1437507218062, 1437507218064]
Another separate problem I have with sort inside monkey. If I add monkey sortById
sortById: Baobab.monkey({
cursors: {
boxes: ['boxes']
},
get: function(data) {
console.log('data.boxes in get', data.boxes);
return data.boxes.sort(function(a, b) {
var x = a['id']; var y = b['id'];
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
}
})
};
I got error: Uncaught TypeError: Cannot assign to read only property '1' of [object Array]
data.boxes
inside monkey get
seem to be a normal array, I don't understand why sort function does not work with it. Is not monkey a good place for creating different sort methods?
Hello @kurdin. Let me check this more thoroughly. Concerning your last question: the thing is the tree's data is immutable by default and the Array.prototype.sort
in JS actually mutates the array. Hence the error thrown.
@Yomguithereal I realised about immutable array after couple of tests. I think it would be very useful if .get()
method can return normal array that you can change, or maybe implement something like toJS()
. If everything is immutable in would be difficult to do any type of sorting. I guess workaround for now is to disable immutable tree.
We are discussing the addition of such methods in #380.
@kurdin I like using the spread-operators when immutability is preventing/helping me from doing something.
let sortedNumbers = [...tree.get('numbers')].sort((a,b) => a-b)
Looks neat to me, the same can be done for objects with the help of experimental features
let renamed = { name: 'default name', ...tree.get('person'), name: 'Zache' };
The biggest downside probably being extra GC pressure?
That's the exact same downside with cloning. But you cannot really get around it anyway.
Can I pass param to monkey?
I want to get Box with id and put watcher on it