API

Create root state

const state = new GState({
    onMapCallback: Function
});

Create sub state

state.path(path, debug);

path is dot notation. It could be a string or array.

"a.b.c" => ["a","b","c"]

Set value into state

state.set(path, value);

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

state.set("a.b", "b");

Batch mutiple sets

state.set will trigger changes. Sometimes, you want perform many sets at once and trigger changes after completed.

state.batch(() => {
    //all state.set and state.delete inside the function will perform without trigger changes.
    //change will called once after the function completed.
});

//gstate will trigger once instead of 1000 times.
state.batch(() => {
    for(let i=0; i<1000;i++){
        state.set(["a",i],"a");
    }
});

Delete object (NOT just reference)

state.delete(path)

It is hard to delete JS objects because you must delete all it’s references. GState makes it easy with state.delete; the api should completely remove the object at the path no matter it could be referenced (or circular referenced) in anywhere.

const state = new GState();
let val = {
  a: {
    item1: {
      name: "item1"
    },
    item2: {
      name: "item2"
    }
  }
};
val.b = val.a;
state.set(val);
state.watch({
    a: {
      _: 1
    },
    b: {
      _: 1
    }
  },
  function(result) {
    console.log(JSON.stringify(result, null, 2))
  }
);
state.delete("a.item1"); // result should be {a: {item2: { name: "item2}}, b: {item2: { name: "item2}}}

Because object b is reference of object a, delete a.item1 is also delete b.item1.

Query data

state.get(query_or_path);

//Get single value
state.get("a.b");

//Query multiple value
state.get({
    a: {
        b: 1,
        c: 1
    }
});

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" }] 
});

Notice:

  1. onMapCallback perform against query's result not full objects. So the map operation should provides enough properties for onMapCallback process. Above sample not work if the map op not included age property. It is make sense because gstate need to know what property needed to reactive when property changes.
  2. Map operation is powerful but expensive. In large datasets, you should consider use $key for better performance.

Watch state changes (same as state.get but reactive)

state.watch(query, [options], result => result) => unWatch

state.watch is same with state.get. Whenever the query's result change, the callback will be triggered with new result.

state.watch return unWatch function which should called to remove the watch to prevent memory leak.

onWatchCallback

state.onWatchCallback(path, query => query)

Set a hook on the existed path. Whenever a state.watch try to query the path, the callback will be called once (for each state.watch). The hook is used for implicit data fetching pattern.

Save/Load state

state.save() => serialize_state
state.load(serialize_state)

Only apply for root state. Use for server side render.

results matching ""

    No results matching ""