DEV Community

Cover image for My thoughts on endless battle of React state management libraries (setState/useState vs Redux vs Mobx)

My thoughts on endless battle of React state management libraries (setState/useState vs Redux vs Mobx)

mpodlasin on September 01, 2020

This, in contrast to my previous pieces, will be a more opinion based article. So, dear reader, treat everything here with a grain of salt - it's j...
Collapse
 
rehubbard profile image
Eric Hubbard • Edited

"there is no easy way in React to share state instances between components"

React Context lets you easily share state in all components, doesn't it? This is a common solution to state management that uses built-in React features.

Collapse
 
adamashored profile image
adam-ashored

No - it does not let you easily share state in all components. It let's you easily share state in all components that are descendents of the context provider.

Personally, I love context. It allows me to think of controllers as components. I don't have to deal with the boilerplate of redux and I don't have to deal with the magic of mobx.

But, if I'm on a team of developers that have various levels of experience in react, I would almost always go for redux as long as an experienced senior is driving the redux bus. If everybody on the team is experienced seniors in react, then context is a-ok by me.

Collapse
 
rehubbard profile image
Eric Hubbard • Edited

Having to be a descendant of a context provider isn't a huge limitation or drawback for context. But I'm sure there are some scenarios I could be missing where that's an issue.

Thread Thread
 
adamashored profile image
adam-ashored

I didn't say, nor imply, it was a drawback. It's not. It's actually a huge feature. React is still, even after several years of composable UI, a "new way of doing things" to a lot of devs and it's hard (or impossible) to grok it all at the outset. To say something like "context lets you share state across all components" is a confusing statement to the ones who haven't made their own mental models yet when they try it and it fails, or they nest context providers without realizing it and end up in a really uncomfortable state because they can't connect "context = global shared state" with what they're seeing with they're own eyes.

Thread Thread
 
rehubbard profile image
Eric Hubbard

Ah I gotcha. I read your original comment wrong. Thanks for clearing that up for other readers 👍

Collapse
 
krenwick profile image
Katrina

I made an account just to comment on this.
The whole time reading this article I was thinking "WHAT ABOUT USECONTEXT????"
This is the third article I've read today that discussed the struggle of shared state in react, and didn't mention the useContext hook. Is there something I'm missing?

Collapse
 
kevin074 profile image
kevin074

I read the whole article, it made a lot of sense to me as we did face the same issues with redux and simiarly mobx. Good job!

For our app, which was made via knockoutJS, have very similar concept to mobx, namely the pub-sub pattern and the computed functions. Just like you said, a lot of complexity comes from asynchronous functions coupled with mobx. So I am wondering what do you think if we structure the app in the way that we will have components handle the service calling, not mobx. This way we take out the step that causes complexity ?

Collapse
 
jbergens profile image
jbergens

I think you may end up with some problem later unless the app is very small. If you put the fetch logic in the component it is hard to share if needed by another component (that is, another component must be able to fetch this data and update the store). If you then move it outside of the component into a helper you are very close to a thunk or action any way but it is outside the components and the store and therefore a bit harder to find. One nice thing with mobx is that almost everything about state and actions can be found in the store.
It could also make writing tests harder. When everything is in a mobx store you can write tests for it. If you split it into a store, some helper and a component you have to test them all combined to know that the application works.

Collapse
 
kevin074 profile image
kevin074

I agree with your observations, namely that if everything's inside the store then you'd have a centralized place for everything. However, I think that's exactly the drawback of the. We had a relatively small app that used redux and had all types of data, global state and service responses, stored in there.

It quickly became a nightmare when there are scaffolding after scaffolding for getting stuffs, which was hard to explain to our team lead who had no hand in building it. It felt as if walking in a labyrinth inside the store. If everything was separated completely, store only has global state, service layer is the controller, cache layer is another, then it would be much clearer.

as for writing tests, you may very well be correct, but I am too newbie at test-writing to comment on :P

Collapse
 
mpodlasin profile image
mpodlasin

Hey Kevin, thanks for the reply.

