6 ms·
Show HN: The simplest React state manager now at stable release
- robovirtuoso 5y agoAfter lots of tweaks based on the valuable feedback from the community, SimpleR State is finally at its first official stable release v1.0.0. Big thanks go to the great people that contributed to this effort to bring it to Production grade. I can now confidently call it the "simplest" out there. Mission accomplished.
- thunderbong 5y agoThis looks fantastic! After twisting my brains over redux, this looks like a breeze to work with!
- tomaszs 5y agoIt looks promising. I wonder how it will play with TypeScript. Would need to dig deeper. However the angle to make it simple is great. No boilerplate code, unit testing as it should have always been. Great work!
- aenero 5y agoHappy to say that this also works well with TypeScript with minimal explicit types required. My main goal is to maximize the use of type inference. The documentation provides TypeScript version of each example (outside of the TL;DR cheat sheet), except in cases where TS version is the same as the JS due to type inference. Even where there is TS version, the difference from JS is minimal.
- panzerklein 5y agoLooks like it's based on the same idea as jotai[1] [1] https://github.com/pmndrs/jotai https://github.com/pmndrs/jotai
- danlugo92 5y agoUsage feels very similar to redux when using redux toolkit, and the latter comes with a more mature ecosystem. There was also nothing about streams and such that you would normally handle with redux-observable or redux-saga. One of the super powers of redux+saga is being able to listen to every state update (and act according to that), this doesn't seem to be possible (unless you make a super entity I suppose?).
- wayneftw 5y agoA quick glance at the documentation showed that you can write plug-ins to do such things as listening to all state changes (unless I misunderstood something). See the logging plugin example. Without a Chrome dev tools extension though I don't think I could leave redux just yet.
- aenero 5y agoHappy to hint that there is an upcoming plug-in to support Redux DevTools too. Soon.
- mewpmewp2 5y agoWould it work with server side rendering? Usually there would be a problem importing/defining things from static files like that as this would be shared within the server between instances of renderings.
- munawwar 5y agoThe simplicity goes away when supporting SSR. You have to depend on multiple stores (one per request) being injected "from the top" (e.g via Context Provider). This is my take on the problem -> https://github.com/Munawwar/react-global-states/tree/ssr https://github.com/Munawwar/react-global-states/tree/ssr
- aenero 5y agoSimpleR State acts as a "module-level store", one of the reasons why it's so simple. When you start doing SSR, though, as with anything else in React global state management, you would sacrifice some of that simplicity. So to answer the question, yes SimpleR State works with SSR, but you need to take an extra step. You would need to somehow "scope" your global state inside the React component tree. The most common solution is using a Context to store your server-side entities, so that they are not "shared" among SSR requests. SimpleR State proclaims itself as "unopinionated", so the preferred SSR solution is a decision that the developer has to make. It would be worth adding some options in the documentation, though. So thanks for bringing this up. I also received a few requests on such documentation in the previous Request For Comments during the beta run. A doc page on SSR is underway.
- hliyan 5y agoSeems like the simplest state management API to wrap one's head around that I've seen so far.
- Tajnymag 5y agoLooks great. The API reminds me of the new Vue 3 Composition API.
- BenoitP 5y agoVery nice! I've been prototyping something server-side in the style of the SQL Kappa architecture: facts on immutable logs, possibly keyed (and compactable by key), and SQL materialized views streaming the updates with Flink. And I'm in search of a React state manager in that philosophy. Rows are sent to each client requesting a feed of them: INSERT INTO user_orders_total_feed(user_id, data) SELECT uo.user_id, SUM(o.price) total FROM user_order uo JOIN order o ON uo.user_id = o.user_id JOIN user_live_subscription uls ON uo.user_id = uls.user_id GROUP BY uo.user_id WHERE uls.subscription_topic = 'orders_total' But: maybe you want all the orders in the UI and do the aggregation client-side, to have all orders alongside the total. You could move the aggregation to the client side. And it would be great to have the same data language than on the server (so that business rule expression is the same). In that case, a React Hook library like SimpleR State could aggregate in SQL the sum and update the view reactively. It would look like: const TotalView = () => { const view = state.view('SELECT SUM(price) total FROM order_feed'); return ( <> <div>{view.total}</div> </> ) } I don't think that would be easy to do; but I think there is a market for it: The business folks doing no-code+SQL client-side, and they would sometimes ask through proper channels for a query to be computed globally server-side or be brought client-side.
- aenero 5y agoAlthough this is not provided by SimpleR State out of the box, the library makes it easy to implement a "selector" function that accepts an SQL query, and pass this selector to the entity hook. This SQL query syntax in React can well be a library on its own, I suppose.
- BenoitP 5y agoWould that be the transform function from here [1]? I do agree too that this definitely should be a library on its own. Anyway thanks for your work; I'll definitely check SimpleR in my project. [1] https://github.com/arnelenero/simpler-state/blob/f6336817c9e3b0eeb56c28e64e7cbb4c12c9500a/docs/recipe-transforms.md https://github.com/arnelenero/simpler-state/blob/f6336817c9e...
- garritfra 5y agoIMHO, since react hooks hit the market, state management libraries became kind of obsolete.
- jeremy_k 5y agoWe tried this approach and have attempted to bend React Context to our need, but it feels like its gotten pretty hacky. Are you only using component state and Context or what is your approach?
- steve_adams_86 5y agoNot who you asked, but: We use useContextSelector to ease context rendering redundantly and to make it clearer what a component uses within a context. It isn’t native to react, but it appears it will be in a similar form in the future. It has been a joy to use so far. Having server side state working so seamlessly with the client is a great feature for us.
- mhalle 5y agoFor another comparison, there's valtio that I learned about from a previous HN discussion: https://github.com/pmndrs/valtio https://github.com/pmndrs/valtio
- aerovistae 5y agoI haven't tried this one, but for what it's worth, if you're looking for a simple state manager, I LOOOOOOOOOVE Pullstate.js. I've been using it for a reasonably complex frontend and it's just excellent, an absolute breeze to work with. For reference, I'm the type of person who appreciates the power of redux but views it as conceptually overcomplicated to the detriment of the developer experience-- I felt it was overhyped and added limited value relative to the cost of its complexity. (Not that it's that complex, but more than a state manager needs to be.) Pullstate is extremely simple but just works perfectly.
- richeyryan 5y agoThat looks really good. I like how the hook is built into the store API. My problem with a lot of these simple state managers is they often just stop short of handling asynchronous state. I think it should pretty much be mandatory to handle pending and error states on promises for state manager nowadays. Pullstate's Async Actions look pretty good for that. I've been using Effector a lot recently because it has just a bit more power in managing the interactions between stores and events but if I needed something more straightforward Pullstate would be good. Thanks for the tip!
- fastball 5y agoIf you like this API but are already using Redux (or still want to use Redux), I've found Rematch[1] to be a very productive wrapper around redux that has a DX almost identical to this library. [1] https://rematchjs.org/ https://rematchjs.org/
- rtcoms 5y agoHave you compared this with other libraries like easy-peasy(https://easy-peasy.vercel.app/ https://easy-peasy.vercel.app/) and kea.js(https://kea.js.org/ https://kea.js.org/) I've tried both of these and actually not fully able to decide which one to pick. I'm inclined towards kea.js
- xyclos 5y agoreminds me of mobx (which I find very simple). an entity is just like an observable, no?
- yetanotherjosh 5y agoI'm an avid user of mobx and yes, this is similar, but no where near as powerful, and much less magical. For example, in no particular order: * mobx is smart enough to know when only one property of a complex object has changed and that that component depends only on that property. So you can have complex state objects, and if your component only uses property X of said object, it only re-renders if X changes but not Y. * mobx allows you to compose observables - any observable can reference the value of any other observable and if that second observable changes, the listeners for the first observable will re-render, etc. This means state can depend on other state, and everything updates correctly. For example, if you have a store that fetches profile data for the auth user, and the auth user id changes due to login or logout, the profile data store can trigger a refetch, all this happening outside the react component tree, then finally the correct components re-render. * mobx works on it own and is agnostic to framework (react/vue/etc) and is integrated via binding libraries for each framework. * mobx provides quite a few different kinds of observables with different behaviors (shallow maps, lists, etc) * mobx allows you to declare arbitrary reactions that run automatically when state changes, whereas this library here really just re-renders components when state changes. * With mobx you don't even have to say which things in your component use observables - you just wrap your component in observer(), and any time it references an observable, mobx tracks it and will re-render the component if the observable changes. Whereas here you need explicitly hooks for each state atom. There are many more differences, in every case mobx does more. So mobx is a far more complex and powerful system, whereas this is a simpler system that extends useState() hooks with objects that live outside the component. Which is not a value judgement, use the simplest tool that meets your needs.
- FlashBlaze 5y agoHave been using mobx recently and wrapping your component in observer() and seeing it update when the observable changes, feels truly amazing.
- jokethrowaway 5y agoThere are tons of small simple state management solutions for react coming from all the people who hate redux's complexity and lack of async actions Well done for getting some community traction!
- acemarke 5y agoNote that our official Redux Toolkit package specifically resolves most of the concerns people have expressed over the years about "Redux boilerplate", including drastically simplifying writing reducers and actions and including support for thunks out of the box. RTK is now the standard approach for writing Redux logic: - https://redux-toolkit.js.org https://redux-toolkit.js.org - https://redux.js.org/tutorials/fundamentals/part-8-modern-redux https://redux.js.org/tutorials/fundamentals/part-8-modern-re...
- lf-non 5y agoI found effector[1] after I started looking around for a state manager which: 1. Either supported multiple stores or provides a way to subscribe to individual branches (as opposed to the entire store). 2. Had an action/event abstraction similar to redux where multiple branches (or multiple stores) could subscribe to the same action and update independently (and without knowledge of invoker). I have been using it for some time and have had a good experience. The core is framework agnostic (with additional integrations for react & vue). I started used it with Svelte and its API matches the expectations of Svelte stores so you can use it without needing any additional integration, which was cool. Later I used it with lit-element through a 5 line custom integration and that worked pretty well too. [1] https://github.com/effector/effector https://github.com/effector/effector
- tyingq 5y agoCurious if React developers feel like this sort of fragmentation of what tools to use around React is fine, or if it's a pain point for you.
- chrisco255 5y agoFragmentation comes with open source. State management is fragmented on the backend as well: PostgreSQL, MongoDB, Kafka, Redis, Dynamo, Influx, etc...it's just that state management fundamentally has different trade-offs based on how you structure it (and may involve 1 or several of these). If your app is simple, you don't really need a separate state-management solution (just use the built-in React useState and useReducer hooks). If it's complex, you have a choice to make, but that's a fundamental issue with apps at scale and you have to make those choices top to bottom.
- vaughan 5y agoI feel like we are still waiting for someone to create a nice multi-paradigm database blending everything we’ve learned in the past 50 years, that can also run in the browser. I see all state as a stream of events building a graph, then we run queries on that graph. Then it’s all about optimizing the queries which we do. We’ve kind of shoehorned our use cases into whatever dbs we had available and have probably been overwhelmed by the speed we needed to scale our cloud storage resulting in sub-optimal solutions. Or maybe it’s just wishful thinking that there will exist a db to do it all.
- tyingq 5y agoAs an outsider to React, it seems significantly less batteries-included and more fragmented than Angular.
- ezekg 5y agoI still don't think I'll ever use something other than this: https://formidable.com/blog/2021/stores-no-context-api/ https://formidable.com/blog/2021/stores-no-context-api/. Literally as simple as it gets.
- kevincox 5y agoThe choice of `set` taking a function is a questionable one. I know this is fairly common for JS libraries but IMHO it should only be used when you know that the value can't naturally be a function. Otherwise it is a footgun. let someval = () => 1234; state.set(someval) // Oops. You need to remember to write the following if the value might be a function. state.set(() => someval); I would have just made this a separate function and call it `.update()`.
- alexandr1us 5y agoI made this a while ago. It is super simple and fast state manager for React Native and Expo https://github.com/4TWIGGERS/aniuta https://github.com/4TWIGGERS/aniuta