-
I think it's because redux is quite painful to use with very modern apps. Most of the time you need something like `redux-saga` or `redux-thunk` to deal with async side effects. I'm not sure which is the most popular today, but sagas are based on generators and trying to use those with typescript is very very painful and the underlying issue [1] is marked as a design limitation in TS itself.
https://github.com/microsoft/TypeScript/issues/32523
In addition, if you want to have your app load as smaller chunks rather than a single large bundle, you need to be careful to ensure that things work even all the backing reducers aren't yet loaded.
-
CodeRabbit
CodeRabbit: AI Code Reviews for Developers. Revolutionize your code reviews with AI. CodeRabbit offers PR summaries, code walkthroughs, 1-click suggestions, and AST-based analysis. Boost productivity and code quality across all major languages with each PR.
-
The first version of React was released on 2013, it took almost 10 years for Suspense to exist (we _just_ got it now with React 18), that's what I'm talking about. Even functional components and hooks took a lot of time from them get and implement the idea after they tried to use ES classes and made everything much harder to manage. Context also isn't perfect, I like it but the redraw performance is not amazing and doesn't scale at all to bigger applications.
> https://github.com/yyx990803/vue-svelte-size-analysis
This is an interesting comparison I haven't seen before, I wonder if it's true for a complete application using some lib for state management, routing, etc. and if this isn't just a kind of cherry picked example. Thanks for showing this though.
-
Depends on what you mean here specifically :)
I'll agree that the Redux DevTools "skip action" and "jump back to action" features are not all that commonly used in practice. I _maintain_ Redux, and I don't even use them that often.
On the other hand, the ability to see a written list of all dispatched action type names is valuable by itself. So is the ability to click one of the listed actions and see the action contents, state diff, and final state. _That_ is very powerful.
Beyond that... I now work at a company called Replay ( https://replay.io ), and we're building a true "time traveling debugger" for JS. Our app is meant to help simplify debugging scenarios by making it easy to record, reproduce and investigate your code.
The basic idea of Replay: Use our special browser to make a recording of your app, load the recording in our debugger, and you can pause at any point in the recording. In fact, you can add print statements to any line of code, and it will show you what it would have printed every time that line of code ran!
From there, you can jump to any of those print statement hits, and do typical step debugging and inspection of variables. So, it's the best of both worlds - you can use print statements and step debugging, together, at any point in time in the recording.
I actually recently implemented a POC version of support for the Redux DevTools in our Replay debugging app, so that if you do record a Redux app (or Jotai, or Zustand, or NgRx), you can use that same Redux DevTools UI to see the action history.
So, yes, time travel debugging _is_ an amazingly powerful concept. It's just ironic that that particular aspect of Redux didn't end up getting used that much... but the Redux DevTools themselves are still valuable, and Replay is actually a far superior "time travel debugger" overall.
-
pullstate
Simple state stores using immer and React hooks - re-use parts of your state by pulling it anywhere you like!
And automatically, any components using uiStateStore.useState and watching the isSidebarOpen property will get updated, exactly the same as the normal useState hook - just shared.
It's so dead simple and has made complex app-building so much easier for me.
The one caveat is that if I have a component with many handlers, e.g. onClick, onMouseMove, onContextMenu, onMouseLeave, etc (and in some cases I do), components can get bloated. I haven't found a fix to that yet. But that's more an inherent issue with react than anything to do with state management.
[1] https://github.com/lostpebble/pullstate
-
inertia
Inertia.js lets you quickly build modern single-page React, Vue and Svelte apps using classic server-side routing and controllers.
Or you just manage state in the server. With https://inertiajs.com/ you can even afford to not to declare an API and still manage the state back there.
-
Context and Redux are somewhat different tools and context doesn't necessarily solve the same problems as Redux. This article by the maintainer of Redux goes over why [0]. Have you tried Redux Toolkit as well? It cleans up a lot of the complexity of Redux and works well with TypeScript [1].
[0] https://blog.isquaredsoftware.com/2021/01/context-redux-diff...
[1] https://redux-toolkit.js.org/
-
This is why I'm building Joystick: https://github.com/cheatcode/joystick.
It riffs on the old, simple APIs of React but uses pure HTML, CSS, and JavaScript w/o any trickery (I'm also hardcore about not changing the component API so WYSIWYG).
The bonus is that it's a part of a full-stack framework (the UI framework has a Node.js counterpart), so wiring up a full app is near-effortless.
-
SaaSHub
SaaSHub - Software Alternatives and Reviews. SaaSHub helps you find the best software and product alternatives
-
We have docs on code splitting reducers and other Redux logic here:
- https://redux.js.org/usage/code-splitting
There have been some different community packages for helping with that process, but some of them seem to have become outdated (only worked with React-Redux v5, etc). I did see a new one at https://github.com/fostyfost/redux-eggs that seemed like it had potential, but I haven't had a chance to try any of them myself.
I also once saw someone play around with the idea of using React's still-not-technically-final Suspense support to help ensure that a lazy-loaded component that relies on a code-split reducer doesn't actually get rendered until that reducer's state is available. Don't have the link handy atm, but if someone wants it ping me and I can go figure out where that was described.
Also, the new RTK "listener" middleware was specifically designed to replace almost all saga usages, and you can dynamically add more listeners at runtime via dispatch an `addListener()` action:
- https://redux-toolkit.js.org/api/createListenerMiddleware
- https://blog.isquaredsoftware.com/2022/05/presentations-evol...
-
redux-xstate-poc
Discontinued Manage your Redux side effects with XState. Use 100% of XState's features.
Fun fact: one of the XState devs did a proof-of-concept showing how to use XState state machines as Redux reducers and integrate the side effects handling as a middleware:
https://github.com/mattpocock/redux-xstate-poc
We'd like to work together to turn that into a more official integration sometime soon.
-
Plain english translation: https://github.com/reidjs/grug-dev-translation
I haven't read it, but wish I had seen it before struggling through the original
-
For anyone who has not had the pleasure of working with these simpler “atom-based” state management libraries, I would implore you to try Jotai (https://jotai.org/), which is mentioned in the article.
Jotai’s atomic model and ease of use has completely changed the ease of writing complex React applications for me.
-
Yeah, _please_ don't use `typesafe-actions` :)
It may have had some value before RTK came out, but a lot of the opinions and approaches shown in its docs lead you to write _wayyyy_ too much code. For example, we specifically recommend _against_ writing TS unions for action object types [0].
RTK completely obsoletes `typesafe-actions`, and the TS usage patterns that we teach today should result in a pretty minimal set of types that you need to write in your own code.
For a small example see the RTK+TS template for Create-React-App [1]. If you want to see what a real app codebase can look like, the client app for my day job at Replay.io is OSS [2]. It's admittedly a somewhat messy codebase due to its long evolution and legacy (started as the FF DevTools codebase, copy-pasted, and we've been slowly migrating to RTK+TS and modernizing it), but files like [3] show how I would write a real slice reducer with RTK+TS.
[0] https://redux.js.org/usage/usage-with-typescript#avoid-actio...
[1] https://github.com/reduxjs/cra-template-redux-typescript
[2] https://github.com/replayio/devtools
[3] https://github.com/replayio/devtools/blob/454804188d33900a26...
-
-
I use Zustand with Next.js. What is the issue? There are even officially maintained examples by Next:
https://github.com/vercel/next.js/tree/deprecated-main/examp...
-
redux-easy-mode
A very easy to understand and use set of tools for Redux. Includes action builders, reducer builders, side-effect middleware, and async actions.
Have you considered something like "selector based side effects"? https://github.com/mikew/redux-easy-mode#selector-based-side.... The difference is most side effects are based around when an action is dispatched, but I wanted to know when things _change_.
It's possible to do the same thing with a react component + useEffect, but I thought a pure-redux solution would better fit the spirit of Redux.
-
Frankly I feel state management is a difficult task on desktop apps as well, to the point that tracking spaghetti-shaped causation and control flow is beyond my mental abilities. Qt itself as well as many apps are rife with redundantly calculating state or redrawing GUIs when changing the same value multiple times, or changing two values which both affect an outcome (my StateTransaction pattern mostly alleviates this issue with a set of dirty bitflags and recomputing all state dependent on those bits, though the reactivity system is currently hard-coded and statically dispatched, and generalizes poorly to open-ended state or managing the local state of many dialogs of the same type). And one of the craziest errors caused by witnessing malformed intermediate values is https://github.com/Dn-Programming-Core-Management/Dn-FamiTra..., where a sloppily-written "load document" function redrew the UI in the middle of mutating document state, causing the GUI to crash after observing a broken invariant.
It saddens me that so much of research in developing better state management techniques is in such a bloated and dependency-laden environment as JavaScript on the web. I like QML's reactivity system, but its evaluation engine is JS-based, dynamically-typed, and dynamically-scoped, and the UI engine itself is a buggy mess. And GTK4's list APIs promise to be better than the clusterfuck of Qt Widgets/Quick's QAbstractItem{Model/View} system (which abstracts poorly over list/column/tree collections, and widget-internal, cross-widget, and cross-application drag-and-drop), but I haven't tried that either.
-
Frankly I feel state management is a difficult task on desktop apps as well, to the point that tracking spaghetti-shaped causation and control flow is beyond my mental abilities. Qt itself as well as many apps are rife with redundantly calculating state or redrawing GUIs when changing the same value multiple times, or changing two values which both affect an outcome (my StateTransaction pattern mostly alleviates this issue with a set of dirty bitflags and recomputing all state dependent on those bits, though the reactivity system is currently hard-coded and statically dispatched, and generalizes poorly to open-ended state or managing the local state of many dialogs of the same type). And one of the craziest errors caused by witnessing malformed intermediate values is https://github.com/Dn-Programming-Core-Management/Dn-FamiTra..., where a sloppily-written "load document" function redrew the UI in the middle of mutating document state, causing the GUI to crash after observing a broken invariant.
It saddens me that so much of research in developing better state management techniques is in such a bloated and dependency-laden environment as JavaScript on the web. I like QML's reactivity system, but its evaluation engine is JS-based, dynamically-typed, and dynamically-scoped, and the UI engine itself is a buggy mess. And GTK4's list APIs promise to be better than the clusterfuck of Qt Widgets/Quick's QAbstractItem{Model/View} system (which abstracts poorly over list/column/tree collections, and widget-internal, cross-widget, and cross-application drag-and-drop), but I haven't tried that either.
-
> poor support for style libraries like tailwind
Can't relate. Tailwind works fine with anything that supports PostCSS. I run it with Vite and there's zero issues.
> the state management ecosystem is fractured between vuex and pinia
This is also just not true. Pinia is officially replacing Vuex as the recommended store library for Vue [1]. They're also vastly similar in how they do things, so the knowledge transfer over from Vuex to Pinia. And Pinia just address most of the design goals mentioned in the article in the most simple way.
As for Vue 2 -> 3 transition, lots of the larger UI frameworks in the ecosystem is struggling to migrate, despite lots of efforts on the compat layer to smooth the transition, which is a bummer. But as long as you're not doing those sophisticated things, Vue 2 examples should work out-of-box on Vue 3 as well. There are surely less resources for the composition API, but the official introduction guide has been good enough in my experience.
[1]: https://vuex.vuejs.org/#what-is-vuex
-
> As for Vue 2 -> 3 transition, lots of the larger UI frameworks in the ecosystem is struggling to migrate, despite lots of efforts on the compat layer to smooth the transition, which is a bummer.
I actually recently looked into most of the frameworks out there and their migration efforts.
So far, I only found three viable options for Vue 3:
- PrimeVue https://www.primefaces.org/primevue/
-
SaaSHub
SaaSHub - Software Alternatives and Reviews. SaaSHub helps you find the best software and product alternatives