Read through the overview and the introduction and literally could not tell what Overmind was supposed to be helping with. Everything shown looks like just basic examples of using state normally in JavaScript. What does it actually do?
Lib like this or Redux seems like to try to better help people who don't have CS back ground to develop. Anyone who had CS training should be able to state management in plain JS or other general purpose programming language.
The main boon of Redux et al in my experience is that they impose some rules as to where and how state changers are handled, meaning less weird inconsistencies when working in a team (especielly if the team members change over time).
Just to state the obvious: there isn't much to reinvent in a wheel, but certainly it's not a one-size-fits-all kind of object.
That wheel might have been designed by a team of brilliant engineers and built with the latest super materials, but if it's a race car's wheel I wouldn't mount it on a bicycle.
Probably because JavaScript as it is used in browsers and especially React is asynchronous and in CS you traditionally study classic programming languages which are mostly synchronous code, even if it is multi-threaded you still command where and how access to shared data happens most of the time. In JavaScript and React asynchronous aspect is mostly hidden from you hence need for things like Reudx.
Redux was first released more than 5 years ago, it's had more than 3000 commits merged from more than 800 developers, and there have been 69 releases. That's a lot of learning about how to do state management in JS. I would argue that's beyond what an individual developer could ever do. Mobx has similarly large numbers - almost 3000 commits from more than 400 developers. No doubt other popular state libraries also have those sorts of numbers.
If you need a general state management library you'd be crazy to write your own. You might be able to do 90% of what the big, popular libraries have done, but that's just settling for something 10% worse for no good reason. Why give up all that knowledge, testing, and creativity when you can build on top of it? Let other people make the mistakes.
Having more developers, commits and code doesn't mean better software!
In general CS course I took in Uni over 20 years ago, one learns about data structure and state of an application with multiple threads. It is something 'web developer' lacks as web was originally meant to be a document based.
I am not saying developers can't pick that up during their development career, it is just that the bar for being a developer has being simnifically lowered in the last few years. It turned more into a buzz word now days.
It is something 'web developer' lacks as web was originally meant to be a document based.
This is unrelated but it's something that annoys me. Even in Tim Berners-Lee's original memo proposing the web he stated "Hypertext allows documents to be linked into "live" data so that every time the link is followed, the information is retrieved. If one sacrifices portability, it is possible so make following a link fire up a special application, so that diagnostic programs, for example, could be linked directly into the maintenance guide."
The idea that the web could be about more than static documents was there right from the beginning.
What does the number of commits have to do with anything? That doesn’t imply any kind of quality, right?
Also, have you taken a look at the source code for Redux let’s say? It’s an extremely small library. Not exaggerating, it’s on the order of 1,000 LOC. You don’t think someone could produce that?
I would agree with what you’re saying if you were talking about something like Postgres, which is enormous and complex. These state management libraries are very very simple (I’ve implemented small versions of them many times), and really just encourage a pattern in the code. They’re not operating systems unto themselves.
Unless you want to consider all those people who contributed as not really smart for spending their time on something that a single person can easily do along the way in their project, I'm not sure why you would suggest doing so as a better alternative.
There are numerous other discussions on whether use of a state management library is needed ever, or at least in some projects. As someone who doesn't usually actually need it, I can understand the motivation for less people to use it until they know enough to realize they need it, but also don't understand people who ignore valid needs of larger teams and projects where something like Redux makes a lot of difference and is necessary. Again, unless those people consider themselves and their projects to be the biggest and most complex that can ever be, which is very likely to be false.
I think the people disagreeing with this greatly overestimate what is actually contained in a library like Redux. An entire ecosystem sprang up around it and most of it is completely unnecessary and overly complex. The base library itself is almost nothing at all and should not be hard for anyone with experience to independently create.
This appears to be a competitor to Redux, but with more batteries included? I was disappointed to see this wasn't answered in the FAQ--might be worth mentioning at least there, if not as an entire article on the site.
For a great example of this, see the Pulumi docs. They list many potential alternatives and why you might choose one or the other. https://www.pulumi.com/docs/intro/vs/
It lets you make state updates using native JavaScript mutation APIs. It uses Proxies to convert those mutable updates to be immutable so that your component updates correctly. This will work:
It doesn't look like it (from what I gather about `use-immer`). What's being suggested is updating React state via a mutable API on the data value itself. `use-immer` wraps the useState/useReducer functional updaters with a call to immer, whereas `use-structure` suggests mutating the data, which is what every React-beginner instinctively tries to do when they first get started with React. Same idea of using Proxies as immer though.
I thought about changing my slightly verbose react state updates to immerjs but your lib looks even simpler.
I dont think it can be simplified any further, really great, thank you.
This looks pretty cool, I love your use of proxies. Along with that though, I'm curious if you've done any performance testing comparisons? This could very well be out of date now but at some point I read that accessing properties on a proxied object are like 600 times slower than a regular JS object. I wonder if that could be a bottleneck if you're doing state updates on, say, scroll events or something.
I've been able to notice performance hiccups in these cases even just using React state. Of course debouncing usually helps.
No, haven’t done any perf testing. I’m pretty sure Vue is moving to use Poxies, so I think it’s somewhat safe. You can still use useState where you need it.
Can someone explain the benefit of using this over the (already existing and popular) reactive libraries?
I've found a combination of MobX/RxJS to be a good fit for most applications that need reactive state and don't use a framework (like Vue or Svelte) that already ships with reactivity.
Looking at this - it looks very similar except that it requires a global mutable variable (which I'm not a fan of, kind of like MobX state tree but without the serialization fun).
Hi there and thanks for the feedback on "Why even choose this". Will update the front page!
But to answer your question.
The main reason Overmind and its predecessor Cerebral (https://cerebraljs.com/) was developed is application insight. The complexity of what we build on the web these days is way beyond the scope of what our brains are able to comprehend. What effects are triggered and what state changes are made is difficult to infer reading code and using low level debugging tools. Basically understanding what actually happens when you open the browser and interact with the application. So the main reason Overmind should catch your interest is its debugger. It is not there just to debug errors, it is there to constantly give you a mental image of the whole application at the abstraction level of the application itself.
The second reason Overmind was developed is to reduce the amount of concepts of APIs required to get going with an application. Most developers, arguably, think about code imperatively. "I have this thing I want to do, let me just do it". That is why Overmind has a base concept of an "action", where you can access any state, effects and other actions you have defined in your application... and just do it. This, arguably, lowers the threshold of understanding and scaling up your app. When you get into concepts related to time complexity Overmind provides operators. When you get into concepts related to state complexity Overmind provides statemachines and statecharts. It is important to understand that Overmind does not let you just free wield state changes. You can only run state changes in actions and unlike Mobx you can use async code as normal. The state changes are bound to the action execution itself, again creating a more straight experience with less concepts to learn.
The third reason is TypeScript. We have all felt the pain of Redux boilerplate and with TypeScript it does not become better. Overmind has the goal for you to spend as little effort as possible telling TypeScript about your application, it should just understand it. Basically help developers move to TypeScript by gaining as much benefit as possible with as little typing as possible.
Now, Overmind was not built to send a message that mobx-state-tree and redux are bad solutions. It is intended to be a healthy alternative in the ecosystem showing that controlled mutability is a valid approach and hopefully be an inspiration that we can push visual tooling way beyond what we are doing currently.
I like the look of Overmind, the website is great as are your videos. I hope it gets more traction because the values you describe are important and underappreciated.
I'm a big fan of Mobx State Tree but have begun to hit a wall.
I'm currently dealing with TypeScript compilation time issues due to the complexity of the types MobxStateTree employs and thus have to face the fact that I can't rely on it to express my application without tiptoeing over circular type performance holes.
This is definitely not true, especially if you co-locate your data fetching in your reducers, which is a common pattern.
It also provides a single, centralized store instead of needing many context's and lets you abstract data shape/formatting logic away instead of having it in your application.
Context and State are great, but they serve a different purpose than Redux.
Having used hooks to replace my state at some point I couldn't agree more. Application state should not be dependent on components, rather components should be dependent on application state.
My recommendation is keep hooks and contexts for ui state only, like form fields/validations, modal popups, drawer collapse, filter options, etc, but for things dealing with more general application state which the ui will display, like user information, products list, project data, application settings, etc, a separable state machine should be used. This works well because components are responsible for their own state leaving the state manager clean from individual ui component information, and ui components are free to be passed whatever data improving reusability.
Why should a seperate state machine be used? Redux doesn't magically seperate state information from the tree. It's built upon react context/provider system, which in effect can be seen as a component.
The special sauce, in regards to seperation, is that it can be wired into the component tree without passing it down, which is a property of provider/context and not redux itself.
> Application state should not be dependent on components
Sorry, I don't follow. When using Context, how does the application state become dependent on Components any more than it is with Redux? You can accomplish pretty much the same thing with far less code.
> This is definitely not true, especially if you co-locate your data fetching in your reducers, which is a common pattern.
How can it be definitely not true, when you have to say "especially"? Most code I've seen (including the official docs) don't data fetch in reducers. But even then, I'm not sure what you mean.
> It also provides a single, centralized store instead of needing many contexts...
Which you can very well do with useContext and useState.
It is very difficult to convey "When does this solution pay back its cost". If you can get by with only React as state management, great. There are so many factors that ties into friction. Everything from the experience of the team, preferences, size of project, how clear the domains of the project is, ability to separate and isolate, typescript or not etc.
Silly question: is state management used outside of the frontend world? The last time I developed desktop apps (it was a long time ago) no-one had ever felt the need to remove state from the individual components and add it to a global store.
So, do very complex desktop applications use redux-like state management nowadays?
Lots of complex applications have always been using state machines, this is not a concept that originated from web front-end development. You can find them in Delphi, Visual Basic, QT, etc.
Applications that need to have state, surely have it.
Most applications store their state in sessions / memcached / redis / databases.
But, of course, some apps must have real time state management that is shared among thousands of users. Think high-traffic low-latency trading engines. Think multiplayer games.
I've built something similar to this in a large app with a lot of networking/async data updates... except these synchronous state mechanisms and parent to child pass-downs are still super annoying with React.
I ended up with a couple global queues (custom, async data pub/sub, similar to Rx) that each component could to subscribe to. A more reactive state management makes things a lot more simple. Only bare-minimum stateless children components (like buttons) are passed props with parent state.
47 comments
[ 3.1 ms ] story [ 122 ms ] threadThat wheel might have been designed by a team of brilliant engineers and built with the latest super materials, but if it's a race car's wheel I wouldn't mount it on a bicycle.
I feel like you could take this stance on almost any framework or library.
If you need a general state management library you'd be crazy to write your own. You might be able to do 90% of what the big, popular libraries have done, but that's just settling for something 10% worse for no good reason. Why give up all that knowledge, testing, and creativity when you can build on top of it? Let other people make the mistakes.
In general CS course I took in Uni over 20 years ago, one learns about data structure and state of an application with multiple threads. It is something 'web developer' lacks as web was originally meant to be a document based.
I am not saying developers can't pick that up during their development career, it is just that the bar for being a developer has being simnifically lowered in the last few years. It turned more into a buzz word now days.
This is unrelated but it's something that annoys me. Even in Tim Berners-Lee's original memo proposing the web he stated "Hypertext allows documents to be linked into "live" data so that every time the link is followed, the information is retrieved. If one sacrifices portability, it is possible so make following a link fire up a special application, so that diagnostic programs, for example, could be linked directly into the maintenance guide."
The idea that the web could be about more than static documents was there right from the beginning.
[1] https://www.w3.org/History/1989/proposal.html - Live Links section
Also, have you taken a look at the source code for Redux let’s say? It’s an extremely small library. Not exaggerating, it’s on the order of 1,000 LOC. You don’t think someone could produce that?
I would agree with what you’re saying if you were talking about something like Postgres, which is enormous and complex. These state management libraries are very very simple (I’ve implemented small versions of them many times), and really just encourage a pattern in the code. They’re not operating systems unto themselves.
There are numerous other discussions on whether use of a state management library is needed ever, or at least in some projects. As someone who doesn't usually actually need it, I can understand the motivation for less people to use it until they know enough to realize they need it, but also don't understand people who ignore valid needs of larger teams and projects where something like Redux makes a lot of difference and is necessary. Again, unless those people consider themselves and their projects to be the biggest and most complex that can ever be, which is very likely to be false.
For a great example of this, see the Pulumi docs. They list many potential alternatives and why you might choose one or the other. https://www.pulumi.com/docs/intro/vs/
It lets you make state updates using native JavaScript mutation APIs. It uses Proxies to convert those mutable updates to be immutable so that your component updates correctly. This will work:
...
const arr = useStructure([]);
...
<button onClick={() => arr.push(1, 2, 3) }>Add value</button>
But you could use deeply nested arrays/objects/Maps/Sets. Or you could use your own class with its “mutating” methods.
If you know basic JS, you should be able to use it without worries.
This is really interesting! Great idea.
I've been able to notice performance hiccups in these cases even just using React state. Of course debouncing usually helps.
I've found a combination of MobX/RxJS to be a good fit for most applications that need reactive state and don't use a framework (like Vue or Svelte) that already ships with reactivity.
Looking at this - it looks very similar except that it requires a global mutable variable (which I'm not a fan of, kind of like MobX state tree but without the serialization fun).
Someone please sell me on this :]?
But to answer your question.
The main reason Overmind and its predecessor Cerebral (https://cerebraljs.com/) was developed is application insight. The complexity of what we build on the web these days is way beyond the scope of what our brains are able to comprehend. What effects are triggered and what state changes are made is difficult to infer reading code and using low level debugging tools. Basically understanding what actually happens when you open the browser and interact with the application. So the main reason Overmind should catch your interest is its debugger. It is not there just to debug errors, it is there to constantly give you a mental image of the whole application at the abstraction level of the application itself.
The second reason Overmind was developed is to reduce the amount of concepts of APIs required to get going with an application. Most developers, arguably, think about code imperatively. "I have this thing I want to do, let me just do it". That is why Overmind has a base concept of an "action", where you can access any state, effects and other actions you have defined in your application... and just do it. This, arguably, lowers the threshold of understanding and scaling up your app. When you get into concepts related to time complexity Overmind provides operators. When you get into concepts related to state complexity Overmind provides statemachines and statecharts. It is important to understand that Overmind does not let you just free wield state changes. You can only run state changes in actions and unlike Mobx you can use async code as normal. The state changes are bound to the action execution itself, again creating a more straight experience with less concepts to learn.
The third reason is TypeScript. We have all felt the pain of Redux boilerplate and with TypeScript it does not become better. Overmind has the goal for you to spend as little effort as possible telling TypeScript about your application, it should just understand it. Basically help developers move to TypeScript by gaining as much benefit as possible with as little typing as possible.
Now, Overmind was not built to send a message that mobx-state-tree and redux are bad solutions. It is intended to be a healthy alternative in the ecosystem showing that controlled mutability is a valid approach and hopefully be an inspiration that we can push visual tooling way beyond what we are doing currently.
To get more details on controlled mutation VS value comparison (immutability) I wrote an article here: https://itnext.io/updating-uis-value-comparison-vs-mutation-...
I'm a big fan of Mobx State Tree but have begun to hit a wall.
I'm currently dealing with TypeScript compilation time issues due to the complexity of the types MobxStateTree employs and thus have to face the fact that I can't rely on it to express my application without tiptoeing over circular type performance holes.
Redux btw, is redundant now; and offers very little value over useContext + useState. And they work wonderfully with TypeScript.
It also provides a single, centralized store instead of needing many context's and lets you abstract data shape/formatting logic away instead of having it in your application.
Context and State are great, but they serve a different purpose than Redux.
My recommendation is keep hooks and contexts for ui state only, like form fields/validations, modal popups, drawer collapse, filter options, etc, but for things dealing with more general application state which the ui will display, like user information, products list, project data, application settings, etc, a separable state machine should be used. This works well because components are responsible for their own state leaving the state manager clean from individual ui component information, and ui components are free to be passed whatever data improving reusability.
The special sauce, in regards to seperation, is that it can be wired into the component tree without passing it down, which is a property of provider/context and not redux itself.
Sorry, I don't follow. When using Context, how does the application state become dependent on Components any more than it is with Redux? You can accomplish pretty much the same thing with far less code.
Can you provide an example?
How can it be definitely not true, when you have to say "especially"? Most code I've seen (including the official docs) don't data fetch in reducers. But even then, I'm not sure what you mean.
> It also provides a single, centralized store instead of needing many contexts...
Which you can very well do with useContext and useState.
From a point of view of API design, it looks great.
Joking aside, im sure this is useful for state management, where it matters.
It is very difficult to convey "When does this solution pay back its cost". If you can get by with only React as state management, great. There are so many factors that ties into friction. Everything from the experience of the team, preferences, size of project, how clear the domains of the project is, ability to separate and isolate, typescript or not etc.
So, do very complex desktop applications use redux-like state management nowadays?
Most applications store their state in sessions / memcached / redis / databases.
But, of course, some apps must have real time state management that is shared among thousands of users. Think high-traffic low-latency trading engines. Think multiplayer games.
You seem to believe that state is synonymous to "reactive store". Also, sessions/ memcached/ dbs have little to do with application state management.
I ended up with a couple global queues (custom, async data pub/sub, similar to Rx) that each component could to subscribe to. A more reactive state management makes things a lot more simple. Only bare-minimum stateless children components (like buttons) are passed props with parent state.