Skip to main content

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

  1. path (string?, default: ""): The path to state that you want to fetch

Returns

(Array): An array with the following elements in order

  1. State at path

  2. Setter for state with the following signature



    **setDoc**

    Arguments

    1. callbackOrNewValue (Function | any): If you want to replace state at path, pass the newValue here or if you want to update some value inside the object or array at path, pass a callback function which receives the state at path to be updated.

    Returns

    (void)

  3. 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

  1. 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

  1. path (string): The path to state that you want to observe

  2. listener (Function): listener which receives state at path and patches generated to update the document.

  3. depth (number?, default: 1): The patches which are generated internally have a path property associated. This argument defines till what depth below path 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

  1. path (string): The path to state that you want to observe
  2. listener (Function): listener which receives previous state at path and patches generated to update the document. You can return the updated change object or null to stop the update.
  3. depth (number?, default: 1): Same as in observe

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

  1. subtree (string): The subtree that you want to fetch the state from
  2. path (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.
  • 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
Last updated on by RohitGeekyAnts