DEV Community

How to: mobx-state-tree + react + typescript

Margarita Krutikova on April 06, 2019

This is a walkthrough on how to get a full setup with mobx-state-tree and react in a CRA app with typescript. This guide doesn't focus too much on ...
Collapse
 
havef profile image
HaveF

Hey Margarita, thanks for your post. Learned a lot.

Btw, I still don't understand what you said, useInject is better than useStore when using complicated store. Use useStore we still can get what we want.

const store = useStore()
const poll..... = store.pollDraft.......
Enter fullscreen mode Exit fullscreen mode
Collapse
 
margaretkrutikova profile image
Margarita Krutikova • Edited

Hey!
Great to hear it was helpful :)

When I implemented the useInject hook, I was thinking about having something similar to customizing inject with a mapper function, but with hooks. So if you have a more complicated app with lots of things in your store, or if you need to combine data from several stores, you might want to just extract all the data your component needs in a mapper function and then not care about how you get that data from the stores in your component.

For example,

const mapStore = ({ publishedPolls, participants }: RootStoreModel) => ({
 polls: publishedPolls.polls,
 totalNumberOfParticipants: participants.totalNumber
})

// in the component
const { polls, totalNumberOfParticipants } = useInject(mapStore)
...

Then you abstract away some details of your store implementation from your component's code. But I agree that it doesn't seem like a big problem to just use useStore, and since I am really used to redux and its mapStateToProps, I was trying to make it more comfortable for myself to develop with mst by using familiar concepts.

There is even a discussion about creating a similar useInject hook in this github issue.

However, when I tried the example above, I noticed an error in my implementation of useInject, which makes it confuse the return type from the mapper function because of this: (mapStore || defaultMapStore)(store), which is supposed to allow omitting mapStore parameter in the hook. On my way to fixing this, thanks a lot for making me notice the error! :)

Collapse
 
havef profile image
HaveF

Thanks for your detailed explanation!

useInject is a bit complicate to me, so I'm sticking to use useStore :-)

And another thing I found when I try your great example is enhanced the useStore with types:

export const useStore = () => useContext(StoreContext)

Enter fullscreen mode Exit fullscreen mode

to

export const useStore: () => TRootStoreModel = () => useContext(StoreContext) as TRootStoreModel

Enter fullscreen mode Exit fullscreen mode

Then it will be more convenience to use useStore with ts autocomplete feature!

Collapse
 
timnhe profile image
timnhe

Hey Margarita, thanks so much for this amazing article, I'm seeing that my knowledge on mst is a little rusty and this lecture helps me to be updated on it

Looking forward for more publications like this, for example, how do you organize remote side effects?

Collapse
 
margaretkrutikova profile image
Margarita Krutikova

Hey! Thank you for your feedback, glad that the article helped you :)

I haven't had time to look into side effects with mst yet, but it is definitely on my todo list ;)

Collapse
 
devozs profile image
Oz Shemesh

thank you for this great article.
The same approach can be used for react native as well?

Collapse
 
margaretkrutikova profile image
Margarita Krutikova

Thanks for the feedback!
I am not sure about react-native to be honest, haven't worked with it, but I think it should be the same, since it is till react :)

Collapse
 
rdewolff profile image
Rom

It is actually the same :)

Collapse
 
bfeeley profile image
Brian Feeley • Edited

Hi Margarita! Thanks for the post. Super helpful. Question .. how would you go about mocking the provider for tests and Storybook integration?