mobx-keystone-asyncstore
An opinionated asynchronous store and container implementation for mobx-keystone.
⚠️WARNING: This library is under development and not yet considered stable. Use with caution as breaking changes to the API may be introduced until reaching v1.
Introduction
One of the most common challenges when implementing a store solution is how to handle asynchronous data sets. mobx-keystone-asyncstore aims to simplify this by allowing you to create powerful asynchronous stores with just a few lines of code. An mobx-keystone-asyncstore implements the most common fetch patterns and support fetch queues, fail states and time to live out of the box.
Let's look at a simple implementation of a TodoStore:
import axios from "axios";
import { when } from "mobx";
import { model, modelAction, Model, tProp, types } from "mobx-keystone";
import { AsyncStore } from "mobx-keystone-asyncstore";
@model("models/TodoItem")
class TodoItem extends Model({
id: tProp(types.string),
task: tProp(types.string),
done: tProp(types.boolean, false),
}) {
@modelAction
public toggleDone() {
this.done = !!this.done;
}
}
const storeName = "stores/TodoStore";
@model(storeName)
class TodoStore extends AsyncStore(
TodoItem,
{
name: storeName,
async fetchOne(id: string) {
const res = await axios.get(`/todos/${id}`);
return new TodoItem(res.data);
},
async fetchMany(ids: string[]) {
const res = await axios.get(`/todos`, { ids });
return res.data.response.map((d: any) => new TodoItem(d));
},
async fetchAll() {
const res = await axios.get(`/todos/all`);
return res.data.response.map((d: any) => new TodoItem(d));
},
},
{
isDirty: tProp(types.boolean, true),
}
) {
@modelAction
public setDirty(isDirty = true) {
this.isDirty = isDirty;
}
@modelAction
public addTodo(task: TodoItem) {
const container = this.createAsyncContainer(task.id);
container.setValue(task);
this.containers.set(task.id, container);
this.setDirty();
return container;
}
async saveToDb() {
if (this.isDirty) {
const res = await axios.post(`/todos`, this.values);
if (res.status === 200) {
this.setDirty(false);
}
}
}
}
const todoStore = new TodoStore({});
const container = todoStore.getOne("foo");
when(
() => container.isReady,
() => {
const todo = container.value;
todo.toggleDone();
}
);
todoStore.addTodo(
new TodoItem({
id: "bar",
task: "Do this thing as well",
})
);
todoStore.saveToDb();