I like your point about async stuff bringing a lot of trouble to Mobx.

Moving async stuff to components definitely might work nicely. My only fear would be only that it would again turn into "Redux-esque" architecture, where whenever somebody new comes to the project, you have to explain to them "oh, we don't put async stuff in Mobx stores, we put it in components, blablabla...".

But maybe that's not a huge issue and if everyone in the team is on the same page, I think it would be completely fine to try that approach.

Collapse
 
kevin074 profile image
kevin074

awesome thanks!

Collapse
 
psiho profile image
Mirko Vukušić

I dont do huge apps, but Mobx worked really well and I haven't run into any of the mentioned issues. I split state into multiple Mobx stores, organized hierarchically. So only RootStore usually gets pushed through provider and other stores are accessible through it. Also parent store is referenced by child store so you can go up the hierarchy too. Basically, its what Mobx docs suggest: mobx.js.org/best/store.html

I must say I also haven't had any unexpected behavior. Quite oposite. "Scratching my head" with React usually was about why some component was rerendering more than once, or even twice. I'm really careful about optimization there. Hate to see rendering time wasted. I find that goes away with Mobx. React state, Memo, and other ways to fight it are in my opinion much more complex thatn Mobx. In Mobx, all you have to remember basically is "dereference values as late as possible" (one point from Mobx docs: mobx.js.org/best/pitfalls.html)

Collapse
 
mpodlasin profile image
mpodlasin

Hey Mirko. Thanks for commenting.

Maybe that wasn't entirely clear in the article, but I DO consider Mobx superior to Redux in most of use cases.

I didn't have "scratch my head" moments too often when developing an app, but I still felt that I am not fully in control of the framework.

This article wasn't meant to bash Mobx (or even Redux). If it works well for you, by all means continue to use it.

Collapse
 
psiho profile image
Mirko Vukušić

No, no, I haven't foind your article to bash Mobx. Just focussed on Mobx part of it, trying to find myself there, but didnt :). And wanted to share.

Mobx is a "magic black box" often, but I got so used to it that it doesn't serve me any surprises.

Thread Thread
 
mpodlasin profile image
mpodlasin

Fair enough!

Glad it works for you. Thanks for the comment. :)

Collapse
 
mkinoshita12 profile image
Makoto Kinoshita

What do you think about Recoil? Recoil enabled me to manage states in a similar way to React. It requires much less boilerplate code than Redux, and it also integrates well with React.Suspense for asynchronous code.

I haven't really used MobX before so I can't speak about it though.

Collapse
 
mpodlasin profile image
mpodlasin

Hey Makoto.

Never used Recoil, in fact never seen anyone using it.

But you got my interest, I will definitely check it out. Thanks!

Collapse
 
dmalechek profile image
dmalechek

I'm a newbie but have been using Recoil on a multi-screen app. Works great for me so far and fairly easy. Maybe too easy.

Collapse
 
sammysaglam profile image
Sammy Saglam • Edited

I really like the idea of a useSharedState concept, and I recently attempted that and created a very small library for it in: github.com/sammysaglam/react-statey

I don't any reason why something like this wouldn't be great & simple! And to address asynchronous behavior, I call setState in a useEffect, which I think is also quite easy to handle & read.

Collapse
 
juliang profile image
Julian Garamendy

Thank you for writing this. I finally understand the core differences between Redux and MobX.

Regarding

I am imagining having a useSharedState hook, which would work just like a regular React state hook, but would allow components to access the same state instance, for example by sharing a predefined key

...have you seen ReactQuery or Vercel's SWR?

They're two very similar libraries. I think you'll like them.

I mention them in some of my posts.

Thanks again!

Collapse
 
chrislovescode profile image
Chris

Dude, try "react easy state" it's the way to joy and peace.

Collapse
 
mpodlasin profile image
mpodlasin

Will check it out, thanks!

Collapse
 
chrislovescode profile image
Chris

In additional to the docs here github.com/RisingStack/react-easy-...
this is an interesting read to blog.risingstack.com/reinventing-h...