Root store
mobx-depot
generates a RootStore
to manage instances of your data. Whenever a mutation or query is dispatched,
that data is deeply resolved by the RootStore
in order to instantiate any models that are returned.
For example, given the following response:
{ "data": { "user": { "__typename": "User", "id": 1, "name": "John Doe" } }}
RootStore
will realize that data.user
should be a UserModel
and will instantiate it. If the User
model
has any nested models, they will be instantiated as well.
Existing instances are preserved
If a model instance already exists in the RootStore
, it will be updated with the new data. This means that
if you have a UserModel
instance in your RootStore
and you dispatch a mutation or query that returns a UserModel
with the same ID, the existing record will be updated with the new data.
Of course, as a result of MobX's reactivity, any components or logic that is observing any affected records will automatically update.
Gotcha: New data can get duplicated
Consider the following scenario:
- A local
UserModel
is created within aRegisterForm
component - The user fills out the form and submits it
- The
RegisterForm
component dispatches a mutation that creates a newUserModel
on the server - The
RootStore
resolves a newUserModel
from the response and instantiates it
There will be two UserModel
instances: one that was created locally and one that was
created by the server, stored in the RootStore
. This is because the local instance is not stored in the RootStore
,
but more importantly, the IDs are not the same either.
But what if there's state within the local UserModel
that you want to preserve? The RootStore
provides a replace
method that allows you to replace an existing model instance with another one. Here's an example:
import { getRootStore } from './depot';const rootStore = getRootStore();class UserModel extends UserBaseModel { password = ""; save() { const createUser = new CreateUserMutation({ input: { email: this.email, password: this.password } }); createUser.dispatch().then((response) => { // Problem: response.data.createUser is a new instance of the `UserModel` that the `RootStore` resolved. // It is not the same instance as `this`. The solution is to copy the data from the server's instance, // and replace the one in the `RootStore` with this. // 1. Copy the data from the persisted instance to the local instance. // The `assign` method is provided by the `UserBaseModel`, which is generated by `mobx-depot`. // It is available in all models. Note: This will also copy the ID of the server's instance. this.assign(response.data.createUser); // 2. Replace the RootStore's instance with this local one. // `this.store` is a reference to the `RootStore`, which is provided by the `UserBaseModel`. rootStore.replace(response.data.createUser, this); }); }}
Any observers that were observing the server's instance will now be observing the local instance.