Basics

GState is very simple. In one aspect, it works like an in-memory database.

Create a state:

const state = new GState();

Put an value into state:

state.set({a: "a"});

Query state:

state.get({a: 1}); // => {a: "a"}

Or watch state changes (same with state.get but reactive)

state.watch({a: 1}, result => result);

state.watch could work with multiple ad-hoc queries (gstate >= 0.1.3)

state.watch(() => {
    const a = state.get("a");
    const b = state.get("b");
    return {
        x: a, y: b
    }
}, result => result); // result => {x: "a",y:"b"}

In another aspect, gstate works like an normal javascript object

Set and watch nested object.

state.watch({
    a: {
       b: {
          c: 1
       }
    }
}, result => result);

state.set({a: "a"}); // result => {a: "a"}
state.set({a: {b: "b"}}); // result => {a: {b: "b"}}
state.set({a: {b: {c: "c"}}}); // result => {a: {b: {c: "c"}}}

state.set({a: {b: {d: "d"}}); // watch not called.
state.set({x: "x"}); //watch not called

state.watch is triggered based on query result not state’s value. So it’s able track changes from non-existed objects. Whenever new objects inputed or removed, watches triggered if their results changed.

Set and watch reference or circular reference

const parent = { name: “Giap” };
const child = { name: “Vinh”};
parent.child = child;
child.parent = parent;
store.set({ parent, child });

function update_parent_name(value) {
    store.set({ parent: { name: value } });
}

function update_child_name(value) {
    store.set({ child: { name: value }});
}

Delete object (NOT just reference)

state.delete("a.b.c");

It is hard to remove an object in JS because you must delete all it’s references. The state.delete should completely remove an object from state no matter it could be referenced (or circular referenced) in anywhere.

let val = {
  a: {
    item1: {
      name: "item1"
    },
    item2: {
      name: "item2"
    }
  }
};
val.b = val.a;
state.set(val);
state.delete("a.item1");
state.get({ a: { _: 1 }, b: { _: 1 } });
// result should be
{
  "a": [
    {
      "name": "item2"
    }
  ],
  "b": [
    {
      "name": "item2"
    }
  ]
}

Sub state/context

state.path(key_or_keys)

The API create a sub state, anyset/get/watch/delete would apply this tree only. Of cause, you could set/get/watch/deletesub state from parent state too.

Query syntax

{
   a: 1,  // if a is primitive return its value
   b: 1,  // if b is object return all it's primitive properties 
   c: {    
     d: 1 // nested object should explicit declare
   },
   e: {
     _: { // reserved for map operator: e.map(item => { f: item.f })
        f: 1
     }
   },
   g: {
      _: "$key" // return all keys: g => Object.keys(g)
   }
}

Gstate have an powerful onMapCallback which able customize map operation. For example, use awesome sift package to turn gstate query into mongodb-liked.

const sift = require("sift");
const state = new GState({  
   onMapCallback(op, nodes) {   
     if (op.query) {    return sift(op.query, nodes);   }  
   } 
});

state.set({  
   group: {   
       person1: {    name: "a1",    age: 20   },   
       person2: {    name: "a2",    age: 30   },   
       person3: {    name: "a3",    age: 45   }  
   } 
});

const res = state.get({  group: {   
   _: {    name: 1,    age: 1   },   
   query: { age: { $gt: 20 } }  }
});

expect(res).toEqual({  
   group: [{ age: 30, name: "a2" }, { age: 45, name: "a3" }] 
});

results matching ""

    No results matching ""