Right now when I need to reset a model (for example when I navigate with the app router to a certain page), I have a reset action like this:
reset() {
self.name = ''
self.owner = ''
self.location = ''
self.employees = 0
self.isOpen = false
self.list = []
},
These values are the same I pass as a second argument to the t.optional in the model, like this:
const SampleModel = t
.model('SampleModel', {
name: t.optional(t.string, ''),
owner: t.optional(t.string, ''),
location: t.optional(t.string, ''),
employees: t.optional(t.number, 0),
isOpen: t.optional(t.boolean, false),
list: t.optional(t.array(t.string), []),
})
and this is how I initialize that state:
const State = t
.model('State', {
sampleModel: t.optional(SampleModel, {}),
otherSubState: t.optional(OtherSubState, {}),
})
Is there a standard and easier way to reset a model to its initial state?
Maybe you can save it on afterCreate. Something like this:
const State = t
.model('State', {
sampleModel: t.optional(SampleModel, {}),
otherSubState: t.optional(OtherSubState, {}),
})
.actions(self => {
let initialState = {};
return {
afterCreate: () => {
initialState = getSnapshot(self);
},
reset: () => {
applySnapshot(self, initialState);
},
}
})
I used the method mentioned above getting and saving snapshot on the initial state. It works great most of them time! However, when the model is big, entire UI locks waiting for, I'm guessing, garbage collection to finish?
Do you have any other recommendation for reinitializing? Thank you!
Here is what I ended up doing:
const State = t
.model('State', {
sampleModel: t.optional(SampleModel, {}),
otherSubState: t.optional(OtherSubState, {}),
})
.actions(self => ({
resetSubState(subState) {
const subStateName = subState.$treenode.subpath
self[subStateName] = {}
},
}))
And this is what become of the reset method
reset() {
const { resetSubState } = getRoot(self)
resetSubState(self)
},
A bit hacky, but this is what I needed to do.
And making a snapshot afterCreate() does not work in react-native if you restart the app. As a new afterCreate() will be triggered uppon app restore with the wrong snapshot.
UPDATE: here is a better way to do it
const State = t
.model('State', {
sampleModel: t.optional(SampleModel, {}),
otherSubState: t.optional(OtherSubState, {}),
})
.actions(self => ({
reset() {
Object.keys(self).forEach(key => {
self[key].reset && self[key].reset()
})
},
}))
reset method:
reset() {
applySnapshot(self, {})
},
No need to save the snapshot an afterCreate, assuming you always use the default values.
Yes that's a nice example, thanks @marcofugaro. And you could even compose this reset method with your stores ;)
@marcofugaro so to reset model I just need to call applySnapshot(self, {})?
why do you iterate over submodels and call reseton them?
that works too @danikkks!
In my case I had some states that couldn't be reset (like mst-react-router). So I was checking if they had the reset method.
ok, I got it, thanks!
Most helpful comment
Maybe you can save it on
afterCreate. Something like this: