Features
Leaf Values, 'next', delKeys

Leaf's Value

There are no limitations on the Leaf's value - the first argument of the leaf. A leaf's value can be an object, a map, a string, number, Date, array, or any other Javascript variable type.

Objects and Maps will get cloned every time one of their values change; so it's not a good idea to use an object that relies on its prototype for meaning; for instance putting a DOM object into a Leaf is probably going to be problematic. see setMeta for how to attach complex objects to a state.

Compound Values

Objects, maps, and arrays are considered compound values; they will(1) get setters inferred for their values in the .do method collection.

A leaf's current value is accessed from the myLeaf.value property. You can get or set that value directly to update state:

 
const numberLeaf = new Forest(${value: 6});
const stringLeaf = new Forest(${value: 'Bob'});
const objectLeaf = new Forest({$value: {x: 0, y: 0}});
const mapLeaf = new Forest({$value: new Map([
    ['x', 0],
    ['y', 0]
  ])
});
 
numberLeaf.value = 10;
console.log('new number leaf value:', numberLeaf.value);
 
stringLeaf.value = 'Rick'
console.log('new string leaf value: ', stringLeaf.value);
 
objectLeaf.value = {y: 3, z: 6};
console.log('new object leaf value', objectLeaf.value);
 
mapLeaf.value =new Map([['y', 3], ['z', 6]]);
console.log('new map leaf value', mapLeaf.value);
 
/**
      new number leaf value: 10
      new string leaf value:  Rick
      new object leaf value { x: 0, y: 3, z: 6 }
      new map leaf value Map(3) { 'x' => 0, 'y' => 3, 'z' => 6 }
*/
 

Keeping the same form

By default -- you can change the value to any type of content you want. If you pass {type: true} to the constructor, Forest will block any attempts to change the form of the value to a different type.

 
  const point = new Forest({$value: { x: 1, y: 2 }, type: true });
  point.subscribe(value => console.log('value of point', value));
  point.next({ x: 3, y: 4 });
  try {
    point.value = 'Bob'
  } catch (err) {
    console.log('bad form error: ', err);
  }
  point.next({ x: 5, y: 6 });
 
  /**
   value of point { x: 1, y: 2 }
   value of point { x: 3, y: 4 }
   bad form error:  Error: incorrect form for leaf [ROOT]; wanted Symbol(form:object), got Symbol(form:value)...
   value of point { x: 5, y: 6 }
   */
 

otherwise, by default, you can mangle your state's type all you like:

 
const point = new Forest({ x: 1, y: 2 });
point.subscribe(value => console.log('value of unguarded point', value));
point.next({ x: 3, y: 4 });
try {
  point.next('Bob');
} catch (err) {
  console.log('unguarded bad form error: ', err);
}
point.next({ x: 5, y: 6 });
 
/**
 value of  unguarded point { x: 1, y: 2 }
 value of  unguarded point { x: 3, y: 4 }
 value of  unguarded point Bob
 value of  unguarded point { x: 5, y: 6 }
 */
 

That being said there are side effects to changing the type/form of a Forest instance's value; see /actions for details on how it affects actions, and /children for how it affects child Leafs.

delKeys(name | names[])

If you want to actually delete an index, you can pass one or more keys to delKey and it will remove them from a compound object.

 
const objectLeaf = new Forest({x: 0, y: 0});
const mapLeaf = new Forest(new Map([
  ['x', 0],
  ['y', 0]
]));
 
objectLeaf.next({y: 3, z: 6});
console.log('new object leaf value', objectLeaf.value);
 
mapLeaf.next(new Map([['y', 3], ['z', 6]]));
console.log('new map leaf value', mapLeaf.value);
mapLeaf.delKeys('y');
console.log('new map leaf value without y', mapLeaf.value);
 
/**
  new number leaf value: 10
  new string leaf value:  Rick
  new object leaf value { x: 0, y: 3, z: 6 }
  new map leaf value Map(3) { 'x' => 0, 'y' => 3, 'z' => 6 }
  new map leaf value without y Map(2) { 'x' => 0, 'z' => 6 }
*/
 
Last updated on April 8, 2023