Store
Store methods:
The store also has a property called reduxStore
which contains the Redux store used internally by SyncState. It might be useful for some advanced use cases.
useDoc
Gives you the state at path
and a function to mutate or replace that state
Arguments
path
(string?, default: ""): The path to state that you want to fetch
Returns
(Array
): An array with the following elements in order
State at
path
Setter for state with the following signature
setDocArguments
callbackOrNewValue
(Function | any): If you want to replace state atpath
, pass the newValue here or if you want to update some value inside the object or array atpath
, pass a callback function which receives the state atpath
to be updated.
Returns
(
void
)A dispatch function for you to dispatch any action to the internal Redux store.
Example
const [todos, setTodos] = store.useDoc("/todos");
setTodos([{ caption: "Hello", done: false }]); // replaces todos array
// OR
setTodos((todos) => todos.push({ caption: "Hello", done: false })); // pushes a new element to todos array
getPatches
Returns all the patches that have been applied to the document.
Arguments
*None*
Returns
(Array
): Array of {patch, inversePatch}
Example
const store = createDocStore({ counter: 0 });
const [doc, setDoc] = store.useDoc();
setDoc((doc) => doc.counter++);
console.log(store.getPatches());
// [
// {
// patch: {
// op: "replace",
// path: "/counter",
// value: 1
// },
// inversePatch: {
// op: "replace",
// path: "/counter",
// value: 0
// }
// },
// ]
getState
Returns the document (root state)
Arguments
*None*
Returns
(any
): document (root state)
Example
const store = createDocStore({ todos: [], filter: "all" });
console.log(store.getState());
// { todos: [], filter: 'all' }
getStateAtPath
Returns the state at path
Arguments
path
(string?, default: ""): The path to state that you want to fetch
Returns
(any
): State at path
Example
const store = createDocStore({ todos: [], filter: "all" });
console.log(store.getStateAtPath("/filter"));
// 'all'
observe
Observes changes at path
and calls the listener function with the new changes/JSON patches
Arguments
path
(string): The path to state that you want to observelistener
(Function): listener which receives state atpath
and patches generated to update the document.depth
(number?, default: 1): The patches which are generated internally have a path property associated. This argument defines till what depth belowpath
you should observe the changes.For example,
0 means that the listener will run only if state at
path
is being replaced.1 means that only the changes made to object/array at
path
will trigger the listener.Infinity means that the listener will run for any level of changes inside
path
For more explanation, refer this.
Returns
(dispose
): Dispose function, which you can call to stop observing
Example
store.observe(
"/todos",
(todos, change) => {
console.log("todos has been updated");
console.log("Updated todos: ", todos);
console.log("Patch generated: ", change.patch);
},
1 // depth to observe
);
intercept
Intercepts changes at path
and calls the listener function with the new changes/JSON patches where you can modify of stop the changes.
Arguments
path
(string): The path to state that you want to observelistener
(Function): listener which receives previous state atpath
and patches generated to update the document. You can return the updated change object ornull
to stop the update.depth
(number?, default: 1): Same as inobserve
Returns
(dispose
): Dispose function, which you can call to stop intercepting
Example
store.intercept(
"/todos",
(todos, change) => {
console.log("Current value of todos", todos) // before applying patch
// return modified patches for some case
if (change.patch.path === "/todos/0/caption"]) {
return {
...change,
patch: {
...change.patch,
value: {
...change.patch.value,
caption: "first task: " + change.patch.value.caption
}
},
};
} else if (
// Don't allow adding more than 10 items, return null will stop the change
change.patch.length === 2 &&
change.patch.op === "add" &&
change.patch.path.split("/")[2] > 9
) {
return null;
}
// no modification
return change;
},
2 // depth to intercept
);
dispatch
Same as Redux dispatch. This is used to dispatch actions to the internal Redux store.
subscribe
Same as Redux subscribe. This is used to subscribe to the internal Redux store.
useSyncState
Note: This method is for advanced use cases. You might not need it unless you are creating a plugin
In addition to doc
which is a JSON document representing your app state, SyncState's internal Redux store contains documents for plugins too. Plugins keep their state in these documents.
The root state of internal Redux store looks like this:
{
// Document containing app state
doc: {
state: {...},
patches: [...]
},
// Document containing plugin1 state
plugin1: {
state: {...},
patches: [...]
},
// Document containing plugin2 state
plugin2: {
state: {...},
patches: [...]
}
}
When you use useDoc
, the operation happens on doc.state
. To work with other documents, you can use useSyncState
.
Arguments
subtree
(string): The subtree that you want to fetch the state frompath
(string): The path to state that you want to fetch
Returns
(Array
): An array with the following elements in order
- State at path.
- A function to modify the state.
- Same as here
- A dispatch function for you to dispatch any action to the internal Redux store.
Example
const [todos, setTodos] = store.useDoc("/todos");
setTodos([{ caption: "Hello", done: false }]); // replaces todos array
// OR
setTodos((todos) => todos.push({ caption: "Hello", done: false })); // pushes a new element to todos array