DEV Community

Arnel Enero
Arnel Enero

Posted on • Updated on

Can React state management get any simpler than this?

I'm one that loves simplicity in things. So despite the plethora of state management libraries for React, I have always wondered what the absolute "simplest" approach would be.

After some time on the drawing board, I think I've come up with just that. And today I'm happy to share with you SimpleR State. (yes, with capital "R", for React 😂)

Imagine being able to implement shared state in just 2 easy steps!

Step 1: Create an entity (shared state) and actions (updater functions)

// counter.js

import { entity } from 'simpler-state'

export const counter = entity(0)

export const reset = () => {
  counter.set(0)
}

export const increment = by => {
  counter.set(value => value + by)  
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Use the entity in your components with hooks

import { counter, increment, reset } from 'counter'

const CounterView = () => {
  const count = counter.use()

  return (
    <>
      <div>{count}</div>

      <button onClick={() => increment(1)}> + </button> 
      <button onClick={reset}> Reset </button>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

(Other components can use the shared counter the same way.)

It's that simple! But that's just a teaser, it can actually do a whole lot more!

Here are some of the design goals for this library:

  • Minimalist API; no complicated concepts or boilerplate
  • Use plain functions to implement state changes (including async)
  • Largely unopinionated with flexible syntax
  • Extremely simple to unit test state changes
  • Highly extensible with plug-ins (e.g. persistence, logging, dev tools)
  • Full TypeScript support with uncomplicated types
  • Made specifically for React, and built on React Hooks
  • Multiple times faster than context/reducer solution
  • Tiny, just around 1 KB (minified + gzipped)

If these benefits interest you, give SimpleR State a try. You can learn more about other things you can do with it at simpler-state.js.org. Yes, I wrote full documentation! 🤓

And if you like this library, and/or the simplicity/concept behind it please give it a star on the GitHub repo to let me know. 😀👌

So tell me, can the library get any simpler than this? I'd love to hear your suggestions. Goal is to get it closer to its bold claim of "simplest", not to compete with other libraries as the "best".

I opened a Request For Comments (here) on GitHub. Your comments and suggestions would be greatly appreciated. Feel free to drop me a comment here 👇 too.

Another P.S. -- I have prior art called react-entities which has already been out for quite some time, and used by our company in production. SimpleR State is an evolution, based on the same stable core, but with completely different (much simpler) API.

Top comments (76)

Collapse
 
ivan_jrmc profile image
Ivan Jeremic

Recoil is as simple and more powerful

Collapse
 
arnelenero profile image
Arnel Enero • Edited

I beg to disagree that Recoil is "as simple", but simplicity wasn't the main objective of Recoil in the first place. Having said that, Recoil is excellent at its intended applications. I wouldn't go around telling everyone to use Recoil for everything, though.

But I'd like to reiterate, in case someone did not care to read the article... this is NOT about being the "best" library. Open source is NOT a popularity contest—it's about offering something that might be useful to somebody out there, for their specific needs.

And a wise man told me that a smart developer does not rely solely on one philosophy/pattern/library, but knows which one to use depending on the task at hand.

Collapse
 
brianmcbride profile image
Brian McBride

Recoil is alpha, and (like typical facebook) ignores what is already out in the open source. So instead of building on something, they add more options that just duplicate efforts.

If you want what recoil does, Hookstate.js is basically the same thing.

I really like what Recoil is doing, but that is because I was using Hookstate before Recoil was a thing. Atomic updates. I think over the years I've gotten severe facebook fatigure as a developer. I would seriously prefer if they uplifted existing projects instead of hyping their own replicated efforts.

Collapse
 
ivan_jrmc profile image
Ivan Jeremic

True but you need to understand that facebook can't use some open source package for the intern products where they depend on

Thread Thread
 
brianmcbride profile image
Brian McBride

What is "some"?

I do not know Facebook internal policies, so I don't know. That sounds like a weak excuse though. I can understand if you use a lib that is small or unmaintained that it is better to use the inspiration there and create your own.

If it is a company policy, I still maintain the same position. It is a choice to fragment the community. Take Netflix, they are a good example of a company that improves existing libs through contributions while releasing their own projects to fill gaps. They have depreciated their own libs in preference to a newer/better open-source lib.

While I do appreciate everyone's contribution to open-source, if a project is active - make it better. Don't replicate the efforts and fragment the community. We just have too much of that in the JS community.

Collapse
 
httpjunkie profile image
Eric Bishard • Edited

I don't see it being an alternative to what's out there, but it's still a cool project. My suggestion is to ignore others and keep building it for your needs and cases. Focus on how it could do things better than the alternatives and worse case you just get some additional library experience under your belt? I love shall projects like this because as someone who is interested in building tools and libraries it's interesting to see other libs, modules, etc... In their initial project state. Thanks for sharing

Collapse
 
antonmelnyk profile image
Anton Melnyk • Edited

The state manager is not about being simplest, it's about being scalable and having good devtools. Nothing better than Redux in that sense.

Your state manager is good only for increment-decrement examples.

Collapse
 
olvnikon profile image
Vladimir

In most of the cases Redux is not needed anymore, unless the application is really huge. Not just a simple crm but a large application with huge amount of logic. Otherwise, it is simpler to use things like apollo (if you have GraphQL), react-query, Recoil or Jotai. Or just write custom hooks. Redux is too complex with a need to create action creators, actions, reducers, then connect them to store. If you need to affect different parts of the store it becomes too sophisticated.
The combination of Redux and redux-observable looks impossible for junior developers. It is powerful but so overcomplicated.

Collapse
 
markerikson profile image
Mark Erikson

FWIW, Redux is still used by about 50% of React apps, and is the most widely used state management tool for React apps by a large margin.

You should take time to consider what problems you're actually trying to solve, and choose tools that actually solve the problems you're dealing with.

Having said that, note that we definitely do not recommend Redux-Observable as a default approach, specifically because it does add a lot of extra complication and most Redux apps don't need it - that's why we recommend thunks as the default, and Redux Toolkit includes thunks out of the box.

Thread Thread
 
olvnikon profile image
Vladimir

You should take time to consider what problems you're actually trying to solve, and choose tools that actually solve the problems you're dealing with.

That's what I'm saying. Use the right tool. Before using Redux make sure you really need it.

My very rough estimates of React ecosystem state management market share are

So these are just some random statistics from some random guy on the internet. Not saying he is not right though.

Most devs still think that Redux is the only state management library and pick it just because they think so and don't want to learn new technologies. I talked to my colleagues and they simply don't want to consider using other libraries because they believe "Redux is Redux and other libraries are meh". They even didn't try those libraries. Some React devs still use class components over functional with hooks because:

  • projects are legacy and nobody is going to refactor them
  • devs keep classes on purpose because they prefer them

Coming back to my original idea. Use the right tool and be up-to-date with modern technologies.

Thread Thread
 
markerikson profile image
Mark Erikson

FWIW, I'm the primary Redux maintainer. So, sure, feel free to take my comments with a grain of salt, but A) I happen to be an expert on this topic, B) I spend most of my time answering questions about when it makes sense to use Redux, and C) I'm definitely not just "a random guy on the internet" :)

I've established a pretty solid track record of being straightforward and unbiased in my evaluations and responses:

twitter.com/tannerlinsley/status/1...

Mark is a breath of fresh air, right?! He'll forever be at the top of my list for people that I trust to always deliver an objective take on something, regardless of stake or emotion.

Thread Thread
 
olvnikon profile image
Vladimir

Look, I didn't want to offend you and I partially share your opinion. I'm just saying that often Redux is popular because devs don't want to consider any changes in their existing apps and don't want to try new tools in their new projects.

Recently, I have been working on a project that uses Redux but it is just about keeping fetched data. Yes, it is a lot of data but Redux is not needed for that.

Even when it is needed to store some state maybe a custom hook is enough. Tools like Recoil and Jotai (or Xstate if your choice is state machines) can keep the state and even transform it (hello Reselect).

Coming back to my point:

Use the right tool. Before using Redux make sure you really need it.

Thread Thread
 
darlingtonokoriec profile image
Darlington Okorie

I think you're very right. As soon as one becomes a react developer, the very next expectation everyone seems to have of you is that you must understand and use redux. Obviously, redux isn't the only state management tool out there. There are easier and less complex tools out there. Once you get in that for most of your projects you get to use any of the options, like Recoil, useContext and so many others, its like a brush of possibilities.

Thread Thread
 
oliverradini profile image
OliverRadini

To provide some additional context (no pun intended) to Vladamir's comments...

I'm sure some developers are still using Redux because they "don't want to consider any changes in their existing apps and don't want to try new tools in their new projects." Familiarity is an advantage but ought to be weighed against the benefits which alternatives would bring. Sensible developers won't only use Redux because it's familiar, but novelty should not be the only reason to switch.

I'm still someone who uses Redux because I've not yet tried a state management library which provides enough benefit to justify the switch. If I want to tell the people that I work with that we're making the switch away from Redux, I'll be talking to smart people, and they'll rightly want to know why it is that we're making this switch. Right now I don't feel like I could provide an adequately watertight answer.

For all the same reasons, if someone already knows a library like Recoil, they are right to consider why they would switch to Redux, when they know a perfectly good solution to the same problem.

Thread Thread
 
sefrem profile image
sefrem

Every time i work with Mobx i'm so happy about how easy and intuitive it is. Worked with Redux and Effector, but Mobx nails it for me.

Collapse
 
ivan_jrmc profile image
Ivan Jeremic • Edited

You clearly are in the Redux fancamp and it is the only thing you know... Redux is not even needed anymore

Collapse
 
smitterhane profile image
Smitter

Redux is not needed any but it still has some tiny advantages such as performance optimization, for instance when compared to the context API in large applications

Thread Thread
 
ivan_jrmc profile image
Ivan Jeremic

I would also never use Context alone for big apps but instead Recoil over Redux

Collapse
 
stojakovic99 profile image
Nikola Stojaković

I'm not in a Redux fancamp but Anton is right - ecosystem matters. That's the reason why some technologies are still used so much despite their flaws (I'm not saying this for Redux though).

Collapse
 
oliverradini profile image
OliverRadini

Just to provide a contrast to some of the other comments on this comment, Redux is not complex in the slightest but it often requires a certain amount of boilerplate. It's a great option, but there are also a range of other equally good options.

Collapse
 
shayneoneill profile image
shayneoneill

"The state manager is not about being simplest, it's about being scalable and having good devtools"

I long ago realised the quest for scaleability is death to so many start ups.

You have to move fast and break things, and for god sake ship. I've seen so many good startups die to giant complexity balls bourne out of "Well what happpens when we have 20 million customers". Cool eggs, but focus on getting A customer first, because for every month your bizarely overcomplicated serverless nosql redux firebase hellmachine remains in development hell, the less enthusiastic investors become about funneling more junk money into your scheme, and then blam out of the blue someone with a simpler but functional product hits the market and eats your market becore your even laiunched. Game over.

Simplicity , is everything

Collapse
 
arnelenero profile image
Arnel Enero • Edited

I completely agree. In the highly competitive industry today, ship fast is the goal. I would bet, if we look at the source code of the early versions of those highly successful apps out there, the perfectionists among us would have a lot of negative things to say about them. But at the end of the day, those apps have beaten the hell out of over-engineered apps that just took too long to launch.

I like your point about "before even worrying about being able to serve millions of customers, focus on getting that first customer first" 😀. Although to be fair to the original comment, "scalable" in this context is probably referring to scaling with the growing feature set of the web app. But your idea still translates well to this context—"before worrying about delivering lots of features, focus on shipping out a minimum viable product first with one killer feature".

Collapse
 
arnelenero profile image
Arnel Enero • Edited

Saying that something is the best for everything would yield nothing but an unproductive debate. There is no such thing as one-size-fits-all in libraries, otherwise everybody would just use Redux for everything. Even the author of Redux himself does not recommend that.

Someone out there could be searching for the "simplest" instead of the "best", and there's nothing wrong with that.

Trashing other libraries in favor of your own favorite is not exactly helping anyone. I hope you actually looked at the library first before concluding that it is only "good for increment-decrement examples", but thanks for your feedback in any case.

Collapse
 
robvirtuoso profile image
robvirtuoso

What's all this commotion lol. Even the Redux guy is here.

Collapse
 
antonmelnyk profile image
Anton Melnyk

Day is not a day without state management drama!

Thread Thread
 
robvirtuoso profile image
robvirtuoso

Nah, a good developer can write great code even with the most rudimentary library. There's no need to have "camps" in this petty topic. Relying too much on "tools" is just being weak. lol.

Collapse
 
bennodev19 profile image
BennoDev • Edited

Yes, sure, stability/scalability trumps simplicity,
but whats about a simple AND scalable state management approach?
SimpleR State is a singleton state management approach,
and it's (in my opinion) pretty simple, scalable, and maintainable.
I have created a State Manager (AgileTs) with a similar concept,
and as far as I can tell, it is extremely scalable if used correctly.

I've created a Style Guide for large applications using such a singleton State Management approach:
agile-ts.org/docs/style-guide#-ins...

Collapse
 
smitterhane profile image
Smitter

I found this, savage

Collapse
 
cadams profile image
Chad Adams

Zustand?

Collapse
 
pshaddel profile image
Poorshad Shaddel

An awesome library that supports async actions :)

Collapse
 
ncpa0cpl profile image
ncpa0cpl • Edited

It is very unclear that "increment" and "decrement" function are in any way related to the "count" state, I'd imagine maintaining code written with this library would not be a pleasant experience, especially if it was a code written by someone else.

A much better approach would be to have the "useEntity(counter)" return an object with "count", "increment" and "decrement" as its properties. This would make it much clearer, and if you want to have simple looking state variable and methods names you can just use ES6 destructuring syntax and you'd have it like this:

const { count, increment, decrement } = useEntity(counter);

Collapse
 
arnelenero profile image
Arnel Enero • Edited

Thanks for your reply. I do have a prior (well, it's still actively maintained) library called react-entities which does package the actions inside the entities.

Based on many user feedback, I decided that for this new library I would try decoupling the actions from the entity for reasons such as:

  • it makes it easier to implement orchestrator actions that can update multiple entities in one go (as discussed in the documentation)
  • it makes the "use" hook syntax simpler (returns a single value, not a tuple or destructuring)... more like useContext than useState.
  • the actions are pretty much static, so we are avoiding needlessly having to include them in the deps array of useCallback when invoking actions there.
  • many popular state managers like React Redux also separate actions/dispatch from the state hook
  • ultimately, I was aiming for "simplest" and based on feedback from users of react-entities standalone actions would be simpler (and more flexible).
Collapse
 
skyjur profile image
Ski

the actions are pretty much static, so we are avoiding needlessly having to include them in the deps array of useCallback when invoking actions there.

What you did in your example with "static" actions is global state singleton. It's a very bad example to teach. Many books talked about this. I suggest to revisit SOLID principles and try to apply them. All OOP concepts are very much applicable everywhere where there is state. And in UI there is a lot of state that needs to be managed.

Passing down dependencies is nothing wrong. It's the right way. When it's too much and interduces dependencies that we don't want to have - it can be avoided in React with useContext().

Thread Thread
 
arnelenero profile image
Arnel Enero • Edited

Just to be clear, this article is not intended to "teach" or even recommend certain "principles". It is merely to showcase—in the most succinct way possible—a library that some folks may choose to explore. And being designed exclusively to work with Hooks, it is obviously for those that prefer functional programming. There is never the intention to claim that it is the "best" approach, nor to compare with libraries, as the article has made clear.

As for the library itself, just like the over-simplified examples (not recommended patterns) used to demonstrate... it is not meant to challenge anybody's approach to development. It is unopinionated, and merely provides flexible building blocks that individuals can use while applying whatever programming principles they choose to adhere to.

Collapse
 
joserocha3 profile image
Pablo Rocha • Edited

I like easy-peasy. Truly is the easiest react state management I've encountered. Uses redux under the hood so existing dev-tools work great.

github.com/ctrlplusb/easy-peasy

Collapse
 
robvirtuoso profile image
robvirtuoso

Comments Section Summary:

Article: Introducing XXXXX. Can you suggest how to make it even easier?
Guy A: I like YYYY. Easiest I've encountered.
Guy B: Try ZZZZ it is even easier.
Guy C: The WWWW is amazing.
Guy D: Have you tried VVVVV?
Guy E: I also created a library UUUUU check it out...

You're a funny bunch!

Collapse
 
ivan_jrmc profile image
Ivan Jeremic

Try Recoil it is even easier

Collapse
 
lexiebkm profile image
Alexander B.K.

What about reactn : github.com/CharlesStover/reactn ?
There is an article which was written by the author in this site, from which I was interested in using it : dev.to/charlesstover/manage-global...
Well, I have been using it for managing global state in my last project. It worked as expected. For local state, I simply used React traditional way, i.e setState.

Collapse
 
jasman7799 profile image
Jarod Smith

Awesome academic exploration for yourself, but I think Kent is correct in this blog post, Application State Management with React. All you need is react.

Collapse
 
arnelenero profile image
Arnel Enero • Edited

Thanks for your comment. After reading through that article, one would realize that as soon as the number of shared-state objects increases, assuming you're not using one monolithic global state, you'd go down the path of dealing with boilerplate. 😀

Collapse
 
skyjur profile image
Ski • Edited

State management is just writing code. Knowing multiple patterns their pros and cons and applying them to simplify application's complexity is the important part here. No library can ever solve this problem because it's education problem. The reason why redux achieved a lot is not because it actually solves anything. It's a tiny library that doesn't do much. It became wide spread not because it solves anything but because their documentation is quite an amazing guide on how to structure application that is easy for many to absorb and apply.

Collapse
 
thomasburleson profile image
Thomas Burleson

The Zustand API [from the React Spring guys] is amazing and clean:

1) Use create(<callback to build>) to build a store, initialize state, and get a hook associated with that store
2) Use the hook (eg useStore(<query selector>)) to query/select data from the store.

Whenever that data slice changes, the hook re-emits and the component can re-render with up-to-date state.

@see github.com/pmndrs/zustand

Collapse
 
ceoshikhar profile image
Shikhar

I created something similar too very recently. I called it simate. A very (sim)ple st(ate) management tool. Have a look at it if you want :)
github.com/ceoshikhar/simate

Collapse
 
rommyarb profile image
L. Rommy Arbantas

Have you tried Valtio?
github.com/pmndrs/valtio

Some comments may only be visible to logged-in visitors. Sign in to view all comments.