Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> For massive apps with 1,000 components on the same page, maybe React's complexity is justified. But what the other 99% of apps?

The number of components is not the only yardstick of complexity. Most of the complexity in building a UI comes from state management and how state changes are propagated across the store and the UI.

I worked with Backbone for many years, and I can distinctly recall the hours of frustration I had debugging a UI because it was freezing due to cascading state changes. That was because we were using Backbone Store, which had bidirectional data flow, and when one updated the store, it would trigger a change to the UI, which would change the state store, which would change the UI, etc.

You could argue that the real innovation of React was "unidirectional data flow," but React team made Flux architecture central to the framework, making it easier to adopt good practices, whereas Backbone remained store agnostic and even encouraged Backbone Store which used the observer pattern for many years. I think you should choose a framework that allows you to fall into the Pit of Success, and React was that framework at the time, and for my money, it still is.



People don’t or even can’t remember how was front end development before React/Flux/Redux. You could easily had problems with state management even with less than 1000 LOC simple pages. Of course, you could mitigate it, but it wasn’t trivial at all.


Look, I wrote one of the only published books on Backbone, and it will always have a special place in my heart, but ... the OP has no idea what he is talking about.

Backbone employed a two-way data binding flow. You're responsible for updating the models (ie. state) (way #1) when the user triggers events, AND you are responsible for updating the DOM whenever the models (ie. state) changes (way #2).

In React, they used a revolutionary new paradigm (flux), making it so you only worry about one direction (updating the models/state in response to events); you never render anything (React renders everything for you in response to state changes)!

If you've tried developing a non-trivial site with both, it quickly becomes apparent how much that one difference completely simplifies a huge aspect of development.


so we need a state manager which also updates dom automatically. is there such a thing?

This is off topic but I need to ask you to stop breaking the site guidelines. You've been doing it repeatedly lately (not in the current case—present comment is fine), and we end up banning such accounts.

If you'd please review https://news.ycombinator.com/newsguidelines.html and stick to the rules when posting here, we'd appreciate it. We've asked you at least once before: https://news.ycombinator.com/item?id=36796345.


Thanks dang, i'll do better.

I remember watching one of the first React demonstrations/talks, and the biggest selling point was literally "You have a web page with various elements, and some of them needs to keep in sync, at Facebook we have chat messages and notifications, and they need to be in sync regardless of where you are, even on the same page, how do you solve that?" and then outlined how having one place for the state to live solves that issue without resorting to two-way data-bindings, instead data only flows in one direction.

Not sure if React isn't being presented as such anymore, but that's still the problem I see React solving, not more, not less.


Yeah I would argue that it's possible to do it well with Backbone, and you end up with something much leaner but it requires a really strong understanding of state/event flow and lot of discipline, whereas with React the correct way to handle this is the 'obvious' path, which dramatically lowers the barrier to entry.


And now everyone has phantom unreads again because it is cyclical and a different team is in charge of every other div


You just need 2 components with bidirectional binding to enter a world of hurt.

As you say many people do not understand how important, vital and bizarrely _non-obvious_ uni directional data flow was.


Everything was so hard. Everything! Backbone was kinda fun to write though, I'll admit. But not fun at scale to manage.


Author here.

I appreciate the point about unidirectional data flow solving real problems, but I think we're trading one complexity for another rather than actually simplifying things.

Yes, cascading state changes with Backbone Store were frustrating to debug. But React's abstractions introduce their own set of equally frustrating problems: stale closures where your click handler sees old state, infinite useEffect loops because an object in the dependency array gets recreated every render, mysterious input clearing because a key changed from stable to index-based.

The difference is that Backbone's problems were explicit and visible. When something broke, you could trace the event handlers, see what fired when, and understand the flow. The complexity was in your face, which made it debuggable.

React's problems are hidden behind abstraction layers.

I'm not saying React doesn't solve problems. I'm questioning whether those solutions are appropriate for the 99% of apps that aren't Facebook-scale. Sometimes the explicit, verbose approach is actually easier to reason about in the long run.


Yes, applying compositional patterns and one-way data flow is most appropriate for all apps, independent of scale. Why? Because developer A (author of app x) leaves company. Developer B gets hired. Developer B is onboarded in an afternoon because things can be understood at a glance thanks to functional patterns and one-way data flow.

Having built many large-scale Backbone apps, anytime someone new came on board it was really very, very difficult, no matter how many design patterns one applied.

React's innovation was making FP mainstream. And then teaching the value of simplicity, as a principle. And yah, if something broke, it might be a little opaque, but at scale and in general, things broke _way less often_.

This is also the reason why most devs are full-stack now. Back in the day backend devs wouldn't dare touch FE code, and now its "not so bad", and pretty much anyone can work all over the stack.


Those problems of react are only react's problems. Other js framework like vue/svelte/solid do not suffer from them.

You can use other frameworks for the other 1% of apps


>which had bidirectional data flow, and when one updated the store, it would trigger a change to the UI, which would change the state store, which would change the UI, etc.

You can hit the same problem with React. Circular state updates. State change->trigger useEffect->change state. I hit those when I had just started React.


You can, but it's harder, React will at least nudge you away from doing that.


> You could argue that the real innovation of React was "unidirectional data flow"

Isn't this just how the DOM works? Data flows down through attributes and properties; events bubble up?

> but React team made Flow architecture central to the framework

Didn't they call it Flux rather than Flow?


The native DOM doesn’t have an idea of “data flow”, it’s just a big tree that you can modify in whatever way you see fit through its imperative API. For example you could add an event handler to a child node which directly modifies one of its ancestor nodes. With React, your “nodes” in the tree are functions. The child node has no idea about what its ancestors are, it only knows what it is passed as arguments (i.e. “props”). The only way implement a similar thing would be to raise the state/event handling code to the ancestor node, and passing relevant information down as props, thus giving the unidirectional data flow. Of course, if you really needed to, you could drop back down to the native DOM API, with React’s useRef and useEffect hooks, but the default behavior is this unidirectional data flow through function composition.


> Isn't this just how the DOM works? Data flows down through attributes and properties; events bubble up?

That's right, but this communication pattern causes serious complexity. Imagine trying to find out what triggered a state change. You would have to listen to every event source to find out. With Flux, all state changes were mediated by the reducer in the store. It made things a lot simpler.


Shouldn't a state change should be purely event driven, and not dispatch its own events as side effect? That avoids reetrancy and is an easy rule to adopt...? Or am I misunderstanding the issue?


You're right about that, but that wasn't common practice at the time. We learned about side-effects from Elm and Flux.


> Didn't they call it Flux rather than Flow?

Ah, you may be right. It's been a long time.


Flow was a type checker (used to be Typescript vs. Flow debates early on before Typescript ended up with more support), Flux was the unidirectional data flow architecture.


There is no notion of components in the DOM (or at least there wasn’t, until after React), so there’s no sense of data flow.

There is a DOM tree, but parents don’t pass data into or receive events from children.


Components are themselves a form of added complexity. The idea is to deliver a composed and self contained code island. To accomplish this you have a big ball of markup, presentation, event handling, business logic description, and then security and accessibility logic to compensate for the prior mentioned abstractions. What you see in your editor may not look like much, but just under the hood is a colossal mountain of foolishness.

Why do people prefer this? It doesn't increase speed of maintenance. Its preferred because its composable to a predefined architecture scheme the developer is comfortable with. That's it. Its just about comfort, but the complexity is through the roof.

Simple isn't free.


From what you're saying, it sounds like components in this framework (React?) are not simple at all. A major hurdle in evolving a program is capturing and maintaining simplicity. The proof of whether something is simple lies in its composability, readability, and so on. If someone claims to have found a method of writing simple components, do not believe them if the simplicity is not evident. A truly simple solution would not be so burdened, and a somewhat simpler solution would be less burdened. Of course, simple still doesn't mean easy, because the Fast Fourier Transform may be simple, but I can't teach it to a 5 year old (or anyone, really).

Never religiously cling to statements such as "strictly separate presentation and content". These are all just guidelines to suggest simpler solutions, not hard rules that guarantee simplicity. They will sometimes be excepted.

There are such things as components, which compose strictly by interfaces and externalize separate details, but it is up to the programmers to realize them in their programs. Also, simplicity is a global property of a system. Nothing can be judged on simplicity in a vacuum.

All that being said, I don't have experience in web or UI in particular. Seems like logic is moreso a local thing, whereas presentation is moreso global (but may consider locally defined advice). State can be local or global.


You are mixing your terms. Complexity is another word for many. As such it is measurable objectively. The opposite, simplicity, means fewer.

Readability is highly subjective. At this point you are talking about what is easier for you. Easiness is not simplicity. Simplicity, in almost all cases, requires addition effort and that is not easy.


I did say that simple doesn't mean easy. I don't know how to judge whether something is many or few without a fixed norm, nor how to measure it without reference to the environment it exists within. Simplicity does not mean having so little to the point of unease.

"Everything should be as simple as possible, but not simpler"

- Einstein (probably[0])

Brainfuck is a simple language. A Brainfuck program written to parity with an existing non-Brainfuck program is likely complex. A musical note is simple, but a musical score may be highly complex.

I think your objections are misplaced.

[0] https://quoteinvestigator.com/2011/05/13/einstein-simple/


Composability is really valuable; you don't get bogged down in interconnectivity when your application gets really big.

You pay for it for smaller stuff, though, since that multiplicative coefficient is high.


I don’t have that problem with large vanilla projects. It’s just a matter of organization and this is supremely straightforward when making heavy use of TypeScript interfaces to define that organization.


I’m not sure i could disagree more with a statement.

Reacts innovation is simple: view is a function of state.

Before that we had to construct the ui imperatively where we managed state AND ui transitions to state changes. Now we mostly just focus on rendering a ui based on the snapshot of state we have. It is revolutionary (for ui dev), it is scalable, it is the reason why react STILL dominates the ui landscape.

React isn’t just popular because it’s familiar, that might be a component, but it ignores the historical and technological achievement it created


To be precise, React was the first (afaik) to apply that to web UI, but definitely not the first to apply that to UI in general.

The basic idea of a unidirectional loop is how video games were built for years before React.


I have had other people tell me this because they perceived state management as a challenging problem to solve. That is true of the big frameworks, but otherwise state management is a ridiculously straightforward problem easily solved.


React came to be because folks at Facabook couldn't get the label displaying unread notifications always to display correct value. This seems like ridiculously straightforward problem easily solved. Yet still many websites and applications today struggle with that.


I'm getting downvoted into oblivion but you can hear it from horse's mouth:

https://youtu.be/nYkdrAPrdcw?t=757


I stopped watching the moment the speaker correlated imperative code to fragility. All code is inherently fragile. The only thing that makes code durable is not failing. Failure can be minimized by separating code into portable units that do nothing more than achieve a singular purpose.

Secondly, they kept talking about this creeping complexity in their code base of about 8 lines of code. 8 lines is still ridiculously tiny. I suspect their actual concern is that the code did multiple things like decrementing a number and modifying a state. I understand this was before TypeScript where execution can be planned against an interface, but I still would have created an object that stores all the relevant data they need to modify on each interaction.


Apparently you are smarter than the team that created the library that spontaneously taken over nearly entire field of front-end development. Good for you!


Probably. I have been doing this for a while.

Its like comparing your car to a Kia Soul as opposed to a Bugatti or McLaren. It not a comparison of what's awesome. Its a comparison against that thing in common use. It doesn't take much to be better than that.


In case you want additional information about who was responsible and what were their motivations, competence and experience here's a documentary:

https://youtu.be/8pDqJVdNa44?si=kEhofuwlthON62xz


I did angular for many years and just recently came back to doing frontend work for a recent project. This is my experience with react, its not perfect and there are a few react-isms to learn, but it tends to make you do the right thing.


At one point I also moved from Angular to React, after moving from Backbone to Angular, and from "just" jQuery + jQuery UI to Backbone. After moving to React, I haven't found the need to move to something else, most of the alternatives are marginal improvements, while the difference before and after React is pretty drastic.


> For massive apps with 1,000 components on the same page

If have a 40X25 table on your page that's editable, that's your 1,000 components right there. But away from tables, it does seem overkill to have 1,000+ components on a single page.


1,000 components is my standard test for trying out a new UI library.

I recently tried it with Kotlin/Compose. Turned out that everything becomes noticeably slower with so many components, even if the components are in a scroll view and only a few of them are visible.


Displaying so many would require virtualization. No one is going to see a myriad of components all at once anyway. The slowing down part might be eager computations in partially optimized implementations.

The same way we use pagination on the web, or lazy loading, etc...

But I guess the question is whether that should be a default...


Maybe but it sounds like bad excuses.

There are a myriad of examples anyone can come up with that require a UI library to simply be fast. For example, perhaps someone wants to implement minesweeper with checkboxes. Or build an "infinite" feed, or a settings panel showing thousands of settings of a system where you can filter with a filter box, etc., etc. You can argue against all of these cases, or you can simply rely on a fast UI library and be done with it.


1000 component should be trivial for a framework in 2025 without virtualization.


Hmmh...

Warning: Lighthouse issues a warning when the page's <body> element has more than ~800 nodes (elements).

Error: Lighthouse reports an error when the <body> element has more than ~1,400 nodes.

Other Related Lighthouse Warnings Lighthouse also flags two other related issues, which often contribute to a large DOM:

Maximum DOM Depth: It warns if your DOM tree has a nesting depth greater than 32 levels.

Maximum Child Elements: It warns if any single parent element has more than 60 direct children.

The general recommendation for optimal performance is to keep your page's total DOM node count below 1,500.

source: https://web.dev/articles/dom-size-and-interactivity

These are "NODES", not even components as you say...


That's because a webpage should render properly on __all__ browsers.

You don't have this problem with UI libraries because all users will run the same library.


?


1,000 is a lot, but not uncommon for a CRUD app. Especially when you start with a small one and the scope creeps. Users want one more feature, and one more field. Then it's time to replace some other CRUD app and you've already got this one going ...


> If have a 40X25 table on your page that's editable, that's your 1,000 components right there.

Why would you do it like that?! Just have a normal component for a table, and when the clicks on a cell, spawn (and teleport) an edit component over that cell.


Also can we stop pretending React is any more "complex" than any other rendering library. You can't get much simpler than () => <div>Hello, World</div>


What makes React complex is that your simple example pulls in 100KB of code and entire layers like the virtual DOM which increase the memory and CPU requirements while adding significant new concepts a developer has to learn to be productive.

That’s not to say that there aren’t benefits from that but it’s definitely extra complexity compared to using web standards.


A single picture is going to be more than 100kb.

Meanwhile, there simply aren’t web standards that match React’s capabilities.


Pictures get encoded and decoded by browsers much much faster than the ability to parse then execute javascript.


You don’t need to know how JPEG or AVIF work internally to use an <img> tag.

> Meanwhile, there simply aren’t web standards that match React’s capabilities.

This isn't true for much of the web but it’s more deeply missing the point: if you’re building a web app, you need to learn the web APIs because those are what all web apps actually use. Adding intermediaries means that you have more things to learn, troubleshoot, and optimize. React’s value comes from managing the complexity of the code you write, which can be a real benefit for some projects but it doesn’t remove the need for you to know how browsers work.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: