mobx-state-tree
mobx-state-tree copied to clipboard
Get snapshot of instance of custom type
Feature request
Is your feature request related to a problem? Please describe.
tl;dr: It seems not possible to get a snapshot of an instance of a custom type without using a model.
Suppose that in a todo app, each todo can have a date it's due by.
Since the user can change timezones, it'd be gross for the app to notify them of the due work too early/late, so the time isn't stored.
In the server, this would be suitable to save as a string in the format YYYY-MM-DD.
In the client though, since it's easier to deal with Date objects for comparing and rendering, it'd be natural to have a custom MST type that gets used by the Todo model:
const CustomDate = types.custom<string, Date>({
name: "CustomDate",
fromSnapshot: value => parseCustomDate(value),
toSnapshot: value => formatCustomDate(value),
// ...
})
Since the application is big, it's natural to keep a layer exclusive to data fetching, which holds no state.
For this, we can have the TodoFetcher model, which must fetch todos due by a given date. It queries the server in its original format YYYY-MM-DD.
types.model('TodoFetcher', { ... }).actions(() => ({
fetchTodos(date: Instance<CustomDate>) {
// ...
}
});
However, date is a standalone value. It doesn't belong to a model, so there's no good way to serialise it before sending the HTTP request.
The API of a custom type like CustomDate only offers ways to create instances and validate values, and no ways to run the logic in toSnapshot:
I take that I might not have researched enough, or that I'm just too new to MST to fully understand how things are done
Describe the solution you'd like
The addition of a method to custom types that can run its snapshotting logic when there's a standalone instance value.
Describe alternatives you've considered
- Making a model that holds the single
CustomDatevalue above so that I cangetSnapshot()it - Duplicate the logic in
CustomDate#toSnapshot()around the codebase - Using a more complicated model that stores both server and client representations with some custom snapshot processing logic
- Setting the date in the state of
TodoFetcher, then calling an argument-lessfetchTodos
Additional context
Disclaimer: I'm not building a todo app; this is a translation of the problem from my business logic to something every reader will understand. The same problems still apply.
Are you willing to (attempt) a PR?
- [x] Yes
- [ ] No
I think to and fromsnapshot are available on custom types. https://mobx-state-tree.js.org/API/#custom
I’m on my phone, so I may have missed the major thrust of your issue. I apologize if that’s the case.
On Sun, Jan 23, 2022 at 9:17 AM Gustavo Henke @.***> wrote:
Feature request
Is your feature request related to a problem? Please describe.
tl;dr: It seems not possible to get a snapshot of an instance of a custom type without using a model.
Suppose that in a todo app, each todo can have a date it's due by. Since the user can change timezones, it'd be gross for the app to notify them of the due work too early/late, so the time isn't stored. In the server, this would be suitable to save as a string in the format YYYY-MM-DD.
In the client though, since it's easier to deal with Date objects for comparing and rendering, it'd be natural to have a custom MST type that gets used by the Todo model:
const CustomDate = types.custom<string, Date>({ name: "CustomDate", fromSnapshot: value => parseCustomDate(value), toSnapshot: value => formatCustomDate(value), // ...})
Since the application is big, it's natural to keep a layer exclusive to data fetching, which holds no state. For this, we can have the TodoFetcher model, which must fetch todos due by a given date. It queries the server in its original format YYYY-MM-DD.
types.model('TodoFetcher', { ... }).actions(() => ({ fetchTodos(date: Instance<CustomDate>) { // ... }});
However, date is a standalone value. It doesn't belong to a model, so there's no good way to serialise it before sending the HTTP request. The API of a custom type like CustomDate only offers ways to create instances and validate values, and no ways to run the logic in toSnapshot:
[image: Screen Shot 2022-01-24 at 02 02 21] https://user-images.githubusercontent.com/826553/150684766-73fdf926-5bdf-4347-9f97-f1316ecb0409.png
I take that I might not have researched enough, or that I'm just too new to MST to fully understand how things are done
Describe the solution you'd like
The addition of a method to custom types that can run its snapshotting logic when there's a standalone instance value.
Describe alternatives you've considered
- Making a model that holds the single CustomDate value above so that I can getSnapshot() it
- Duplicate the logic in CustomDate#toSnapshot() around the codebase
- Using a more complicated model that stores both server and client representations with some custom snapshot processing logic
Additional context
Are you willing to (attempt) a PR?
- Yes
- No
— Reply to this email directly, view it on GitHub https://github.com/mobxjs/mobx-state-tree/issues/1862, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABCW4XKWQQ7ITLS3HDMYV3UXQLXRANCNFSM5MTOUGVQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
You are receiving this because you are subscribed to this thread.Message ID: @.***>
-- -Matt Ruby- @.***
hi @mattruby, that's just how the custom type must be implemented. Its returned value doesn't have that.
OK, I've re-read your question in more detail. Hmmm. So you'd like to add some kind of static function off the custom type to expose toSnapshot. I think I'd just make that a function that your custom type imports and share it out that way.
I don't think it's worth spinning up mini model instances just to use the date serialization logic.
On Mon, Jan 24, 2022 at 2:15 AM Gustavo Henke @.***> wrote:
hi @mattruby https://github.com/mattruby, that's just how the custom type must be implemented. Its returned value doesn't have that.
— Reply to this email directly, view it on GitHub https://github.com/mobxjs/mobx-state-tree/issues/1862#issuecomment-1019826906, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABCW4TFR4ECDM6KN3Q7XMTUXUDDJANCNFSM5MTOUGVQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.
You are receiving this because you were mentioned.Message ID: @.***>
-- -Matt Ruby- @.***
Hey @gustavohenke and @mattruby - thanks for the good discussion here. I'm in agreement with @mattruby on the path forward here.
I'm going to close this issue since it's been over a year without activity, and I think y'all found the answer. @gustavohenke - if you feel strongly about serializing these custom types, please consider opening up a discussion and we can talk it out a little more.