It's great that there are alternatives to React, and that they do some things better than it. But what I find is that most large, complex applications I've worked on are not in particular hindered by the choice of React as a technology. It does vary from project to project too, of course - some applications will benefit more from some kind of well designed central state management solution.
AKA, React is accidental complexity. Solving accidental complexity issues may be required some time, but more often than not, it's just something you endure as the alternative choices are not that much better.
State management and optimized DOM manipulation can be achieved with vanillajs nowadays and I'm not saying that as a purist, it is just good enough that React is not needed. To help a bit with the ergonomics, I use lit-html/uhtml for the templating but they are both based on template literals, a native JS feature.
The essential complexity was the interactive need of your UI. Any of the current web framework can be a solution. The only reason to go for React is hireability (almost anyone knows it) and devex (so many prebuilt components). But it's not like that the others are so hard to learn and components are hard to build.
> and devex.
Indeed, devex is the strong point of react. See this thread: https://news.ycombinator.com/item?id=43770579 > But it's not like that components are hard to build.
I really want to like other frameworks, but if I'd have to build a MUI(x) by hand, I'll accidentally pivot our business model to "component library maker" as a result.I think we need to be clear about what scope we are talking about. A full fledged data-heavy B2B application, or something simpler like a web shop?
I think the new memo compiler address' this in the most complicated way possible.
Wow that's really bad and make it basically useless.
I still think Zustand is the simplest state management, while staying efficient. It's similar to the old Svelte stores. But I have used many state management tools and the re-renders were not the problem when it came to speed.
function MyProvider({ children }) {
const [value, setValue] = useState()
return <Context.Provider value={value}>
{children}
</Context.Provider>
}
In the above example, the Provider re-renders, but it's children remain unchanged.Jotai, mentioned briefly in the article, may not be built in but is as intuitive as signals get and isn’t even tied to React as of later versions.
I’ve very rarely met a state management problem in clientside state management where neither tanstack query (for io related state) nor jotai (for everything else) are the best answer technically speaking. The rare exceptions are usually best served by xstate if you want to model things with FSMs or with zustand if you actually need a reducer pattern. There’s a tiny niche where redux makes sense (you want to log all state transitions or use rewind or are heavily leaning on its devtools) but it was the first to get popular and retains relevance due to the fact that everyone has used it.
You can go a long way with useContext and useReducer/useState but few would opt for alternatives if jotai came batteries included with react.
There's nothing stopping people from using these atom-based libraries to build more robust abstractions, but from my professional experience I tend to just see global getters and setters with useEffects / lifecycle method of your frameworks choice as a side effect sync.
Maybe my instincts are off here though and I am overly cautious. I love XState but the learning curve is rather massive and getting buy in from other team members is hard when the DX of the atom approach is so nice.
I feel like state "management" and reactivity performance are talked about a lot, when ultimately state orchestration is where I see things fall over the most.
I’ve seen far larger messes created in redux due to tight coupling of things across large apps to a global store and the inability to work with things like Maps and Sets or other values that are not trivially JSON serializable.
In the other direction I have seen messes with observable-based state management systems where things become far more complex and too far abstracted (how often do you really care about anything other than the latest value and maybe the previous one?) or with proxy based systems that have too much fragile magic (valtio, mobx) or require wrapping your components and going all in on oop (mobx)
To me signals hit the magic spot of reactive without being overkill and keep code testable in smaller units while retaining performance benefits of surgical updates
I like xstate in theory — it’s a good way to think about complex state transitions — but in at least half of cases in practice where you aren’t interested in a derived value, someone is storing a value/ getting the latest value or toggling a boolean and it’s just such overkill for that. The reducer pattern itself doesn’t meaningfully show up much for similar reasons. The other common cases are with fetching states (idle, loading, refetching, success, error) but you often end up wanting things like cache management or maybe even optimistic updates so eventually tanstack query covers that ground better than rolling your own.
I also like the approach of Svelte, and realize that sometimes a full state machine isn't needed. I don't think that atoms should be used everywhere, since updating state freely without guardrails just leads to disaster long-term.
React could be argued to have abandoned the fight for being the best client side framework technically (though they have dominance pragmatically). They are really all focused on Vercel’s Nextjs/SSR/SSG/RSC stuff in recent years
Signals recently became more popular as people observed the performance and DX that they made possible in SolidJS. Solid's creator, Ryan Carniato, has acted as a bit of an evangelist for them-- even working closely with the Angular team.
"Preact, Qwik, Svelte, and Angular all quickly followed suit and unlocked huge performance benefits."
> The current draft is based on design input from the authors/maintainers of Angular, Bubble, Ember, FAST, MobX, Preact, Qwik, RxJS, Solid, Starbeam, Svelte, Vue, Wiz, and more…
What other voices would you like to get feedback from?
I think this might be true short term, but long term it means Svelte has more room to evolve with the web and with JavaScript itself, since fewer users means more room to move fast and break things, like Zig can and does. And Zig isn't dead.
This gives me a little encouragement for my personal web reactivity project. I'm confident I came up with a reactivity model that's technically innovative, which does and is what I always wanted React to do and be. But being so late to the game, my hypothetical framework has no chance to gain traction. I say hypothetical because I haven't even started making it yet. It would be built on the Ref class[1] that came out of my experimental work on os.90s.dev, but only last night did I finally get around to experimenting with using it with HTML[2].
The concept is to have JSX transform to allowing attributes to be given MaybeRefs and if its a ref then watch it and set the attr to the value, and just return the HTMLElement itself. This should be a good enough foundation to build an entire reactive framework around.
Having almost no users is a blessing, because it gives me the complete freedom to experiment with this relatively slowly. The time between creating refs and stabilizing them was a few months. The time between stabilizing them and using them in that experiment was another month. It'll probably be another month before I get a functioning non-trivial app working with it. And another few months before it's cleaned up enough to be both generic and convenient.
Maybe this should have been a blog post. I never know.
[1]: https://90s.dev/guides/refs.html
[2]: https://github.com/sdegutis/bubbles/commit/cde2bea973b22538f...
That is essentially what Signals are, including directly setting .textContent when possible.
This model actually predates all of this and was used way back, in Backbone.js and other pre-react frameworks, except we didn’t have JSX or virtual DOM at the time.
const el = document.createElement(tag)
for (const [k, v] of Object.entries(attrs)) {
if (v instanceof Ref) {
el [k] = v.val
v.watch(val => el[k] = val)
}
else {
el[k] = v
}
}
As someone else mentioned in this thread, the main innovation in the React era was actually it's sister library Flux which brought the idea of a unidirectional data flow into the picture, later inspiring Redux et al. We are now getting past the immutability detour and keeping the best of both worlds, maybe.
That being said, Svelte absolutely does continue to innovate. We'll be introducing a new async primitive, RPC mechanism, etc. in the near future: https://m.youtube.com/watch?v=1dATE70wlHc
This is coming from someone who is no way a front end dev, but svelte 5 in particular is just so easy to get started with and has the most sane approach to reactivity and syntax compared to the other frameworks I have tried, and it seems like it is in the best position to grow with the web as well.
So I will stop trying to be like them. I can't.
I'll just keep my head down and write my little apps for fun.
// Create new Ref
const r = van.state(0)
// derive functions as adapt/watch/multiplex.
// Implicitly depends on any Ref it uses and re-runs when they change.
const r2 = van.derive(() => 2 * r.val)
van.derive(() => console.log('r2 is ' + r2.val))
// Changing the value doesn't update r2 or print immediately, it schedules
// a batch update when all derives will get recomputed.
r.val = 3
// ...So 'r2 is 6' won't be printed here.
r.val++
// Refs can be used in a hyperscript-style DOM builder.
// This creates a regular HTMLElement, with a regular Text node where r2 goes,
// but it holds onto that Text node behind the scenes and automatically
// updates it when r2 changes.
const {p} = van.tags
document.appendChild(p("The value is ", r2))
There are enough web frameworks. If you make a blog post where you state what limits you have with the current state of web technology, and you describe it really well, I’m sure someone will be able to point out how there is a web framework that deals with that. Or a way to implement that in current web frameworks.
Pinia is so low ceremony and "just works"; it makes state management concerns practically disappear.
That's the best kind of simple.
and its not elegant, lets call it that way
I call it "nation state" because it groups sets of related variables together in a scope between local and global.
I implemented the pattern with Svelte runes, but I think it could be implemented with anything; even React.
I went into more detail here (with live example/code): https://www.reddit.com/r/sveltejs/comments/1dgf8la/comment/l...
Might be an anti pattern but it works really well.
Yeah sadly the stores the author talks about here aren't the right way to do things anymore in modern svelte and they're all-in on Runes.
Stores were a big part of the reason I liked svelte; they were so conceptually simple, extensible with plain JS, and made interop outside of Svelte trivial without the Svelte magic leaking out.
They're still in Svelte, but they mix poorly with runes and are basically unsupported in runes mode. I opened up a bug about store behavior not working like it used to when mixing with runes, and the response was pretty much "yeah we don't expect it to work like that anymore when runes mode is enabled".
svelte has earned it's place and the more people use it - the better. I couldn't find a reason to switch, same with ember in early days, same with any handlebars go/php/rust etc. We live in the era when it's enough to learn one UI framework and just ship things.
Good post though, I wish it had more examples so
There’s an arcane layer of $yntax to mediate and a lot of flexibility and intuition is lost as a result.
voby.js looks neat
“When to use stores
Prior to Svelte 5, stores were the go-to solution for creating cross-component reactive states or extracting logic. With runes, these use cases have greatly diminished.
when extracting logic, it’s better to take advantage of runes’ universal reactivity: You can use runes outside the top level of components and even place them into JavaScript or TypeScript files (using a .svelte.js or .svelte.ts file ending) when creating shared state, you can create a $state object containing the values you need and then manipulate said state state.svelte
export const userState = $state({ name: 'name', /* ... */ }); App
<script lang="ts"> import { userState } from './state.svelte.js'; </script>
<p>User name: {userState.name}</p> <button onclick={() => { userState.name = 'new name'; }}> change name </button>
Stores are still a good solution when you have complex asynchronous data streams or it’s important to have more manual control over updating values or listening to changes. If you’re familiar with RxJs and want to reuse that knowledge, the $ also comes in handy for you.”
Those two examples aren't equivalent because any parent component wrapping the Svelte component doesn't have access to the state whilst App (in the React example) does.
For the Svelte example to be equivalent, the component would have to export the store.
A minor gripe but the hooks vs Svelte state is pretty minor issue in itself.
This is described in the Solid documentation: https://docs.solidjs.com/configuration/typescript#control-fl...
In my experience with data-binding, these instances of disabling the typesystem accumulated, and became a frequent source of bugs.
So even though I hope for Signals to catch on, I believe the best way of connection to them will still be React:
function Output({ userSignal }) {
const user = useSignal(userSignal)
if (!user) return <span>No user found</span>
return <span>{user.firstName} {user.lastName}</span> /* TypeScript knows that user must be defined */
}
rendall•1d ago
> I like Svelte more than React (its store management)
bravesoul2•1d ago
Easy mnemomic: the apostrophe is for a missing letter, I.
okonomiyaki3000•1d ago
bsaul•1d ago
zamadatix•1d ago
The same goes for "alot", avoiding the use of "whom", and so on - I ain't gonna give up on them!
elpocko•1d ago
billforsternz•1d ago
tln•1d ago
Honestly I don't love HN's title edits. Why can't we have nice blog titles that start with why?