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.
I wrote this library with the hope that this might be it. Any ideas/suggestions how to further simplify it would be super!
It’s not clear how to define a new entity out of another one using a selector. So perhaps instead of/in addition to `x.use(foo)` you might want `x.select(foo).use()`.
Not sure if simpler but something I’d be missing/would feel inconsistent.
Hi. SimpleR State makes use of selectors without creating a new entity (unlike atoms in Recoil, for example). It uses the more classic paradigm used by popular libs like React Redux where you just use selectors to filter/transform the "received" state to the format required by the component, and not to "create" a derived state per se. I hope it makes sense.
If you want a simple and elegant state management module then check out Zustand. I have been using this for a year or a bit more and am absolutely happy with it.
With this one, you can write granular shared states (multiple "entities") without creating layers and layers of Context Providers in your component tree.
Since data is not encapsulated inside React component tree, I found it to be multiple times faster than when using Context.
And one thing that's perhaps the most obvious... it's simpler because you don't have to use Providers at all.
Maybe "encapsulated" is not the right term when I simply meant "scoped".
I tried scoping the entities using Context in some prior art which we use in production. Some colleagues kindly gave me some benchmark results and the version without Context (external/module-scope) was faster.
I'm not trying to debate against Context here. In fact, there's nothing that would stop anyone from using SimpleR State's entities with Context API.
Not that I'm a fan of Context (or even React); but without publishing the benchmark code or specific technical arguments, it's hard to support a claim about slowness or of speed.
Yup agreed. That's why I stated it as "I found it to be...", coz I'm not trying to convince everyone else LOL.
It's never my intention for this library to try and be the "best" out there. I simply want to create what I sought for, which is the closest to the simplest approach I can think of. And to share it to the public, in case someone out there is looking for the same thing I am, and maybe it could help that someone. That's what open source is for, after all.
Oh cool! Do you have some benchmark results for that? Would be awesome to post them in the README if you can.
> simpler because you don't have to use Providers at all
I think the Provider pattern is part of the functional programming pattern with React, so while I do agree it might be harder to get used to but it underlines the no side-effects affecting the state of a given React components and its children.
At scale proper action, reducer pattern is helpful to manage a complicated state tree to still make it functional, easily testable and giving the same end result as a function of state.
So this makes things very similar to how Vue does things. Vue 3 with its encapsulated reactive library also works this way. But immediately I wonder how it works with React innards, do I have to optimize rendering? Does it do wasteful re-renders? How does it affect diffing?
While I finally bit the bullet and learned redux a couple years ago, I tried for a long time to avoid it. It’s overly complex for the tasks it is often trying to solve.
I like this solution because it’s simple, testable, and global.
> It’s overly complex for the tasks it is often trying to solve.
That's a bit like saying a excavator is a bit too complex to hammer nails. Yes, that's true, but that was not why we created the excavator in the first place.
Same with Redux. Initially created to get rid of big, hairy and complex balls of state. If you use it in your basic CRUD, you're probably using the wrong tool rather than the tool is wrong itself.
Each tool has it's place in our toolboxes. It's our job to decide when to use what tool.
How do you define "simple"? Simple is a very complex topic :)
For example, in React the common way of using hooks is `useMyhook()` where "Myhook" is whatever you name it, like "useState", "useEffect", etc.
So I'd argue that an API that follows the conventions in a platform is simpler than one that rewrites them. In this specific situation in the first demo, I would expect to have a hook called `useCounter()` instead of `counter.use()`.
Furthermore, since we are manipulating state again the convention in React for state manipulation is to return the value and then the setter, like:
const [counter, setCounter] = useCounter();
Now I understand since it's a global state we cannot give it a local initial value to avoid race conditions, so that's IMHO about as simple as you can get.
I didn't do that, but I believe I got pretty close with my own React state management library https://statux.dev/:
but the `counter.use()` was chosen in the documentation due to more feedback that requested this "simpler" format (i.e. no need to import `useEntity()`. But again, to your point I will restore the mention of `useEntity` in the documentation.
2. As for the [state, setState] convention, think of useEntity more like useContext than useState. Then it gets simpler.
3. I would also argue that since this is "shared" state, the developer might (again, the library is not opinionated on this) choose to separate the logic of updating shared state. For this reason, I didn't see any reason to provide a setter through the hook, when you can access the setter from anywhere via something like counter.set(). Conforming to useState convention was not justified in this case, especially since useContext convention equally makes sense for shared state.
4. To suit whatever convention, you can always do something like this alongside the definition of the entity:
export const useCounter = counter.use
I want to point out that SimpleR State provides the flexible constructs to allow the developer to tailor it to their preferred convention.
Hey, I like your version too. I’m digging these simple state libraries. Really proves just how absurd Redux was when you finally see the simple solution.
I believe Redux is good when you have 3+ people working on the same project front-end, and absolutely necessary when you have 10+. This makes it work great with the Facebook, Airbnb, etc. of the world.
Which is totally fine, but not your everyday problem for the rest of us! I'm very happy to see all of these versions pop up as well.
It formalizes how data is created, accessed and modified. Instead of multiple places trying to modify some specific data ad-hoc and with possible collisions/changes, now you have a mores strict way of dealing with data.
I see what you're saying here, and actually agree at some level.
But there is always an alternative, IMHO. If the project has a good code structure and follow equally good coding standards and review process, using simple un-opinionated/flexible libraries would not be a liability with "scale" (in terms of team/project size).
And there's one advantage of simpler approaches for growing teams: faster/easier onboarding. Let's face it, even good React/Redux developers can understand simpler code faster.
Just an alternative thought. But I completely get your point.
Ok, so what are the actions/reducers nonsense about?
I’m just not seeing the argument here, and I’ve been on multiple redux applications on teams of various sizes. We always seem to create layers of indirection to do the simplest possible state update.
We adopted Dan Abramov’s mental model, and my god, it was a labyrinth.
Ultimately, it's about putting a deliberate separation between "what happened" in the UI and "how the state is updated", writing as much of your state update logic as pure functions, and being able to use that indirection to enable tracing state updates over time via the DevTools.
Also note that our official Redux Toolkit package is now the standard recommended way to write Redux logic, and it simplifies most of the Redux code you'll write:
I think you guys should take a more honest retrospective on an age old topic of ‘Intent versus Impact”.
The truth of the story was that community was desperately looking for a solution to global state to avoid prop drilling. No amount of technical virtuosity, or cop outs to a half assed flux architecture that fundamentally mimics model-view-controller or a pub/sub pattern will be satisfiable to anyone with critical thinking ability.
The kids had one job, get some global state available to the app, and they managed in their bravado to pack in ‘addons’, or in sales terms, they ‘up-sold’, that $40 hdmi cable along with your new $1600 television.
Dan packaged his extra bullshit (the reducer pattern) over to a desperate group that had nowhere else to turn for a global state solution. Celebrity and hero worship was one of the premier sins in all of this. The guy didn’t know what the fuck he was doing and no one called him out on it.
Certainly we are not going to marvel at the fact that he is a React core developer. Bad ideas are bad ideas, regardless of the current class that ordains it.
For this, I am depressed, and will continuously antagonize the Redux team for the damage they caused the entire community.
The Redux team owes a debt. Rewrite your library so that the api is 5 lines at max. Replace your conceptions, seek forgiveness for the sin, and let it rest. Until then, don’t peddle your Frankestein ever again anywhere, you all had plenty of time in the limelight and quite frankly - you weren’t good enough.
Like what is the redux-toolkit? Do you guys lack the conviction to decide what the api is or isn’t?
With all that said, if you don’t understand what I’m saying, then mapDispatchToProps or mapsTateToFuckYou, connect everything to nonsense, and I suppose in your new bullshit, createSlice to shut up already. You guys can’t write an api if your life depends on it. And I swear to god, if I hear about the stupid Ducks pattern ... I just can’t anymore.
Anyways, I’d prefer never to punch down if I can avoid it. The redux/abramov/constituents of the react community became the Zeitgeist of the Javacript community. Paragons. And no one stood up to them and behind the bullshit is a clusterfuck of shitty apps. You guys ain’t a small agenda, and I expect the fight to continue.
I'm genuinely sorry that you're angry enough to rant like this. You might want to look into some therapy or something - that kind of anger can't be healthy.
In the meantime, we're going to keep working to support our users. Who, based on the vast amount of feedback we've gotten over the last couple years, _are_ happy with the directions we're going.
Simple state libraries are great for simple web apps, not for massive, enterprise-level applications. As someone who regularly investigates alternatives to redux, it still sits at the top of state management.
These intro how-to comparisons don’t do redux justice because being simple to use is not the stated goal of redux. Large scale, maintainable, and traceable code is the primary goal of redux. When you allow anything to update your state with zero form of traceability, you’ll start to see the cracks in these simple designs.
Are these new state management libraries easy to use? Sure, but what happens when you have tens of thousands (even hundreds of thousands) of lines of code to deal with and then add major refactoring objectives in the pipeline?
Like others have mentioned, if you are using redux for a simple to-do app, then its design principles are probably not as valuable.
It’s like thinking about time complexity for algorithms, at a small enough N, even slow algorithms can compete, but as you increase N, some algorithms become untenable.
You are not the only one debugging large apps. How does the wider world of programming debug stuff without actions and reducers?
It’s crazy how the Redux people either always appeal to authority (‘my app is bigger than yours’) or can’t say anything more than ‘I just like it’.
And to play the rhetorical game, what happens when you have hundreds of thousands of lines of insane Redux code where you have lost all sense of the state tree and need to mentally cordon off one single piece of it to not go insane? Kind of like how libraries like this are already doing it.
So here is my challenge to you. Spec out an app that you believe can only be solved with Redux at scale (or rather, highlight the areas of the app that absolutely benefit from Redux, but please provide as detailed a spec as you can if you have the time, or care for that matter). I’d love to hear about this incredible web app.
The reason is because the problems that surface at scale are difficult to illustrate in a comparison blog, which is the foundation for all the rants against redux.
Redux is not complex, contrary to popular belief. The core code can be written in 100 LoC.
The real downside to redux is not the boilerplate that is required to set it up or the number of concepts to learn, instead it’s how easy it is to do it incorrectly. The redux maintainers have spent the last few years not making changes to the core library, but figuring out conventions and helper libraries to make it more clear what you should (eg normalize state) and should not (put every piece of state) in your redux store.
No offense but the spec exercise seems like a waste of both of our time. No amount of talking about an app can illustrate the code organization at scale.
If you missed it rematch is very promising:
It has the feature completeness and interop of redux while being much simpler
https://github.com/rematch/rematch
(though I find Mobx to be perfect)
For folks who use Redux, the React Redux library has gotten much much more developer-friendly than it originally was. The other libraries like Easy Peasy and Rematch serve a nice syntactic sugar, though.
Out of curiosity, any specific features of Rematch and Easy-Peasy that you specifically like that aren't covered in Redux Toolkit? I've actually got an RTK issue open asking for ideas and concepts that we can learn from them:
Actually I was favoring the official React Redux stuff in my comment. Just trying to balance it out by mentioning that Rematch, Easy-Peasy and other libraries in the ecosystem all have their own place in the open source world, even if they can be considered different flavor icings on top of the same cake.
This is a general question, but how do you structure state with hooks if your React app is mostly composed of hierarchical, dynamic components?
For example, let's say the initial UI lets you create one or more of Component A (only one type of component); Component A can create one or more Component B (which can be many types of components); and Component B can create one or more of Component C (which can be many types of components).
The app is to model some configuration for some physical devices that are interconnected. I have something working today using the "useImmerReducer" package and updating parent components whenever children components change, but was curious if there is a more established pattern?
Depending on which principles/patterns you are applying, you can go as elaborate as using something like Recoil for that (I think this might be a great application of Recoil as it deals with atomic data), or you can choose to go simple with a tree-type data structure that parallels your component tree.
But first thing you should identify, IMHO, is which of those states are _really_ "shared" states. Coz some of those state values are probably better kept local.
I was looking at Recoil this weekend and it does seem like a good use case, I just wasn't sure how it would simplify what I was doing.
I think I may have applied a bad design as I converted all of my React Components to React functions. Is it possible to instantiate Recoil atoms inside of for loops?
Basically, I would like to be able to scope state locally to React functions, but hooks don't let you do that, they have to be completely abstracted.
It would be counter-intuitive if I endorse a Recoil-based solution on this thread that talks about a different library, LOL.
But since I want to help as much as I can, my advice is, regardless of which library you choose, or which approach (atomic vs. monolithic/structured)... start with analyzing which parts of the state in your app really are supposed to be "shared" state. I have a feeling you may be trying to use "shared" state libraries to manage state that only the individual components would actually need. Do those dynamic components actually need to share data? The answer to that is the first important consideration, IMHO, before you can go forward.
hi thanks for building this - i'm struggling with finding a good state management react workflow too. could you speak a bit about the other alternatives that are around and when Simpler is better, and when it isn't? Would help me have more confidence to pick this up.. thanks!
Hi. There are LOTS of much more popular libs you can choose from. My library does not intend to compete as the "best" library, but it has a very specific set of goals, the topmost of which is simplicity through a minimalist API.
Don't get me wrong. SimpleR State is a "complete" library despite the simple API. It supports things like selectors, async actions, and plug-ins. And soon, it will come with built-in plug-ins like persistence, Dev Tools, validation, etc.
Everyone has different priorities when choosing a library, so I suggest going through the design goals that I highlighted in the README file, or complete documentation here:
and see if it fits what you're specifically looking for in a library.
At the end of the day, all these libraries are just React code. In that sense they differ in terms of patterns/principles behind their implementation, but maybe more importantly, in the API/syntax (which is what immediately matters to the developer using it). This is what I can confidently say that SimpleR State delivers... one of the simplest APIs you can find.
52 comments
[ 2.9 ms ] story [ 122 ms ] threadI wrote this library with the hope that this might be it. Any ideas/suggestions how to further simplify it would be super!
1. Do you mind sharing examples with async calls? This is very common and I really look for this example as quick as possible
2. How you do connect two stores? Say one triggers and update in the other...
Thanks a lot :)
Specifically, look at these "Recipes" pages:
https://simpler-state.js.org/recipe-async.html
https://simpler-state.js.org/recipe-orchestrators.html
Not sure if simpler but something I’d be missing/would feel inconsistent.
It rely on https://github.com/facebook/react/tree/master/packages/use-s..., which make it safe to use in concurrent mode and the implementation a lot simpler.
https://github.com/pmndrs/zustand
Since data is not encapsulated inside React component tree, I found it to be multiple times faster than when using Context.
And one thing that's perhaps the most obvious... it's simpler because you don't have to use Providers at all.
What do you mean by data being encapsulated in the tree? How does that make it slower?
I tried scoping the entities using Context in some prior art which we use in production. Some colleagues kindly gave me some benchmark results and the version without Context (external/module-scope) was faster.
I'm not trying to debate against Context here. In fact, there's nothing that would stop anyone from using SimpleR State's entities with Context API.
It's never my intention for this library to try and be the "best" out there. I simply want to create what I sought for, which is the closest to the simplest approach I can think of. And to share it to the public, in case someone out there is looking for the same thing I am, and maybe it could help that someone. That's what open source is for, after all.
> multiple times faster than when using Context
Oh cool! Do you have some benchmark results for that? Would be awesome to post them in the README if you can.
> simpler because you don't have to use Providers at all
I think the Provider pattern is part of the functional programming pattern with React, so while I do agree it might be harder to get used to but it underlines the no side-effects affecting the state of a given React components and its children.
At scale proper action, reducer pattern is helpful to manage a complicated state tree to still make it functional, easily testable and giving the same end result as a function of state.
https://simpler-state.js.org/recipe-transforms.html
Thanks for your reply.
I like this solution because it’s simple, testable, and global.
That's a bit like saying a excavator is a bit too complex to hammer nails. Yes, that's true, but that was not why we created the excavator in the first place.
Same with Redux. Initially created to get rid of big, hairy and complex balls of state. If you use it in your basic CRUD, you're probably using the wrong tool rather than the tool is wrong itself.
Each tool has it's place in our toolboxes. It's our job to decide when to use what tool.
For example, in React the common way of using hooks is `useMyhook()` where "Myhook" is whatever you name it, like "useState", "useEffect", etc.
So I'd argue that an API that follows the conventions in a platform is simpler than one that rewrites them. In this specific situation in the first demo, I would expect to have a hook called `useCounter()` instead of `counter.use()`.
Furthermore, since we are manipulating state again the convention in React for state manipulation is to return the value and then the setter, like:
Now I understand since it's a global state we cannot give it a local initial value to avoid race conditions, so that's IMHO about as simple as you can get.I didn't do that, but I believe I got pretty close with my own React state management library https://statux.dev/:
1. It was inadvertently removed from the documentation, but these are equivalent:
but the `counter.use()` was chosen in the documentation due to more feedback that requested this "simpler" format (i.e. no need to import `useEntity()`. But again, to your point I will restore the mention of `useEntity` in the documentation.2. As for the [state, setState] convention, think of useEntity more like useContext than useState. Then it gets simpler.
3. I would also argue that since this is "shared" state, the developer might (again, the library is not opinionated on this) choose to separate the logic of updating shared state. For this reason, I didn't see any reason to provide a setter through the hook, when you can access the setter from anywhere via something like counter.set(). Conforming to useState convention was not justified in this case, especially since useContext convention equally makes sense for shared state.
4. To suit whatever convention, you can always do something like this alongside the definition of the entity:
I want to point out that SimpleR State provides the flexible constructs to allow the developer to tailor it to their preferred convention.Thanks for your feedback.
Which is totally fine, but not your everyday problem for the rest of us! I'm very happy to see all of these versions pop up as well.
What about this would get worse with more engineers or higher caliber engineers that Redux clearly avoids?
Basically the Flux architecture. See from 10:20:
https://www.youtube.com/watch?v=nYkdrAPrdcw
But there is always an alternative, IMHO. If the project has a good code structure and follow equally good coding standards and review process, using simple un-opinionated/flexible libraries would not be a liability with "scale" (in terms of team/project size).
And there's one advantage of simpler approaches for growing teams: faster/easier onboarding. Let's face it, even good React/Redux developers can understand simpler code faster.
Just an alternative thought. But I completely get your point.
I’m just not seeing the argument here, and I’ve been on multiple redux applications on teams of various sizes. We always seem to create layers of indirection to do the simplest possible state update.
We adopted Dan Abramov’s mental model, and my god, it was a labyrinth.
- https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-ta...
- https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-ta...
- https://medium.com/@dan_abramov/you-might-not-need-redux-be4...
Ultimately, it's about putting a deliberate separation between "what happened" in the UI and "how the state is updated", writing as much of your state update logic as pure functions, and being able to use that indirection to enable tracing state updates over time via the DevTools.
Also note that our official Redux Toolkit package is now the standard recommended way to write Redux logic, and it simplifies most of the Redux code you'll write:
https://redux.js.org/tutorials/fundamentals/part-8-modern-re...
The truth of the story was that community was desperately looking for a solution to global state to avoid prop drilling. No amount of technical virtuosity, or cop outs to a half assed flux architecture that fundamentally mimics model-view-controller or a pub/sub pattern will be satisfiable to anyone with critical thinking ability.
The kids had one job, get some global state available to the app, and they managed in their bravado to pack in ‘addons’, or in sales terms, they ‘up-sold’, that $40 hdmi cable along with your new $1600 television.
Dan packaged his extra bullshit (the reducer pattern) over to a desperate group that had nowhere else to turn for a global state solution. Celebrity and hero worship was one of the premier sins in all of this. The guy didn’t know what the fuck he was doing and no one called him out on it.
Certainly we are not going to marvel at the fact that he is a React core developer. Bad ideas are bad ideas, regardless of the current class that ordains it.
For this, I am depressed, and will continuously antagonize the Redux team for the damage they caused the entire community.
The Redux team owes a debt. Rewrite your library so that the api is 5 lines at max. Replace your conceptions, seek forgiveness for the sin, and let it rest. Until then, don’t peddle your Frankestein ever again anywhere, you all had plenty of time in the limelight and quite frankly - you weren’t good enough.
Like what is the redux-toolkit? Do you guys lack the conviction to decide what the api is or isn’t?
With all that said, if you don’t understand what I’m saying, then mapDispatchToProps or mapsTateToFuckYou, connect everything to nonsense, and I suppose in your new bullshit, createSlice to shut up already. You guys can’t write an api if your life depends on it. And I swear to god, if I hear about the stupid Ducks pattern ... I just can’t anymore.
Anyways, I’d prefer never to punch down if I can avoid it. The redux/abramov/constituents of the react community became the Zeitgeist of the Javacript community. Paragons. And no one stood up to them and behind the bullshit is a clusterfuck of shitty apps. You guys ain’t a small agenda, and I expect the fight to continue.
In the meantime, we're going to keep working to support our users. Who, based on the vast amount of feedback we've gotten over the last couple years, _are_ happy with the directions we're going.
These intro how-to comparisons don’t do redux justice because being simple to use is not the stated goal of redux. Large scale, maintainable, and traceable code is the primary goal of redux. When you allow anything to update your state with zero form of traceability, you’ll start to see the cracks in these simple designs.
Are these new state management libraries easy to use? Sure, but what happens when you have tens of thousands (even hundreds of thousands) of lines of code to deal with and then add major refactoring objectives in the pipeline?
Like others have mentioned, if you are using redux for a simple to-do app, then its design principles are probably not as valuable.
It’s like thinking about time complexity for algorithms, at a small enough N, even slow algorithms can compete, but as you increase N, some algorithms become untenable.
It’s crazy how the Redux people either always appeal to authority (‘my app is bigger than yours’) or can’t say anything more than ‘I just like it’.
And to play the rhetorical game, what happens when you have hundreds of thousands of lines of insane Redux code where you have lost all sense of the state tree and need to mentally cordon off one single piece of it to not go insane? Kind of like how libraries like this are already doing it.
So here is my challenge to you. Spec out an app that you believe can only be solved with Redux at scale (or rather, highlight the areas of the app that absolutely benefit from Redux, but please provide as detailed a spec as you can if you have the time, or care for that matter). I’d love to hear about this incredible web app.
Redux is not complex, contrary to popular belief. The core code can be written in 100 LoC.
The real downside to redux is not the boilerplate that is required to set it up or the number of concepts to learn, instead it’s how easy it is to do it incorrectly. The redux maintainers have spent the last few years not making changes to the core library, but figuring out conventions and helper libraries to make it more clear what you should (eg normalize state) and should not (put every piece of state) in your redux store.
No offense but the spec exercise seems like a waste of both of our time. No amount of talking about an app can illustrate the code organization at scale.
https://easy-peasy.now.sh/
https://redux.js.org/tutorials/fundamentals/part-8-modern-re...
https://redux-toolkit.js.org
https://github.com/reduxjs/redux-toolkit/issues/527
Just incrementally add reducer and you're good to go. With redux-thunk, devtools built-in, i don't need much more.
Better state management to replace redux to me requires another approach (maybe atom like ?)
I use Redux not (just) because its ecosystem and tooling. It's simply just because i found its API simple to use and scale.
https://recoiljs.org/
For example, let's say the initial UI lets you create one or more of Component A (only one type of component); Component A can create one or more Component B (which can be many types of components); and Component B can create one or more of Component C (which can be many types of components).
The app is to model some configuration for some physical devices that are interconnected. I have something working today using the "useImmerReducer" package and updating parent components whenever children components change, but was curious if there is a more established pattern?
But first thing you should identify, IMHO, is which of those states are _really_ "shared" states. Coz some of those state values are probably better kept local.
I think I may have applied a bad design as I converted all of my React Components to React functions. Is it possible to instantiate Recoil atoms inside of for loops? Basically, I would like to be able to scope state locally to React functions, but hooks don't let you do that, they have to be completely abstracted.
But since I want to help as much as I can, my advice is, regardless of which library you choose, or which approach (atomic vs. monolithic/structured)... start with analyzing which parts of the state in your app really are supposed to be "shared" state. I have a feeling you may be trying to use "shared" state libraries to manage state that only the individual components would actually need. Do those dynamic components actually need to share data? The answer to that is the first important consideration, IMHO, before you can go forward.
Good luck.
Don't get me wrong. SimpleR State is a "complete" library despite the simple API. It supports things like selectors, async actions, and plug-ins. And soon, it will come with built-in plug-ins like persistence, Dev Tools, validation, etc.
Everyone has different priorities when choosing a library, so I suggest going through the design goals that I highlighted in the README file, or complete documentation here:
https://simpler-state.js.org
and see if it fits what you're specifically looking for in a library.
At the end of the day, all these libraries are just React code. In that sense they differ in terms of patterns/principles behind their implementation, but maybe more importantly, in the API/syntax (which is what immediately matters to the developer using it). This is what I can confidently say that SimpleR State delivers... one of the simplest APIs you can find.