Hacker News new | past | comments | ask | show | jobs | submit login
React I love you, but you're bringing me down (marmelab.com)
696 points by fzaninotto on Sept 20, 2022 | hide | past | favorite | 557 comments



I've worked in a few roughly-the-same-size (~50 engineers) web development shops. It's always the same. Doesn't matter if it's React, Angular, Class based components, Functional components with hooks, Just Some HTML, PHP, Rails views, etc.

The frontend just collects the cruft of a product organization changing course very frequently. There are always a dozen half-finished fix-the-world ideas conflicting with each other, half-finished move-to-new-framework initiatives.

I just mean to say that when I hear "it's because React" or "it's because rails views", any other of the infinite variations of this, I kind of just tune out. Some part of your organizations chaos is going to reflect in code, and honestly I'd rather it be in a big ball of frontend than in the data models, infrastructure, etc.


> Some part of your organizations chaos is going to reflect in code, and honestly I'd rather it be in a big ball of frontend than in the data models, infrastructure, etc.

I disagree. I like my frontend to be as dumb as possible. It gets data and reacts to it as simple as possible. Seen too many frontends with a lot of data logic and it becomes extremely brittle, harder to test.

These are the ones where the frontend devs are getting data from the API and creating new structures, transforming it, conditionals everywhere, etc.

It requires way more discipline to ensure that frontend devs aren't recreating the wheel and writing duplicate code as the app and components evolve, and it's worse for larger codebases of course.

They need to build some new component and go - ok I got the data from the API and now I need to do the thing that's already been done by another frontend dev for another component because we've allowed the frontend to be responsible for transforming the data. But if they aren't aware of this, then you get a lot of dupe code.

Just have your backend API provide the contract. Setup resources/transformers as needed on the backend instead of littering the frontend with that logic.


I primarily agree with you, but his primary point is mainly regarding the tendency for projects at large organizations to have a substantial number of unfished attempts to rework existing applications, which often results in serious headaches for whoever owns the code.

What I mean is that even if you've followed a specific set of programming principals, code practices and design patterns consistently across the life time of the application, there will still have been initiatives to change how things are done. Maybe they want to use a "better" authentication library, or add a material framework that has capabilities they need. The exact initiative, and how valid the request or decision is doesn't matter. These initiatives may occur one at a time, or be competing with each other for priority while being incompatible without anyone noticing. But some of them will fail to be completed, and someone has to back out the changes that shouldn't go to prod. Inevitably something will get left behind. Over 5-10 years this can have a shockingly large impact on the code base in ways engineers frequently notice but don't understand how the code got to the state its in.

This frequently means dead code, unused dependencies, comments that don't make any sense, properties on objects that are never displayed or referenced by business logic, and multiple classes/services which accept the same inputs and produce the same outputs but do the job just differently enough you can't be sure it's the same. That, and over abstractions (any piece of code which branches based on the context of "who's asking").

And frankly few things any me more than someone who felt the need to implement their own logging implementation, especially in C# (yes I know we're talking about React, but people do the same stupid crap in that case as well). Reinventing the wheel has to be done on occasion, but you need to ask yourself if it has to be you that makes it happen,and whether it already has been.


That's why I like GraphQL, you get exactly the data you request, no transformation necessary.


This is why I dislike graphql especially with react. It’s gets set up as a half assed ORM (but without joins!) and then all but the most senior of engineers end up using it as your application state which slows the whole app to crawl forcing a big rewrite.

Using an orm and building a proper data model in your code using a store like redis takes very little additional time (especially with sequelize!) and it has the benefit that your junior and mid level engineers understand where the underlying data is stored.


Yes I've also seen a bunch of these apps with extremely chatty graphql calls because it's so convenient!

One component just needs 2 pieces of data = graphql call. Another needs more data and they're doing another similar call. And so on. You got query flexibility but now you are drowning in additional network requests because it's so easy for your team to just "query for what they want".

To me, if your application doesn't need to have the flexibility in querying, then it isn't worth it. Is your dataset so large you don't wish to overfetch data (you can do that without graphql anyway)? Do you need ad-hoc querying in your UIs?

Think about your data, how you will need to expose it and expose it.


Seems you're not familiar with recent advances. GraphQL servers have the ability to collate requests together and only redo a query when data changes instead of "whenever they want" because the client and server know exactly what data is used for which component.

This video describes how this is done in Relay but it can exist in other servers too: https://www.youtube.com/watch?v=KT3XKDBZW7M


That doesn't prevent your frontend and components from making a ton of extra network requests because graphql makes it easy for frontend devs to do fire a new query for their component.

Simple example:

1. header component - dev queries user for first name to do a welcome message.

2. sidebar component - another dev does a query for first/last/avatar/profile/etc.

Your app sends 2 network calls. Certainly it doesn't have to, but I've seen this chattiness get implemented.

So you avoided overfetching of data like official REST APIs but now you have more network calls.


Yes, it does. As I explained, GraphQL servers can see which requests should be collated and deduplicated and puts them all into one request. For example, Relay:

> Relay combines the advantages of both of these approaches by allowing components to specify what data they require, but to coalesce those requirements into a single query that fetches the data for an entire subtree of components. In other words, it determines statically (i.e. before your application runs; at the time you write your code) the requirements for an entire view!

> This is achieved with the help of GraphQL. Functional components use one or more GraphQL fragments to describe their data requirements. These fragments are then nested within other fragments, and ultimately within queries. And when such a query is fetched, Relay will make a single network request for it and all of its nested fragments. In other words, the Relay runtime is then able to make a single network request for all of the data required by a view!

https://relay.dev/docs/principles-and-architecture/thinking-...


Ok but I'm talking about your client application sending multiple network calls at different times. How does the server prevent that? It doesn't.

In order to prevent the frontend from doing that, I have to be sure to enforce usage of another layer. Devs need to use fragments and relay and not just fire off their own ad-hoc graphql queries.

Which is interesting, and thanks for sharing. I would move toward implementing this on any graphql project, especially an inherited, network chatty graphql project.

But I still prefer keeping the frontend really dumb and just sending the data it needs, that has been identified.

Most of the time a REST or REST like API endpoint is sufficient, and it doesn't matter if you overfetch some data, you avoid extra graphql layers (now enforcing fragments/relay, extra resolvers, potential performance issues, multiple schemas and access concerns).

I like GraphQL but it seems like a lot of overhead for little gain for many projects. One project has 3 different graphql schemas. Can't be exposing the whole tree to every user type.

I can see why frontend devs would like it though (need this data, probably already available), but a REST or REST-like API is more enjoyable for me unless I'm building a framework or on top of a framework or a client that needs ultimate ad-hoc query ability where it really shines to me.


By that logic even a REST endpoint server can't stop people from making network calls at different times. How would you even stop that, simply make people wait until a set time before collating and sending out the data?


I don't see frontends using REST servers doing what I see with GraphQL.

UI using REST server tends to centralize the API client, call the endpoint(s), and make that available to all components.

UI using GraphQL often has frontend devs doing their components, running their ad-hoc queries for "just what they need". More network calls.

So overfetching like with REST tends to lead to less network calls unless you are extra diligent on a GraphQL project.


Not sure I understand because I use GraphQL with an ORM, Prisma with Postgres and Pothos which converts the Prisma schema into GraphQL types. It even has the ability to use Redis as a store. So we get all the features of an ORM and also typesafe queries.


Right my point is that

1. It incentivized using it as the data model which is both inefficient and lossy in regards to transactions.

2. what’s the purpose of graphql in this context? You have to use an ORM anyway with which you can do all delegations to servers etc your heart desires and with typescript you can ensure proper column types regardless. You can trivially autogenerate objects or any kind of descriptor from a database as well.

Seems to me people decided graphql was a perfect solution to nicely hit multiple data stores with the now added caveat that we have a worse query language that lacks joins to boot.

I’ve still yet to see an actual technical argument for why we should add another (less efficient) layer between the actual data stores and the ORM/Application DataModel.

Is it resolver logic between stores?


GraphQL is for the client to efficiently query data, it is not supposed to be used as a SQL replacement on the server side. If people are using it for a server side query language, that is not what its benefit is.


IIRC in the Gatsby framework it has a built-in GraphQL parser for server-side developers to query data from Gatsby plugins, which can be things like data stores, other APIs, or even a mixture and blended together.


In a way, that's using the server as a client for other servers, ie it would be the same as a server sending a REST request to another server asking for data. What I mean is nowhere should there be GraphQL between a server and a database, because that doesn't make any sense, just use an ORM.


How can the client most efficiently query data from a sql database without joins? Surely there are cases this would be needed to speedup grabbing of data?


Any ORM will handle getting data with joins just fine when it constructs the SQL. Or you can write your own SQL with joins to pass along to the query.

If you mean GraphQL doesn't have joins, I'm not sure in what use case that would matter when you're declaratively asking the server for some data, not hand constructing SQL. What would you need joins in? You mean like this example [0]?

[0] https://stackoverflow.com/questions/51805890/how-to-do-a-sim...


Right so, again, what exactly is the purpose of graphql?

It seems to be a replacement for an ORM that then needs an ORM. So it’s a replacement for passing JSON objects around except it’s just doing that with a dash of esotericism.

What can graphql do that an ORM can’t?


You're mixing up server side and client side. The point of GraphQL is to make a client request only what data it needs rather than making X different REST calls then combining and filtering them in the client side. That's it, that's the entire purpose. (If you then ask, why not have REST calls that give specific pieces of information, ie have sorts and filters within the query parameters, and be able to take a table and ask for specific columns in that table, then congratulations, you've reinvented GraphQL.)

You can then implement a server which, given a GraphQL query, turns it into the data that's expected. The client doesn't care how you implement that. You can write raw SQL, use an ORM, whatever. Since people don't want to reinvent the wheel they use libraries like Apollo Server, but again you can do it all by hand if you really want to.

Have you actually used GraphQL? This is all explained within the first 15 minutes of any GraphQL tutorial.


> If you then ask, why not have REST calls that give specific pieces of information, ie have sorts and filters within the query parameters, and be able to take a table and ask for specific columns in that table, then congratulations, you've reinvented GraphQL.

Obligatory note: this really is just supposed to be REST. GraphQL seems to be the final expression of throwing in the towel on REST's original capabilities.

As such it's not clear of it's a step forward (REST as it should be) or a step back (let's just use a crippled SQL and ship)


So if front-end devs get everything they need client side, what’s the point of having backend devs?

https://imgflip.com/i/6u4obk


SPAs and REST APIs moved a lot of the complexity around data to the client side. GraphQL moved it back to the server side. I think that's a reasonable decision, as the client - compared to the server - runs in a much more unpredictable environment. Of course some backend devs complain about more work, especially work that could be moved to the client side at first. Making things the proper way is hard, yes.


The pitch I remember back when it first was released was that GraphQL was meant for development, when the API was still changing a lot, and was supposed to be replaced with dedicated API calls before going to production. During development frontend devs has something flexible they could use without pestering the backend constantly, then the dedicated non-GraphQL production version would be stable and could be significantly more optimized than the GraphQL version.


The backend still needs to implement the endpoints for the frontend? Not sure what you mean, if anything the backend work increases because everything is done on the backend now.

And did you really link me to a meme you made specifically for this conversation?


True and I like GraphQL but in many cases your UI needs data in a way that isn't available on your existing endpoints. Ex: summary data / aggregations for reports or analytics. Or simple things like fullName on a user entity, a displayAddress, a display greeting based on their user group, you get the idea. You can do all of this on the frontend but it just becomes messier.

This is what I'm referring to.

So you still need to write some new graphql resolvers on the backend and update your graphql schema. Not much different from writing some new REST api endpoints or expanding an existing endpoint.

But if you use GraphQL then I agree on the benefit and approach still of having as much of your data logic on the backend. And with GraphQL you have a schema that is readily available, auto-documented and available for frontend devs to use for current and future components.

Which is better than having that logic on the frontend IMO.


Graphql fans will attempt to convince you the way you’re querying data is wrong. You can do triggers if needed but graphql to me seems like a solution to internal enterprise data wrangling ootb. I don’t see the benefit of using it over an orm when you add in multiple databases, a working data store, etc


Yeah I'm not entirely sold on GraphQL but I think it shines in some cases.

Ex: you are building on top of third party ecommerce software.

You need to add more data to the Cart entity because you have a custom module/plugin/etc. You write a graphql resolver, extend the schema and the Cart type. You can use the existing built-in endpoint to query your new data.

So it's nice to be able to extend a framework and data access in that manner.

In general though, I do prefer REST APIs and then writing custom endpoints if I need data for a specific UI, like for visualizations.


Parent is mixing up GraphQL and ORMs which serve two completely different purposes and doesn't seem to have actually used GraphQL. GraphQL is purely a way for a client to request some data instead of REST. How the backend serves that request is not any concern to the frontend, the backend can use an ORM or it can use raw SQL, or whatever else it wants.


Yes I think you are right; I wasn't following the ORM part either. I mean, you can return whatever you want so long as matches the schema. Hard code it, raw sql, whatever.

I wrote some custom resolvers yesterday to extend graphql on a Cart entity and it works well for that.

I used some existing repositories the backend already had but was not yet available on the GraphQL side.

All the resolvers can lead to extra performance issues of course, but I suppose you can adjust your schema as needed and tune it with more efficient queries or code (ex: move some properties to nested and resolve with a single tuned query)


GraphQL was designed to solve a singular problem, slow mobile internet speeds. Now that mobile internet (5G) is faster then some wired home connections I'm worried that GraphQL will die off. It's a solution that no longer has a problem. Though it is a cool tech.


I love GQL, but making things optional by default in the schema was the stupidest decision they could've made.

Also the issue with GQL is that FE devs love to copy+paste giant queries that just get everything because it's "convenient", or build up a query while building/testing something and then go on to use that query, including fields that don't eventually get used in the final work.

What GQL->consumer ecosystem really needs is something that can check if a field is ever actually accessed in the code or not, something TS/compilation-wise would work. That way the query can be narrowed down to what's actually used in code.


Graphql does not address the problem he's describing. When he says "transformation" his meaning is similar to transformation in an ETL process. What he means is the application loads data, the user takes an action, and the front end code handles updating the objects locally, then sends messages to the backend telling it what the new data state should be.

This is very dangerous behavior for any application. You don't want the front end to determine how much the shopping cart costs or to just tell the backend they've paid, therefore add the items to the orders list. Even if there isn't blatantly obvious security concerns, you should still never let your front end blindly determine data state changes. All such business logic belongs in the backend as much as possible.

What he's talking about is when business logic is split between the front and backend, which makes everything much harder to test on top of increasing the likelihood of duplicate code or even code which does the same thing but looks different enough to not be caught as duplication (which means changing business logic requires finding all the places it was implemented and changing them all, and if you miss any its unlikely anyone else will realize it until it hits prod).

The UI should always just be a shell that sends requests to a backend which determines which updates to make. There are exceptions like when a user makes form based changes to an object, but the only business logic in that case is "let the user decide what the value should be and persist that choice as is". If any additional changes may need to occur as a result of their change, your backend should make them. Even if you just need to determine if a change shouldn't be allowed because of related data, send a request to your backend requesting the answer and any relevant data necessary for display purposes, not the data necessary to make that determination.

There are exceptions to what I've said, but even in those cases, the backend should still verify whether the front end's result is correct. While the front end was working, a change could have gone through in the backend which invalidates that change. This is why things like concurrency/version tokens can be very important.

In any case, Graphql may have capabilities that look like they help keep business logic in the backend, but it doesn't stop programmers from putting business logic in the front end anyway. No matter how you try to look at it, spreading business logic out across your applications various layers always has unintended consequences for maintainability and even scalability.


> What he means is the application loads data, the user takes an action, and the front end code handles updating the objects locally, then sends messages to the backend telling it what the new data state should be.

But you don't have to do it like this at all. I don't understand what this has to do with GraphQL, you can make the frontend never update local state and only fetch from the server if you want. That's an implementation detail not related to GraphQL, REST, or any other API format.

> No matter how you try to look at it, spreading business logic out across your applications various layers always has unintended consequences for maintainability and even scalability.

I agree with you here, but for:

> In any case, Graphql may have capabilities that look like they help keep business logic in the backend, but it doesn't stop programmers from putting business logic in the front end anyway.

Again an implementation detail, if you're the tech lead, just tell your devs (or architect the app in such a way as to) not to put business logic into the frontend.


I wasn't referring to trusting the client's logic and state changes and then sending it back in an update and storing it. But certainly some devs do that.

As a simple example, you may send an entity to be updated and then the frontend makes a decision to say, you changed this value, then alter this other value so that the update request has the values we want (ie: one property may need to be blanked if another property has a certain value). Your frontend has logic it shouldn't and you should be enforcing your data on the backend anyway.

However, I was referring more to a situation where a frontend dev has an API request that it can work with but needs in another format or structure. And then logic is added to that data based on the user inputs or to simply do client side aggregations. Maybe it takes the user's chosen store location and filters out the out of stock products from the API on the client side.

Instead of sending the inputs to the API and have the API's logic handle it and provide you with the dumb data for your frontend to render - here are the products you should render; don't think about anything. So your frontend isn't growing into this brittle thing that is doing too much and is more likely to end up with dupe code as multiple frontend devs get tasked with new but similar components and recreate the wheel.

> In any case, Graphql may have capabilities that look like they help keep business logic in the backend, but it doesn't stop programmers from putting business logic in the front end anyway.

I'd argue that it in many cases it promotes frontend devs adding more business logic. Because your devs can query for whatever they want on the schema, transform the data, do whatever logic in the components instead of relying on an API contract for said data.

It means there's really no thought into: what does this client actually need?

So the frontend devs don't have to involve a backend dev or team to get most of their tasks done, which may be a great thing for their situation.

But the business logic gets pushed more and more into the frontend and gets bloated and brittle.


I believe what you're describing is called "Backend for fronted" (BFF)


Why? What's the difference?


You’re likely duplicating a lot of business logic between the frontend and backend. You can do it, but if you forgot to update one implementation, it could get ugly fast.


Backend doesn't need to deal with animations, styling, browser support, responsiveness, etc.


It really is hard to understate how damaging the half-finished ideas in the code base can be. To the point that I often prefer to stay on something I don't like, if I'm not positive I can finish moving completely off of it.


> It really is hard to understate how damaging the half-finished ideas in the code base can be.

People get promoted for all the shiny new things they do, not for the discipline they show in only focusing on what really matters.


> People get promoted for all the shiny new things they do, not for the discipline they show in only focusing on what really matters.

Depends on the company and its values. I've been in companies where engineers who don't care about the business/customers were promoted by other engineers who don't care about the business/customers, and yeah, promotions were getting handed out for engineers who did a hacky prototype integration with the latest & greatest NoSQL Big Data GraphQL Blockchain OSS project while solving no actual problems. I've also been other places (Amazon) where customers really are front and center, and spending time on cool engineering projects that serve no customer purpose meant absolutely nothing when you wrote up your promotion doc.


I'm trying to select a good framework and coming from long before react, having a tough time finding why shouldn't use just custom elements with no framework. Which is already built in.

   customElements.define('my-element', class MyElement extends HTMLElement { ... })
I can manage state within the component, app state in window.state. Coding up a simple reactivity is really pretty straight forward. Now, for this feature and that - maybe not - but do we need all those features. Programmers like to write code, so every framework always gets bigger and more complicated.

I understand and respect the problem react is trying to solve, I just don't see it as much different than the js world before async/await and fetch, etc.. callback hell - which I saw as much more prickly issues.


Mithril or Svelte should be all you need. If you're coming from React, I'd recommend trying Mithril first. I've been using it heavily for 5 years now and I'll likely stick with it for at least another 15.

Mithril is reactive out of the box, and just works. It smokes React in every category, but still has an optional JSX integration if that's what you're comfortable with.

https://mithril.js.org/

https://svelte.dev/


I was excited about Svelte, but now Astro JS is my favorite.


Those tools are not mutually exclusive. Astro is not a component UI library.


If we’re talking about class-based components then I agree with you. React doesn’t do much… maybe some performance benefits, and maybe you can avoid some complex DOM manipulation here and there, but with the extra abstraction required that all might be a wash.

But with functional components I think React gives you something substantially more debuggable than an object instance with random method calls that manipulate the DOM.

React functional components (with hooks) mandate a very specific control flow that probably halves the debugging surface for any given bug, saving time.

You do have to exercise restraint when incorporating third party libraries, but if you can do that it can be a very rapid development environment.


I'm not sure if I'm following, are you saying that class-based components (whether React or not) could be characterized as "an object instance with random method calls that manipulate the DOM", and thus React functional components offer an advantage to them?


Iirc correctly the hooks in functional react are classes under the hood (maybe I’m wrong and it’s functions, been awhile.) The advantage functional react has over class based is reusability. You could reuse classes before and functions within them but it gets harry keeping a clean architecture.

With functional components you can write hooks that allow you to reuse all state logic between components.


Any good articles I can check out that go into this in depth, or should I just check out the tutorials/documentation? Thanks


I pursued this idea pretty aggressively for a while. What I found is that it was a wonderful fit for small projects, and then became a real drag as the scale/complexity grew, which led me to start thinking in terms of a budget-matching principle [1]

  1 https://paulfrazee.medium.com/building-on-budget-4b91b43d0357


>"having a tough time finding why shouldn't use just custom elements with no framework"

This is exactly what I do on SPA front ends for many of my customers. Of course we use some libs but those have nothing in common with the frameworks, just narrowly scoped solutions. Saves gobbles of time and money.


React itself really hasn't gotten significantly bigger. It's more of a rendering library than a framework.

Custom elements are really neat, and may very well do what you need. The big pain point that React solves (for me at least) is that you get to define your views declaratively instead of imperatively.


Custom elements are just a way to define tags. React solves everything that's inside that class you wrote... and in a better way IMHO. E.g. with custom elements there's a difference between an attribute and a property and it's a PITA.


Compatibility for starters: https://caniuse.com/custom-elementsv1


Last time I used them, web components were incredibly slow. They were so slow to render, after using maybe 2 or 3 of them I realized why nobody is trying to build apps this way. Just isn't there yet. Probably won't be until HTML Imports are merged with JS Imports.


This is a surprising perspective, since we're using web components top-to-bottom to build photoshop on the web, & some of that decision was driven by performance comparisons where web components outperformed react.

It's possible that very naive implementations of web components would render as slowly as you describe - like if you rebuilt the whole DOM tree at every level on every change.

Here is a performance-oriented talk about rendering web components via browser-parsed template literals via Lit (which is how we do it):

https://youtu.be/CJYkwDTaHzY


Stop your propaganda, the Internet largest video platform uses Web components with Polyfill.


They mostly encourage bad practice by design and people do what these tools give an affordance for which is why the results are broken.


People can write bad things in every language. "It takes a lot of skill to write Java in any language." is a pithy quote for a reason.

The issue is usually frontend pedagogy or the lack of it. Maybe things have changed but when I graduated undergrad CS in 2017 the extent of frontend being taught in my school by professors was "hand write some HTML, maybe some PHP if you're lucky". I've never met anyone who learned frontend anything in school to a degree that matters, so everyone is either learning from other junior devs on the job, from blog posts that are often wrong, or from a backend engineer who was pressed into learning frontend.

Yes, JS has a very tortured history coming from the fact that it was not intended to be the long-term development language for web interactivity from the start, but we also don't really teach how to do it properly.


> Maybe things have changed but when I graduated undergrad CS in 2017 the extent of frontend being taught in my school by professors was "hand write some HTML, maybe some PHP if you're lucky"

Here's a secret nobody told you: You don't need to learn frontend specifics. All the same lessons from business software engineering apply.

I not-graduated comp sci in 2012 and have been building webapps since before jQuery was cool. It's nothing special. The biggest problems are always the same: data and domain modeling, managing complexity, teamwork, and state consistency.

If your comp sci degree didn't teach you how to apply solutions to those problems in any context – frontend, backend, iOS, firmware, desktop app, Android, or data pipeline – then it was a worthless degree and you should get your money back. The point of comp sci is to learn about the ideas behind the scenes, not about specific frameworks.


Preach!

Data modelling and managing complexity (or I prefer to say knowledge organization) is a prerequisites for every software program ever.

I'd add one more: System design.

Basically dealing with many asynchronous moving parts, managing entities' lifetime, separating and categorizing domain/data, and understanding what-is-important-to-whom. It is a knowledge that's applicable whether you are programming a kernel scheduler or managing people and projects


Yep and nowhere seems to teach this in practice other than job sites. I’m building a team right now with two mid level engineers and a junior. They’re great and I couldn’t ask for better guys to be clear; but your point stands.

They don’t understand this (subsystems architecture and the the living data model.) It’s like they think I have a giant list of existing solutions to every problem that they haven’t memorized yet so when hit with a problem needing a subsystem they were basically useless until I slowly started teaching it to them. I’m talking Ivy League kids with degrees I only ever dreamed of getting. There brains just aren’t trained to architect systems the way I expected junior/mid level engineers to be as a self taught engineer.

Also the data model stuff has been a real painpoint for me. We were set up with graphql and Postgres so of course the MVP forwent any working data store other than react states.


Eh, to some degree you do get a starting point in uni for various things. You’ll learn basic models for systems or databases as part of core requirements. If a web course exists, it’s most likely optional and out of date.

Web is certainly a different context, and some people struggle to pick it up. There’s no authoritative book like the C Programming Language, and the web is full of wrong information that sometimes comes above more authoratitve sources like MDN in Google results.


> Web is certainly a different context

I mean it's a thin or fat client talking to a fat or thin data source over a network. "We" have been building systems like that since the 1950's.


This is absolutely correct from the perspective of a senior developer. Junior devs generally haven't completed enough language/framework hype cycles to develop the required experience (or cynicism really) to look past the bullshit to this very simple fact.


how we present has changed a lot, though. And we reap the rewards of not teaching.

As a general example, part of why accessibility on the web is so poor is because we don't teach anything about it. It's become this mythical scary thing, when in reality a lot of the pain is avoidable with a little bit of thinking. We just don't teach any of it.


If we're talking language level (even in C, you'd usually be using other libraries and APIs even if it's just POSIX or curses), I'd argue that "JavaScript: The Good Parts: The Good Parts" is probably the most authoritative book out there.


woah woah hold on there young one

This isn't that. My hostile working definition of a framework is something that

. breaks core assumptions about a language or system

. limits what a user is permitted to do

. increases complexities by adding new abstractions

. has non-specific specifications by using unclear and imprecise language

At the end you are hardly writing software. Instead you're deep into a world of new abstractions and are fundamentally limited by these abstractions.

Frameworks work at a subconcious level. They permit the users to be constantly busy as they chaperone codebases which would otherwise have long term stability all while staking the claim that it's the fastest and easiest solution.

Because frameworks exist primarily in a product space it's worth looking at their value proposition. Frameworks essentially act as a modern facilitator to what Frederick Winslow Talor called "Soldiering" in the text "Scientific Management". Essentially this means "the evasion of work or duty", the workers you wish to provide to have a vested interest in their own well-being and do not benefit from working above the defined rate of work when it will not increase their remuneration.

Normally a manager would have every reason to dismiss these programmers. To combat this natural inclination, a proper framework makes sure this is impossible by making them unfirable.

Given a product:

. Systems should not continue to function without the programmer

. Code has to constantly be rewritten in order to achieve the same ends

Also it permits the users to go on constant employer funded vacations to conferences and training sessions.

From a professional programmer's point of view, the primary goals of any framework are to provide the users with the following:

. Job security by ensuring brittle applications

. Endless tasks by ensuring endless complexity

. A sense of elitism and entitlement

. No expectations of deliverables

. Be vague enough so blame can get shifted if things break

By making every project asymptotically impossible to deliver vaporware, the ideal framework ensures that people are always doing something while at the same time nothing ever gets done.

The old is dying and the new cannot be born; in this interregnum they're on salary so they make it last as long as possible.

In trades where there's no guilds or unions, there's a tendency to create career protection through other forms of tribal qualification systems or arcane knowledge. Making things intentionally complicated so that only a select few people can comprehend them is a common way to capture and exercise power.

People adopt the patterns because they want to have the perceived protective properties of the obscurities.

Worlds of irrelevant relations and materially meaningless abstractions are essentially how fields such as fortune telling and astrology continue unabated. The form becomes the function and the elaborations its aesthetic.

...

Btw, this is a collections of excerpts from a 40 page document I have on the psychology and function of frameworks on how the most popular ones service human emotion that I've been working on off and on for a while.


That reads like a parody to me - the cynical engineer that uses conspirational thinking patterns to create a narrative of the world when emergent outcomes are the causes.

Look for counterexamples where your cause incentives don’t exist yet the same outcomes still do: that is scientific thinking.

> Job security by ensuring brittle applications > Endless tasks by ensuring endless complexity > A sense of elitism and entitlement > No expectations of deliverables > Be vague enough so blame can get shifted if things break

The last thing many programmers desire is a millstone of old code they are responsible for. Perhaps you posit that they subconsciously desire to make complex code to give them job security? I suggest you watch (or ideally become) a founder engineer, who’s incentives are the opposite of all the above, yet the founder still ends up with the same problems.


Done both.

This phenomena can also happen organically.

All these things are tools and you can wrestle with tools or have them make life easier.

The question is about in what direction this tools assuage the creative process.

I've had the luck of seeing and being involved in codebases to both billion dollar successes and million dollar moneypits.

There's certainly patterns and difference I've seen.

The most notable one is successes seen to use a lot of boring unexciting old software with ugly websites.

Like say emacs, that's got an ugly old site. Or what about GCC? How about the Apache site? It doesn't even hype up how amazing and easy your life is with their simple and elegant efficient masterpiece. What about debian.org? FFTW? PCRE? Sqlite? imagemagick?

Now compare this with react and vue.

One is "we have this tool" and the other makes lofty emotional pleas about your relationship with your work. They're fundamentally different approaches and thus have fundamentally different outcomes.

One accomplishes a goal while the other accomplishes an affectation.


This is cynical as heck, but a good read. Do you have any plans to publish the larger document?


After that encouragement I do! Thanks!

The premise is how to write a successful framework. The cynical takes are presented as advice.

It's structured like those guru business books like "Blue Ocean Strategy" or "Little Bets".

That genre requires an additional separate focus and some further work. It's by a bunch of narcissists who ran multiple businesses into the ground who pivoted to being a guru and offer acronyms, charts, and X-point frameworks in tidy books with a bunch of business examples, most of which catastrophically collapse within 12 months of publication.

And then the books sell 5 million copies, the authors get Ted Talks, it's the same mechanism at play. People pass around their Clayton Christensen of Geoffrey Moore diagrams and crib paragraphs quoting them like they're bible passages. And people eat it up. It's wild.

I remember looking at the Appendix of one of Jim Collins books for the first time about 10 years ago where he talks about his methodology with his team. When you start cross-referencing and see the omissions, mistakes, and misrepresentations, it's wild. I was like "wow this thing is nonsense".

You've got Sutherland's Scrum, Collins BHAGs, and you burn through $20,000,000 in Series A without releasing shit. Alright, I guess that's what we do.


This is a great reply and something I've noticed IME as well. I'm sure there is an economic term for it, but it's like perverse incentives coupled with unconsciousness.

Echoing the other replies that we want to read more of your thoughts (book, articles, blog). Is your site in your profile the best way to follow you?


This is easily the most accurate description of what a frameworks are and the consequences of their adoption I have come across in my 25 years of experience in industry. A not so minor quibble: I think most end users of frameworks approach framework selection with good intentions, likely from a position of naivete, rather than from some sociopathic desire to build a bunker for themselves in their workplace. This of course doesn't change the outcomes.


Give us the doc


When it's ready. I'm going to look for a published


Link to the doc?


When it's ready. I'm going to look for a published


> Maybe things have changed but when I graduated undergrad CS in 2017 the extent of frontend being taught in my school by professors was "hand write some HTML, maybe some PHP if you're lucky"

And rightly so, because frontend web development is not Computer Science.


I completely agree. And the thing with different frameworks is they let you scale to varying heights of complexity before you reach those high-level problems. For example, I find that functional components can have more complexity in terms of logic than class components before they become a complete mess. React itself allowed us to go way beyond jQuery before becoming a complete mess. I don’t think there will ever be a framework that saves us from that as long as managers keep doing what managers do.


> There are always [] half-finished fix-the-world ideas conflicting with each other,

I work in a code base like this. People's suggestion? Introduce React!


> Some part of your organizations chaos is going to reflect in code,

This is reality, and why organizational chaos is so painful for engineers.


If you read Programming As If People Mattered from 1992, the frontend mess was true then too.


relevant codeless code parable: http://thecodelesscode.com/case/123


I’ve had similar experiences, but I wonder how much of this is truly inevitable because software development is complicated and requirements often change along the way, and how much is simply bad management.

I’ve noticed that over time the prevailing culture in software development has drifted more and more towards “thinking small”. This has certainly been encouraged by the shift to web and mobile apps in an always-connected, always-updatable world.

First it was just the code. Short functions, few parameters, shallow nesting. Make everything testable and maintainable!

Then it was the commits. Release early, release often, merge WIP straight into master in your CI/CD system. We need fast feedback and short cycles to avoid unnecessary conflicts!

Then it was the whole process. Break everything down, do one small thing at once, move it across that Kanban board, next sprint please. We need focus and visible progress!

The danger with all of these is the same: they come from good intentions and even have an element of truth behind them, but they can also mean the big picture gets lost. There’s no coherent vision shared by everyone involved. No-one is watching all the extra dependencies that connect the many small parts. Tech debt compounds. Eventually we are forced to acknowledge that there are “challenges” but even then we somehow convince ourselves that those were inevitable, even though they weren’t really there before.

Yes, of course our early-merged WIP hidden behind a feature flag in CI is completely different to the feature branch we used to use. Now we know everything builds before it can be merged, even though nothing is really testing that all the different combinations of WIP actually work together, so that’s a big improvement on before. And since obviously we have a reliable, automated process for backing out any unfinished code that doesn’t make the cut later, we’re also much better off than the old situation where we’d just have sidelined that feature branch and never merged into the next level up in the first place!

In the real world, this leads to exactly the mess described in the parent comment. There’s no coherent vision for anything big that is shared by everyone involved, no considered and consistent structure for the software architecture or the APIs or the data formats. If we rely on emergent properties that evolve organically, we also run into evolutionary dead-ends, and what survives might work but also be messy.

Personally, I don’t really buy the argument that this is inevitable. Five players can make a great jazz band. With 100 players, you probably want an orchestra with a conductor and sheets and the occasional featured soloist. Neither jazz nor orchestration is “better” or “worse” in absolute terms but they are certainly different.


> First it was just the code. Short functions, few parameters, shallow nesting. Make everything testable and maintainable!

I don't think this is related to losing sight of the big picture, no more than focusing on good clear sentences means you can't write Anna Karenina.

But I do agree that sometimes the big picture is lost, with tasks that have been broken down inappropriately.

I have a suspicion that partly this is driven by open plan offices: tasks have to be broken down, as focus is a luxury.


As a developer who’s been working with React since the beta, I can confidently say that the author is speaking the truth. Especially so near the end of the article where they can’t seem to quit React.

For all the annoyances of Hooks, they really are a godsend when it comes to composing state. And refs do indeed suck, but they sucked even more with class based components. I can’t tell you how many times I was able to solve a complex DOM state issue with custom hooks wrapped around refs.

Newer tools like Svelte and Solid do look promising as far as removing boilerplate, but they personally feel a step too far off the path of “it’s just JavaScript.”

Has anyone else here successfully left for greener JS pastures?


I just use vanilla JS on the front-end just like I do with Node.

I have never understood why people find state management challenging. I suppose its because they are stuck in a framework or MVC mindset where everything is a separate component and each must have separate state models that must be referenced frequently and independently. I just put all my state data in one object, save it on each user interaction, and use it only on page refresh. I have an entire OS GUI working like this and the state management part is only a few dozen lines of code.

Frameworks are like being locked in an insane asylum. You may not be crazy, but everybody else is and you have to follow all these extra rules you would never follow with freedom in the real world. But, the insane asylum provides you meals and bedding and many people can't be bothered to figure that stuff out without necessary hand holding.


I wish I could understand the appeal of react and other frameworks but everytime I interact with them I find them so terrible opaque and frustrating. I've built plenty of things with various frameworks including react[1], maintained, been in team-based development doing it, have github projects that use them with thousands of stars but I think they are brain-damaged terrible ways of doing things that shouldn't exist.

I've given it a fair shake and I wish I could change this opinion. I'm trying not to rant so I'll stop here.

I do a cathartic exercise every time this stuff gets to me at a themed twitter account. It's pure vitriol: https://twitter.com/sisnode

[1] oftentimes I see the anti-react argument as "react sucks which is why I use Y framework". I'm saying they are all(?) a toxic trend that leads to terrible products; more complicated, harder to maintain, aggressively encouraging a glossary of programming antipatterns passing it off as elegance.


Frameworks enable ecosystems. Ecosystems enable reusable components.

The more you deviate from one of the set of common conventions, often enforced by frameworks, the more you have to build on your own.

The larger your project gets, and the more developers who need to understand your code, and the more developers you need to hire and get onboarded quickly, the more that those extra rules start to make sense.

And once you've learned and internalized the patterns necessary to build larger systems, it becomes force of habit to just use it wherever, even if it's nominally easier without them. For most developers, a go-to pattern will be faster than working from first principles on every project.


I'll take Libraries over Frameworks every time.


> I suppose its because they are stuck in a framework or MVC mindset where everything is a separate component and each must have separate state models that must be referenced frequently and independently. I just put all my...

Then you exactly describe MVC...

> state data in one object,

This is your model.

> save it on each user interaction,

This is your controller.

> and use it only on page refresh.

This is your view.

MVC is a relatively simple concept, and it works well.


Yes I was confused by this. It’s MVC, but without React’s benefit of having the GUI update without a page refresh.

edit - fwiw I too am another heartbroken React dev


I introduced Vue to a plain JS project once and reduced the amount of front end code by almost half, and vastly simplified the state management.

We must work on very different kinds of projects. I really can't imagine plain JS being a viable or appealing solution compared to Vue, which gives me very little grief at all.


While I don't doubt your specific experience, I'm wary about drawing firm conclusions from a single project. Vanilla JS projects can vary wildly in how verbose and complicated they are. I would bet that there are plenty of examples of both types: those that would be much more concise with a framework and those that wouldn't.


> and use it only on page refresh

Doesn't that mean you can never reflect state updates in the DOM without refreshing the whole page?

> I have never understood why people find state management challenging

Automatically determining what DOM objects need to be updated in response to a change in state and updating them without a page refresh adds a lot of complexity, if you completely ignore that requirement then state management would be simple like you said.


I’m also a developer and tech lead who’s been working with React since the beta. Agreed with all your points about React. I’m not sure I would say Svelte and Solid are a farther step off the “just JavaScript” path than React given JSX though.

I haven’t tried Solid, but Svelte has already paid considerable dividends for our team. Frontend feature development pace is faster, the code is generally leaner, and the developers love working with it.


I'm also a TL (which makes me a teaspoon here in Germany, which I like more than the tech lead title). I understand how the development can be faster with Svelte, but ecosystem argument really hits home. You'd get to 80% with Svelte perhaps much faster than React, but that missing library for, say, drag-and-drop makes that last 20% itself plus "hey let's develop our own drag-and-drop library in-house which should be easy and opinionated and maybe it gets open-sourced" (it will be hard, with crazy high budget, as it will try to cover many use-cases you will never have and it still won't be open-sourced because now it's your "core competency" and five months later someone will realize your component has terrible a11y and etc. and one million bug fixes later it is a monster code-base that none wants to touch and maybe rewrite? oh here we go again).


All excellent points. Yes, the package ecosystem has been a pain point.

We’ve turned this into a slight positive by pushing the business to allow us to make open source contributions. The developers seem to enjoy this a lot, and hopefully our work helps others in the space.


Someone needs to invent a way to import React/Vue/Angular packages to Svelte and still use Svelte syntax somehow. Sounds crazy but I wonder if even remotely possible.


What is a teaspoon?


TL – Teelöffel (teaspoon, unit of measurement)


TL is the abbreviation for the unit teaspoon in German, the way ts is the abbreviation for teaspoon in English.


Yeah, I also didn't get the 'teaspoon' reference.


German word for teaspoon per googling it on the bing: Teelöffel

Seems like the obvious abbreviation for that is TL, so it's a joke on cross-language abbreviation collision.


> I haven’t tried Solid, but Svelte has already paid considerable dividends for our team. Frontend feature development pace is faster, the code is generally leaner, and the developers love working with it.

Is that just down to Svelte, though? Or is it the greenfield effect? Projects always fly quickly at first, when the code is fresh and unconstrained, and you're building the basics.

My concern would be when things get complicated and you have to debug Svelte's binding magic - and I have very bad memories doing that in Angular and Knockout.


I would argue it's 100% greenfield effect. A rewrite fixes all the things but introduces new problems. I would bet the OP could've achieved the same effect by figuring out what's wrong with their codebase (which honestly is easier for an outsider to do than someone who has worked on it everyday).

And I would caution against converting anything to a non JSX or hyperscript language (like svelte or vue), you don't want to tie your entire view to some HTML-like DSL IMO.


To clarify, this was new development — not the process of rebuilding of an existing app. For that reason, the greenfield development was indeed simpler.

That being said, it’s been one year and making changes to the Svelte application is (in the developers’ opinions) easier than our set of comparably-sized React applications. Of course, all of this is specific to our team members’ skillsets, the application complexity, etc.


That's interesting. 12 months is still very early though, unless it's a project with a lot of throughput.


I can confirm Svelte is way easier, leaner, and quicker to work with than React. The exception is, of course, the library support, which is a huge drawback and would make me cautious of using it in a business setting for another year or two.


Vue has been my favorite since Vue 2. It hits the right balance for me between the opinionated Angular and "you figure it out" React. It does what I want a JS framework to do: binds values and renders views with minimal setup (computed properties solve so many common problems).

Also, it has amazing ESLint rules that really help keep all your code aligned and following best practices.


That’s the thing though - hooks aren’t JS. They don’t allow for control flow. Hooks are a language that superficially looks like JS. I’m with you on not inventing new languages, and I wish that React didn’t step so far off that path itself…


> hooks aren't JS

This is so silly. Hooks are literally hooks into a scheduling algorithm you are at the mercy of. That scheduling algorithm is pure JS. Of course you don't have classical control flow in someone else's scheduler.

The key users are referring to when talking about "JS vs magic" is that React is just constructing objects and invoking functions, with known semantics, whereas Solid and Svelte are auto-magic-reactive systems without clear semantics rising from the choice to do even more things in their internal black boxes than React, such as never re-rendering components, dark compiler magic on syntax that doesn't naturally map to a JS tree, and other such things


Indeed, part of svelte's whole "magic" is to interpret labelled blocks beginning with "$" as a hint to do all manner of AOT codegen


But hooks need to be named "useX" and have restrictions on where to be called (that a program detects). While they are of js clearly they are not "normal" js functions either.

While I use hooks without problem, I also feel like it is an invented mini-language with a lot of extra quirks. Maybe the problem is js does not map elegantly to some of these functional concepts without a good type system.


Hooks don’t actually need to be named “useX”. That’s the convention, and the React team provides a lint rule that enforces it, but you can name your hooks whatever you want and it’ll work fine.

I’m not what sure what you mean by not “normal” JS functions, though? They’re an API provided by a framework, and — like all APIs — they have specific constraints that govern how they’re used.


Absolutely correct. I stand corrected. There is also a lint rule (the program I was refering to) to check that hooks are not called in some wrong places IIRC. Those lint rules are the default for create react app.

To each their own. Although I use react and hooks, for my taste the hooks api is not very clean. All these are implicit not explicit and without linting they can easily result in runtime errors. But maybe I am spoiled by Elm ;)


> have restrictions on where to be called

This is because hooks are just next() calls on an iterator. Is it magic and entirely because the devs thought it was more beautiful than having to pass a key like state = useState("state", 0)? Absolutely. Does it transcend JS, no.

   hooks = [1, 2, 3, 4]
   
   isOne = next(hooks)
   isTwo = next(hooks)

   if flipcoin()
      isThree = next(hooks)

   # oops, it's sometimes 3
   isFour = next(hooks)


> But hooks need to be named "useX"

No they don't, that's a suggested convention

> have restrictions on where to be called (that a program detects)

Yes, it is strange that they opted for this implicit approach, but this is the nature of interacting with a scheduling algorithm in real-time; it is with limitations

I agree they are clearly not unrestricted free-use JS, but they aren't a custom DSL hydrated by compile-time craziness, they are hooks into a scheduling algorithm to help you maintain consistent state in a giant tree. I'm not sure how that is ever going to be free. Perhaps a better type system can help but this is fundamentally complex


> hooks aren’t JS

They literally are.

> hooks aren’t JS

The code in React executing components relies on hooks running in a consistent order each time the component runs, but the existence of a runtime context that has expectations about side effects (and hooks are side effects) doesn't make it “not javascript”.


Hooks are executed in order as they are defined, isn't that a fundamentally broken design in regards to language spec?

I don't have an opinion, just generally curious because it feels very odd that the order of my functions matter.


> Hooks are executed in order as they are defined

Hooks are functions, and they are executed in the order called from within the component, which is itself a function, just like any other functions calls from within another function.

(The mechanism tracking calls to them and deciding whether the function passed to the hook needs to be called requires them to be called in the same order each time the component is executed; if they were called in order of definition rather than normal execution order this would be true by definition; the whole reason for the rule about not using flow control around them is that they are functions executed in normal flow order.)


Thanks for the correction and teaching me something!


It only matters that the order not change dynamically between renders. This probably could have been avoided if react required a unique key per hook, but I think for brevity it's a decent trade-off.


For the life of me, I can't understand why they didn't go the route of "add an id to your hook." It would solve one of the two big gripes people have with hooks.


ids would be stuttering (especially for things like useMemo/useState), add a different source of error, and—if the goal was to make hooks compatible with flow control—probably create new categories of bugs that would be harder to catch in a linter or even with runtime checks like the existing “number of hooks cllaed changed” one.

Adding visual noise to enable subtle bugs may not be a win.


Hooks are not a "language", they're just react API calls.


"Just" is not really fair here, they're a window into global variables. Global state is awful to deal with but a necessity in the real world, so having some sort of constrained global state is something we're always trying to solve in new ways, singletons, monads, etc. Here we have hooks, which is an interesting experiment but something I personally would have played with in some new framework rather than dropping into the most popular and mainstream one.


Depends on what you mean by global state. You don't have access to a single pool of global variables. You only have access to what you put there and what you've been given.


Is it that they are global state to react but not to the programmer or his/her code?


It's that they are not shared like globals.


Yes and I'm surprised no one has mentioned Lit or bare metal web components in this convo. I'm starting a large TS project at the AAA game studio where I work (my day job, not DTA) and it wasn't hard to choose to avoid React or Vue or Angular.

Lit is the anti-framework because it isn't a framework. Once you remove all the cruft, you can spend a lot more time writing the code that you want to write and, doing so in the way that you want to do it. Everything discussed in this article is solved by bare metal web components.


Indeed, lit is fantastic.

It is built on top of web-standard; I am surprised how (lit)tle attention it gets on HN (so far).


Because lit is too bare metal to qualify as a js framework. Does it have good solutions for router or state management? Last time i checked: No.

That is why it is not discussed that much. If you need to write components, then lit may work for you, but whoever wants to ise those components would prefer a js framework.

Also, lit is from Google. which makes it worse as Angular is from Google as well


Lit is just syntactic sugar for bare metal stuff that is W3C standards based. There isn't any vendor lock-in and won't be "upgrading" your Lit because they told you to.

You are right on components for other people -- but if all the components are for you or your company, ones you handcraft w/ Lit will be lighter weight and easier to write and fix.


Well, I work for a fortune 100 company and we use Vue. After using React, I strongly prefer Vue, so I would say it is the greener JS pasture ;-)


Agreed. Vue is the best of all worlds in my opinion. Here's my take on the whole thing from a Svelte post a couple of weeks back: https://news.ycombinator.com/item?id=32763509#32767905

> I still think Vue (especially Vue 2) is the greatest of them all. I've worked professionally with Angular, React, and Vue. Each for several years. Vue is easily the winner for me with the syntax that closely matches native HTML and JS/TS and how it encourages clean separation of concerns and clean code. JSX/TSX is absolutely the worst for the latter, it's like the wild west. "But you don't have to write it that way" - yeah ok, but when you work in a large organization it's going to get written that way by your peers; good luck trying to stop it. Angular is just a clusterfuck of pipes and observables that require higher cognitive load to unravel when trying to understand a semi-complex block of code. Contrast with Vue where I can near instantly understand what it's trying to accomplish.

> This shit right here - {#if <condition>} {:else} {/if} - is why Svelte is deterring me. For the love of god, can we stop coming up with weird custom syntax for templating code? This is one area where Angular also pisses me off: *ngIf for example is just as hideous. With Vue: v-if, v-else. You add it as an attribute to native html, it's dead simple. No weird symbols, no braces or other oddball shit I have to look up when I step away from it for a few months and come back. It just makes sense right away.


v-if and v-else are not native html attributes either. Control flow via HTML tags has always felt like a code smell and been a major turn off to me.


I tend to agree with this, I prefer the way Svelte make the not HTML/JS/CSS bits really stand out but it's definately just a personal preference. I don't really care about the "it's not JS" argument, people are happy to use typescript without that compaint so it feels rather arbitrary.


Personally, I found Vue was the best solution for CRUD-like use cases, where the complexity is in the sheer variety and volume of UIs you need to maintain. Whereas React works better for more complex interactions.

That being said, the Vue2 -> Vue3 migration has felt pretty frustrating. It's felt like, with enough work, I could eventually get Vue to behave similar to React.


> Has anyone else here successfully left for greener JS pastures?

I've simply stopped doing any frontend development contract work *. Until the whole JavaScript world pulls its head out of its bottom, I'll leave that niche to other people.

* I'll do JS and React if I really have to, but I'm actively avoiding any client-side focused projects.


It's a wide open web with millions of developers, and 25 years of language and ecosystem development, so there will always be 27 1/2 ways to solve a problem. Client side dev is hard. Especially on the web. It's understandable that anyone would avoid it for easier work.


Been using various web component frameworks in enterprise level projects and have been very happy with them (Polymer, Lit, other custom frameworks as well). The nice thing is that since they are standards based you know that they will be around for the long haul and will have a more measured evolution.


I've been using React for maybe 6 years now and Javascript for at least 10 years before that. I've started using Svelte in the last 6-12 months in professional capacity having messed around with it ofr 12 months of side projects before that, to me it feels much closer to writing HTML, CSS and JS than React ever did. Animations, transitions and other things that can be really awkward in React, requiring hooks and all sorts of framework specific constructs just work as if writing in plain HTML/CSS/JS. The template type bits feel nicely and explicitly separate unlike JSX's oddities wrt things like "className", I prefer it. Particularly I find a typical svelte component significantly more legible.


I've used Mithril [1] for years for my personal projects, and React (unfortunately) for my day job.

I wish I could write everything with it.

1. https://mithril.js.org/


Same background here.

I don’t believe in quitting cold turkey and I don’t think there’s anything available to fully replace all aspects of React. We’re instead gradually transitioning our internal ecosystem to use less React-specific stuff, positioning us to migrate (or not) in the next few years.

- Move from CSS-in-JS to vanilla CSS

- Avoid React-specific libraries, both developing them internally or when selecting third-party deps

- Keep business logic out of React components whenever possible

Etc


I've went back to server rendered templates/html, and I'm using Unpoly (1) for adding interaction and partial updates where necessary. I also have a couple Lit (2) components for a part of the app that should work offline.

(1) https://unpoly.com/ (2) https://lit.dev/


I think my sentiment is echoed in some sibling comments as well, but I have been having a good time with vanilla JS lately.

React and friends really do make certain things easier and "nicer". But when you sit down and think about it, those things aren't that bad with vanilla JS. It really makes me wonder what value React et al is adding for the cost in KB and mental overhead.


We have had success in migrating away from React, and in fact away from client-side code altogether by building more and more of the UI of our Elixir/Phoenix backed application in Phoenix LiveView. There are still some parts of system that really need to be client-side code powered (a WYSIWYG HTML editor, for example) but now our default choice for new UI is LiveView.


Same here - we've been much more productive on the development side with LiveView than with our previous React iteration.


> they personally feel a step too far off the path of “it’s just JavaScript.”

That’s more or less exactly what everyone said about JSX when it first arrived. Now people don’t really consider it. I suspect we might end up feeling the same way about Svelte’s language additions if they ever become commonplace.


Why does it have to be in the path of "it's just Javascript"? I don't understand this.


Wider marketability.


Yes! CLJS + Reagent (and thus react).


Seconded. All the benefits of Clojurescript and React's core proposition without any of the classes/hooks madness.


React is great for managing the shadow dom, but it still sucks for state management. I am really happy with React + XState as my core stack. Scalable, type-safe, universal.


React is low level. Svelte and Solid are low level too.

You are dealing with particular values and wiring everything meticulously.

Whenever I write stuff using https://rxjs.dev, writing React feels the same.

Using ExtJS years ago felt higher level than React.


AlpineJS fits my needs for simple sites.


I must be the only person in the world who likes class components in React.

Sure, it's often overkill and a functional component does the same thing with less code. Use a functional component in these cases. But if you're doing something more complicated then stop treating class components like the fucking devil. They have their place.


I ditched React soon after they released hooks, mainly because I couldn't relate to the tradeoff React roadmap was taking from there. They went in a different direction from that point onwards, it seem like whatever code you write will become obsolete with the new set of best practices in the next release cycle.

More importantly, I realized React is trying to tame Facebook level of problems and hence their design decision steams from those data points. I develop small/medium type of frontend apps which doesn't need to apply solutions developed for such a scale.

These days I'm using Hotwire[1] (Turbo + Stimulus) with fair amount of vanilla javascript libraries in my apps. Occasionally, when I need to develop a reactive piece of UI I reach out for Svelte[2]

I'm quite happy after making the move. My apps complexity has reduced drastically and there is huge boost in my overall productivity.

[1] https://hotwired.dev

[2] https://svelte.dev


Step 1: The existing tooling is too clunky, big and a major PITA to work with, Developers spend most of their time fighting their framework and tooling to do simple things.

Step 2: Someone gets fed up with this writes a framework that "does things right" and is designed for "simplicity"

Step 3: People start loving the new tool because it is so much easier to work with.

Step 4: People start to do things the tool wasn't designed to do. They start making "minor feature enhancements" to the tool so that it can fit more use cases.

Alternative Step 4: Tool becomes "industry standard" so everyone starts using it because it is "the right way", regardless of whether or not it is a good fit.

Step 5: The new tool becomes massive and bloated and overwhelmed with too many features, configurations, and options.

Step 6: Return to step 1.

> The Wheel of Time turns, and Ages come and pass, leaving memories that become legend. Legend fades to myth, and even myth is long forgotten when the Age that gave it birth comes again. In one Age, called the Web 2.0 Age by some, an Age yet to come, an Age long past, a wind rose above the great mountainous island of FANNG. The wind was not the beginning. There are neither beginnings nor endings to the Wheel of Time. But it was a beginning.”


I don't agree with you.

I have been doing Rails development for past 10 years now and I never faced a dilemma where the framework took a direction which isn't aligned with its core vision.

I have been just trying to find a similar tool for frontend where I don't have to keep rewriting the entire codebase.


What about the webpack rails7 situation? I feel like rails has guessed wrong too many times about FE (coffeescript, asset pipeline, websockets) that I don't trust them to deliver their own stack.


I'm not sure this is a fair representation. Rails didn't "guess wrong" too many times. They chose the best option available at the time. Remember, CoffeeScript was used in Rails in 2010! Brendan Eich even borrowed many ideas from CoffeeScript in subsequent versions of JavaScript. Ditto, the asset pipeline solved a great number of problems for many years. With recent advances in web browsers, many of these problems aren't really problems, so it's less relevant, and Rails has to take advantage of import maps as an alternative.


This is kind of a great example because Django did the opposite: insist on having no frontend opinions.

As a result, Django left its users completely on their own, while Rails made choices that wouldn't last the test of time.

Given how chaotic the frontend ecosystems have been over the past decade, I'm not sure there was a "right" answer in hindsight.


You are correct, Rails and Ruby are one of the few places I haven't felt like there's been constant and unedning churn, I attribute it to the incredible flexibility and power of the Ruby programming language, which incidentally is my favorite language to work in.


I think Rails was able to avoid this because of its modular structure and ease to write gems that extend the framework in a way that fits your project's circumstances and needed tradeoffs. As DHH famously said Rails is omakase, but you can also make reasonable substitutions.


It partly became modular because it merged with Merb, which was an alternative modular web framework that competed with Rails for a little while.


> The Wheel of Time turns, and Ages come and pass, leaving memories that become legend. Legend fades to myth, and even myth is long forgotten when the Age that gave it birth comes again. In one Age, called the Web 2.0 Age by some, an Age yet to come, an Age long past, a wind rose above the great mountainous island of FANNG. The wind was not the beginning. There are neither beginnings nor endings to the Wheel of Time. But it was a beginning.”

I've never seen this before, but I'm stealing it!


In case you don't know. This is a variation of the first paragraph of the Wheel of Time book series by Robert Jordan. Each book opens with a variation of this same paragraph


I’m well aware of the origins of the quote :)


Just wanted to make sure, it wasn't clear to me if you just liked their modifications or you weren't familiar with the quote at all :)


Nah.. That's some Ba'alzamon stuff...


> The new tool becomes massive and bloated and overwhelmed with too many features, configurations, and options.

It is almost as if people are not breaking their problems over the correct dimensions.


After a few trips around the wheel you'd think that people would realize "hey, we rewrote our entire react app, we were good little developers, we did the right thing,.. but that path led nowhere"


This tired argument has been trotted out repeatedly, and isn't really funny anymore. It's just old and boring.

For people like me who are new to JS and use these sorts of discussion to determine which technologies I should adopt first, it's really just pointless noise in the channel.

The little I know about JS so far, I definitely know this joke is tired and played out.

Step 2: Get a better joke please?


It's not a joke, it's intended to convey the wisdom of not thinking "the next big thing" will solve all your problems, it is intended to focus on the importance of fundamentals, and of relying on using engineering skill to solve problems rather than fancy gadgets, it is to point out the value of developing technical acumen rather than becoming a tool bound technician.

If you define yourself by the technology you work with you aren't an engineer you're a technician.


It's not a joke. It's reality. It gets mentioned repeatedly because of how true it is.


I understand your frustration, but I think you’re missing what is actually meant to be a helpful takeaway from this.

Essentially, all these frameworks ARE part of a cycle that repeat, and in time we all start to see it. Most of them just iterate on previous concepts, with some core concepts going way back to the late 60s, 70s and 80s.

What remains the same is the underlying Javascript language itself, and more importantly, fundamental software engineering and computer science principles.

Learn the fundamentals, and they will help you learn every new framework and language more easily, and in more depth.

If you really just want to get a job using JavaScript, then you might be best off browsing job postings to see what kinds of companies are hiring for which frameworks, and go from there.

But if your goal is literally to learn JS and find the right tech stack for you, unfortunately there is no replacement for learning the basics, and then picking a framework that looks interesting, and building something in it to see if it clicks with you.


It is because its true and once you get through the endless cycles of your newly chosen framework you will adapt a similar mind.


adopt better methodologies, languages (TS, ReasonML, etc), find what works for you, automate the hard part, find reusable patterns, don't settle for the popular but mediocre new stuff (eg. React)


this is how everything echos through time, no joke


> I realized React is trying to tame Facebook level of problems and hence their design decision steams from those data points.

Strong agreement!

There's a saying in community organizing and activist circles that goes something like:

"Don't apply the solutions of the butterfly to the problems of the caterpillar."

Imho it's a really important consideration when thinking about scale of movements (and nonprofits... and any community initiative...). This is especially true when "professional" people are always coming in and confidently over-applying their learnings in corporations to thinking about activism (which often, though not always, has very different incentive structures and lifecycles).

I think about this parable often in regards how all these scaled tech companies end up stewarding the developer tools and therefore practices for everyone. And they tend to out-pace and out-broadcast other wonderful tools that could better serve the majority of developer niches.


I don't have a strong opinion either way but if you left React because you are frustrated with code becoming obsolete and picked up Hotwire, a significantly smaller framework, arnt you likely to run into the same problem if Hotwire doesnt end up being the next big framework?

In 5 years if no one else is using Hotwire then your code is obsolete, no?

I liked working in next.js in the past but my company was already talking about Nuxt.js when we hadnt even fully converted to next. Feels like jumping ships from a ship with some major flaws, but will continue to float for x+ years, onto a lifeboat that may or may not make it another 500 feet before sinking.


In 5 years if no one else is using Hotwire

I think that's the opposite of what he is saying. Because React is updated and changes frequently, your code becomes obsolete unless you update to follow the latest changes. In theory, if everyone abandoned Hotwire, your code would never be obsolete or need changes, because Hotwire would never change. In reality, as browsers and web standards change, frameworks need updating.


React doesn't change frequently though, that's the point. And it has always had excellent backwards compatibility. Class components are still fully supported, for example.


React changing best practices every few years is a good thing! It means it keeps getting better.

That would be a bad thing if it meant that earlier best practices were no longer maintained. But that’s not true. Class components are still around. All official documentation continues to have class component examples and explanations (where it makes sense obviously…there isn’t any class component documentation under hooks, of course). And class components will likely still be around 5 years from now.


React changes best practices every few years prompting many rewrites.


One has to question the sanity of a rewrite launched for the sake of notional orthodoxy. If it ain't broke...


Right but you dont actually have to rewrite it, correct? The updates dont break the old code. It's just not best practice anymore.


All the class components people wrote still work and can be maintained. React doesn't overhaul everything like Angular did. You can have function components with hooks and also have your old class components in the same app.


No ones learning class components for react anymore, and I'm not implying that class components are bad or ancient.


I liked classes to-- their lifecycle methods were so clear to work with.

That said, learning how useEffect replaces lifecycle methods is pretty quick to pickup. As is useState.

The lesser known hooks are what are difficult for me to understand. useRef is pretty clear. useMemo? I'm not quite sure what it's for, but I imagine it's not too tough to figure out if I spend a bit of time learning & experimenting with it.

So, although I liked the simplicity of class components, functional ones aren't too bad. They bring in some additional complications, but with a bit of effort it seems to all be learnable to me.


> when I need to develop a reactive piece of UI I reach out for Svelte

I never used Svelte, but I feel that "develop a reactive piece of UI" is basically Stimulus' job description. Can you explain a scenario/task where Stimulus does so poorly, that you flip the switch and use Svelte instead?


Stimulus was made by people who hate JavaScript and deliberately and pointlessly avoids JavaScript conventions. If you hate JS, you might like it, but I like JS, so I hate Stimulus. My preference is for Alpine.js, but Svelete is cool too.


Howard Lewis Ship kept changing the paradigm for Tapestry every major release or two. He could have had something to take the spot that Spring eventually filled, but these big gear shifts I think left people with a lot of rework and at some point it seems like porting your code to something more architecturally stable is a better bet.

It’s challenging though to keep supporting an API contract that you don’t believe in anymore. Or especially that you are causing you and others pain. I think sometimes maybe the thing to do is pass the baton and work on something else, but we also punish people for abandoning things. Like the author of Groovy, who hopped around from project to project and lost people.


I haven't got the ideas why many frontend jobs require experience in React whether it's for a new or existing projects, maybe I need enlightenment.


Because HR (and IT strategy) nowadays is a farce, managers, decision-makers and the actual organizational units that do hiring rarely have the necessary systemic big-picture knowledge/information, foresight, experience, longitudinal thinking that would allow them to venture out of their preset suboptimal ways.


Talking with recruiters again and can agree.

The worst experience so far was for a general full stack role. They sent me a 3 page long PDF of job "requirements" which was a lot of fluff and implicit stuff. I get it... but I think that can be reserved for later. Not the best offer, seemed like they were disorganized in general, etc.

The best experience was for the best TC offer _and_ most relevant position for me... they sent over half a page that didn't waste a single character. Named a few frameworks but they had a crystal clear idea of what they needed. It was amazing, lol.


Are you suggesting that requiring React experience for a job where you will use React is not a reasonable ask?


It's usually perfectly reasonable, but not really optimal. In this job market requiring React seems worse than hiring someone that is a good frontend developer and has the wits and eagerness to pick up React and whatever tools the team uses, and the job requires.

This has the advantage that when - inevitably - tool1 gets deprecated and tool2 arrives you'll have someone that can adapt and learn, and likely you'll also have someone who can teach.


Probably because a large portion of their app is built in React?


> I ditched React

Did you rewrite your entire app?


my front end is 50k loc, is that medium or small or what?


Amen


Nope, I'm with you. React inventing a half-baked, partial re-implementation of objects/classes (in a language that already has them!) with super-weird declaration syntax & runtime behavior, just to avoid telling their userbase "Ok you will have to use classes sometimes, for certain functionality", was when I started looking around, because they were clearly out of real problems to solve that were sufficiently good-looking-on-a-résumé, and it was just gonna go downhill from there.

Class components were/are just fine.


The cycle of javascript libraries:

* SHOW HN: UberTinyUltra.js Here's my new super light-weight 4k Javascript Library!

* How I switched to UberTinyUltra.js from PopularFramework.js and simplified my life!

* SuperCoolStartup switches to UberTinyUltra.js

* How I built my unicorn on UberTinyUltra.js

* UberTinyUltra.js 2.0 now with a compiler, classes, typesafety and a C++ like turing complete template language to take on the big enterprise jobs because we have too much time, attracted a lot of developers to the project, and ran out of obvious simple features to implement!

* I hate you UberTinyUltra.js you are too complicated.

* ShowHN: SuperTinyMega.js Here's my new super light-weight 4k Javascript Library!


Often, things don't get bloated because the developers are bored, it stems from users requesting features because they are doing it wrong.

Sort of how AWS keeps mucking with Lambdas so that thier customers can keep doing it wrong and paying too much.

Or how doctors just give patients scips if they ask about a drug and it won't incur them any liability.

Over and over I have seen the world shout the praises of a new paradigm that solves a problem...except they totally misunderstand the concept and run in an unintended direction. No one can fight that momentum. So they don't. It happens with nearly everything in tech.


I still remember the Parcel or Prettier saga. The first, the no-configuration bundler, the other, the no-configuration opinionated code formatter.

Then, for their next big major release, the big feature was adding configuration to make it even more powerful!

I haven't used them in a while so my memory might be hazy, but this is exactly the phenomenon you've described. I wonder if it's insecurity or trying to please the crowd that simple niche tools in the frontend end up being configurability behemoths. There's always a time in a JS library where someone decides to rewrite the whole thing and add plugin support, and that's the time that library goes to shit.

Over long enough time you get Webpack, with more knobs than the Linux kernel, and cycles back to a version that tries to be smart and not require any configuration anymore, like 1.0 did.


Well. Life moves in waves, but historically, over a long enough time frame (and if we manage not to kill ourselves), more lessons will be learned than lost, and life gets increasingly better.


React is coming up on 10 years since its release. That world you describe is far from reality nowadays.


Heh. Arguably JS itself "invented a half-baked, partial re-implementation of objects/classes"... _in their class implementation_.

God it drives me nuts that the language will allow you to spread a class into an object and it will take the properties but not the methods.


Oh, absolutely. Pretty much every distinctive feature of prototypal OO is best classed as "please, never ever actually use this". Adding the "class" sugar and general agreement to pretend the prototypal stuff isn't there, though, made JS OO usable-enough. But yeah, it's not great.


Exactly! If the Javascript implementation was better, React probably never would have had to come up with Hooks in the first place.


You can solve the problem Hooks purported to solve in plain, idiomatic JavaScript with classes[0]

[0]https://raganwald.com/2016/07/20/prefer-composition-to-inher...


This thread may have an OP who prefers classes, but I'm for one 100% in favor of hooks. You could struggle and suffer to solve them with classes, or you could move on to something better.


It is purely because `this.state` is hard for V8 to optimize, nothing more and nothing less. They did it for their own purposes, for better performance on low-end machines. You can almost certainly just use classes for 99% of use cases


Hooks had nothing to do with v8 optimizations or `this.state`.

Per https://reactjs.org/docs/hooks-intro.html , the primary motivations were:

- "It’s hard to reuse stateful logic between components "

- "Complex components become hard to understand"

- "Classes confuse both people and machines" (remembering how `this` works, code minification, method binding, etc)

There's also an excellent "Why React Hooks?" post at https://ui.dev/why-react-hooks that gives background details.

Additionally, the React team has talked about how hooks and function components allow them to have "forks" of the component tree in various states of partial completion at a time, for use with Suspense and transition features. This works because closures capture data in a scope, whereas mutable class instances could have gotten changed and refer to a single `this` instance.


One of the few reasonable comments in this thread.

Hooks are better than HOCs, no this is better than managing this, and dependency arrays are better than if (this.props.fooBarBaz !== newProps.fooBarBaz || this.props.onFooBarBazChanged !== newProps.onFooBarBazChanged || …)


> This works because closures capture data in a scope, whereas mutable class instances could have gotten changed and refer to a single `this` instance.

So `this.state` is hard to optimize?

> Hooks had nothing to do with v8 optimizations or `this.state`.

Huh? That's what you just said. The spec makes it hard to optimize. The JIT compiler can't infer enough about the shape of the data.


You're very much misreading what I said.

It's not about "optimization" in the sense of "how fast can the v8 interpreter execute lookups on the class instance" or anything like that.

It's about "when this function executes, what data does it see, and did any of those values get changed out from under it in a way that could potentially break the logic"?


> It's about "when this function executes, what data does it see, and did any of those values get changed out from under it in a way that could potentially break the logic"?

You're just describing the semantics of functions versus classes, and the consideration has existed long before hooks came around for exactly the reasons you describe. This discussion has also existed long before JavaScript, React, or hooks existed obviously. It's secondary to the discussion because function components have existed for a long time.

None of what you're saying changes the fact that replacing classes and lifecycles with hooks was done despite the fact that 99.9% of the API users would never care about the performance implications of classes, while that is precisely why the React team made the change. JavaScript is plenty composable with classes and without nested useEffect calls, which is one of the most absurd foot gun APIs that I have seen released in my entire career.


I'm legitimately curious. Can you point to a single actual source to cite "the React team made the change to hooks because of JS engine performance"? (and when you say "performance", you _are_ talking about literal instruction execution time / JIT behavior / etc, that sort of thing?)

I'm pretty deeply tied into the React ecosystem, and I honestly can't remember _ever_ seeing that mentioned as a justification.

If you can link me a reference with them saying that, I'd both be interested in reading it, but honestly surprised to see that stated at all.


It's just a prop access how is that hard for v8 to optimize? What were they doing to cause that to de-optimize?


Funny that this whole hooks mess could have probably been better resolved with investment in developing optimization patches for v8 rather than attempting to "fix" React


It would be funny if it were true. Hooks were made for composable behavior for components.


How would Facebook convince the community to dogfood their new API without some marketing buzz? It's pretty obvious that V8 has trouble optimizing changes to object properties because of the design of the spec, and they were also pretty open about it in the blogs where hooks were introduced. I think it's also clear that useEffect is harder to grok than it's lifecycle equivalents, so there might be other things at play than composability.

It's also a bit funny that certain kinds of people can just brush off these things with some non-sequitur on a message board when there are almost always bigger things at play.


I was just going off my own experience with React through the years. It was very hard to compose behavior with class based components. We had to create higher order components that had functions as children which could pass down data as arguments to the child function. It really made a mess of the component hierarchy. Now you can create reusable custom hooks that can be used from any component.


I agree with you. It's much better to have useAuth everywhere than having WithAuth capping every class.


My understanding as well though a lot of the details may be perf related..

Ultimately hooks are probably the way they are for the same reason Redux is the way it was(pre RTK I suppose)..


what are you using these days?


Mainly Vue. It's OK and pretty widely used, which gets you decent library support and such. If I were starting from scratch and didn't have organizational/team inertia & experience to consider, I'd probably give things like htmx a hard look.

I'd have to re-evaluate the current Android landscape because it's been a while, but I might still consider React Native only for that platform, because having RN smooth the rough edges off Android dev made it a lot more pleasant and quick, with far less time lost fighting the platform and working around/replacing bad 1st party stuff piecemeal. But maybe it's gotten better-enough in the last 4ish years that it's no longer tempting to drag in RN just to avoid native Android dev.

In general though, I just no longer default to advocating React for highly-interactive sites or "webapps", as I did for a while.


They absolutely do not have their place. Just about everything is worse with class components. I’ll take a dozen useEffects over a single class component any day.

That said, the hooks model is far from perfect. They give you a lot of rope to hang yourself with and were badly introduced. Within weeks the internet was ablaze with terrible advice.

When so many people get it wrong, the library is to blame. And I wish hooks were as robust as Solid.js’ signals model.


I don't think hook themselves are a bad thing. But the way react implements hook probably is. The react team invented their hook format the suite themselves the most, but that probably isn't for other.

Vue 3 also has hook now. But none of these defects in the article exist.

In vue.

To use some value in a effect, you just use it and it is tracked.

If you need to clear up your code. You cut some code into a useXxx function, and your reusable utility is done. You can use it everywhere now. You don't really need to specify dependency of whatever by yourself.

If you must manipulate a dom, you just manipulate it. It will work as long as you revert the change before vue want to update it again.(And vue do provide a hook for you to attach a handler when these happen)

These restrictions are added by the way react implements hook, but not hook themselves. Hooks are just more user friendly services (by allow the hook to attach to component instance without all the glue codes(addListener or whatever))


Vue 1.x was great, v2 lost its way, and Vue 3 with the composition API looks fantastic on paper. (I haven’t used it in any meaningful way)

I’m even more impressed with the extended Vue ecosystem like Vite, Vitest.


> Vue 3 with the composition API looks fantastic on paper. (I haven’t used it in any meaningful way)

Recently worked on migrating a large codebase over from a legacy solution to Vue 3 with composition API, it was a pretty enjoyable experience, especially with Pinia!

Though I'd say that the problem was that most component libraries/frameworks out there actually don't support Vue 3 well enough. Last I checked, only the following were viable with Vue 3:

  - Ant Design
  - Element Plus
  - PrimeVue (went with this, also has icons and a layout solution; also alternatives available for React and Angular)
Most of the other ones considered weren't quite there yet:

  - Vuetify
  - Quasar
  - BootstrapVue
  - Vue Material
  - Buefy
  - View UI
  - Vuikit
  - Chakra UI
I mean, is it really so hard to get a bunch of pre-built components for Vue 3 with Bootstrap, or Bulma? It feels a bit like the Python 2 to Python 3 migration in some respects.


> Most of the other ones considered weren't quite there yet

From what I recall, quasar managed to update very quickly.

Vuetify is currently in Beta for Vue 3 as they went with a greenfield rewrite to deal with tech debt. I rolled it out to a production site recently and it works well.

BootstrapVue completely dropped the ball, despite the corporate sponsorships the original maintainers went missing for a whole year & bailed. It got new maintainers at the start of the year, but they've been delayed by current geopolitical events.


> From what I recall, quasar managed to update very quickly.

This is true, at least there now is Vue 3 support, just checked: https://quasar.dev/

Though I can't edit the original post anymore. Oh well, thanks for clearing that up.


I used it in a few project. And it reduces the code by a lot.

For example. To make a mutex to prevent duplicate submit of form. You use need to declare a instance field and wraps the code that do the submit. That alone is 3 lines of code but don't even include error handling.

But now I sealed it into a one line hook

    const wrap = useMutex()
    const submit = wrap(async () = { … })
And then the submit can't run in parallel now.


> I’ll take a dozen useEffects over a single class component any day.

Someone actually did in a project once and that lead to render loops that were hard to debug or solve: https://blog.kronis.dev/everything%20is%20broken/modern-reac...

Instead of a clear message about what caused that loop and maybe a walkthrough of the last N iterations (which changes caused which logic to be triggered), the error message was just a vague and lazy error (even AngularJS errors were better back in the day, filling in details in the docs as URL parameters).

Then again, over the years I've formed the opinion that both approaches are bad, just in different ways. There is no silver bullet, just look at how even desktop software and UI solutions struggled to be workable throughout the decades, of course things won't be that much better in regards to front end.

However, Vue's approach to hooks seems refreshing: creating and nesting components still isn't as easy as in React, but getting things done feels a little bit less cryptic and not as confusing, especially with something like Pinia!


Class components are great. One thing I did see at my old job, however, was people extending the class components, sometimes 10+ times, which was very unexpected and harder to reason about. With functional components and hooks, you enforce proper composition.


Hooks are a natural progression from class components, class components seem more straightforward with all the willMount beforeMount etc. but they trick you into visualizing your component in different states of mounted/rendered/etc. That goes against what React wants to be at its core, which is totally immutable and pure, it isn't mounted or pre/post-render it looks the same whether it is the first render or the 100th. Ultimately I think the mental model of the component as a pure function is superior to juggling the react lifecycle.


Class components were/are fantastic for training new devs because of how easily abstracted the mental model is compared to memorizing all the hooks and their use cases. Obviously, the syntax tends to be a bit more verbose in general, and I won't deny that hooks making improving performance easier, but at the end of the day I prefer code that's readable whether it was written yesterday or 5 years ago - even if it costs like 20 more lines of boilerplate.

I also think the fear of verbosity in this post is why I can't take it too seriously. Solo maintaining a not-so-old Expo application which uses React Navigation, I constantly have to rewrite large sections of code due to constant refactorings to match whatever coding style is hot at the moment, as the 6 month deprecation deadline is constantly at my doorstep because I have bigger fish on my plate. SO answers being out of date isn't a problem because React is too old, it's a problem because of everyone wanting it to be shiny and new again, and React acquiescing to those demands.

The author does have a bit of a point with libraries, but I counter with Nessim Btesh's fantastic article regarding proper React style[^1]. In short, you shouldn't really be depending on libraries for production needs, just for prototyping.

[^1]: https://nesbtesh.medium.com/how-i-write-react-after-8-years-...


> They have their place.

How so? There is nothing that a class-based component can do that a hook-based component can't (EDIT: Except for error boundaries). I'd go as far as to say class-based components are strictly inferior because they force you split your behavior logic across lifecycle methods and are not easily composable. I've been able to support much more complex behavior easily with hooks (e.g., connection management), that would have been a nightmare with class-based components.


You still need to use class components for error boundaries.

https://reactjs.org/docs/error-boundaries.html


Yeah, this feels like a weird oversight.


A bit weird, although it’s not clear how they would do it without class components. I guess it would probably look something like React.forwardRef.


They could provide a <ErrorBoundary> component as a built-in that just does what the current one does, but is implemented by the library.


Isn't it also easier to get subtle lifecycle bugs with them, because you can forget one.


I don't know that I agree with that. I recently had to fix a few bugs because some devs forgot, or simply didn't know, that lifecycles still exist.

We have reached a period of time where junior devs exist that did not cut their teeth on class components and have no idea of what the lifecycles are. They don't know how rendering works so they either throw up useless memoization everywhere or they don't bother to think of it.

The complexity of class components did not vanish. It was only swept under the rug. Take useEffect. It's overloaded to hell and back. It does too much and people continue to struggle with it. Another one, useRef. It's not really for refs, per se. You will end up using it for data other than refs because function instance variables aren't a thing. No one knows when to use useLayoutEffect or useCallback.

The fact of the matter is that it's not class components vs. hooks. It's that React's API sucks. It's always sucked. And it continues to suck.


> I recently had to fix a few bugs because some devs forgot, or simply didn't know, that lifecycles still exist.

And then it just stays fixed. You don't have to split up the logic across different lifecycle methods and remember to keep them in sync. They're consolidated into functions that can be trivially pulled out into their own hooks and reused.

React is definitely a more low-level framework that requires you to have some familiarity with how the scheduler works, and could benefit from a couple more built-in hooks. But the benefits are undeniable, they make writing and refactoring complex applications an absolute breeze. The fact that you can factor out some state-related behavior into a hook and trivially reuse it is incredible.

For example, take state. With hooks, you use useState. A very common pattern is to need to persist it in the URL to enable deep linking. You can literally just replace your useState call with useQueryParam from the use-query-params library [1] and have your component function identically. You just can't do that with class-based components.

[1] https://www.npmjs.com/package/use-query-params


Oh yeah, that's the worst. Since logic related to a behavior must be split up across multiple methods, it's really hard to tell if you've actually implemented it correctly. With effects, the setup and teardown is in the same function and can be moved around as a unit.


> I'd go as far as to say class-based components are strictly inferior because they force you split your behavior logic across lifecycle methods and are not easily composable.

That's not strictly true. You can implement "hooks" on top of a class based components. It's essentially the strategy pattern.


No, you're not the only one. Apart from useState, which is elegant, I hate others with passion. How can a replacement for lifecycle methods be called useEffect? Seriously?

Great article, couldn't agree more with them.


> How can a replacement for lifecycle methods be called useEffect? Seriously?

Yes, seriously. Have you used it for more complex components? You can split your effects across multiple useEffects, and have a guarantee that they run completely independently of each other (especially since you know what their dependencies are). Compare that to lifecycle methods: you only have one per component. All your effects concerned with setup have to be piled into the same function, and their associated teardowns have to be elsewhere in another method. How do you audit a behavior's logic? How do you reuse that behavior in another component? It's not easy, and you can cause weird bugs depending on the order in which you run them.

Compare that to useEffect. Setup and teardown in the same function, which allows it to focus on just one behavior. And if you need to, it can be trivially pulled out into its own hook and reused across all your components.


Fair enough. Though, the first question is - why does the component do so many things? Do they all need to be in a single component or can you break them apart?

For the cases when this is not possible, I agree, useEffect works better than classes lifecycle methods. But do you really want a system which caters to a small percent of use-cases at the expense of readability in others? And the improvement, to my eyes, is not that big anyway.

The hooks are my main gripe with React, but as the OP, I don't see a better alternative either - at least not one that would be worth a rewrite.


An issue I have with hooks are the names. "useEffect" is one of my least favorite function name in any library.

What am I using? What is the effect?


Yeah, it's not great, but that's because it's extremely general purpose. Its name refers to function side-effects. Since you're writing your components functionally, you need to explicitly declare any effects of your function to be run appropriately. Hence: `useEffect`. The names are super generalized because hooks don't necessarily need to render anything; they're just hooks into the React scheduler, so they can even be used to manage connection state if you want.


> What am I using?

The effect.

> What is the effect?

The state-modifying (and thus side-effect-producing, or simply “effectful”) function passed as the first argument to useEffect.


It's not a matter of doing too many things. Lifecycle methods exist to be used, and the moment you have any behavior that requires multiple lifecycle hooks, you will run into these issues. So I'd say it's not a small-percentage of use-cases at all, and you'll often see the benefits of hooks immediately.


My experience is exact opposite, let's agree to disagree.


I find hooks make it easier to break apart components. With a class component, there are tons of hidden dependencies on those huge components. Maintenance programmers add them relentlessly. When it comes time to refactor, it's often easiest to just translate to hooks and then start breaking things apart. Why? hooks are small and self contained by nature, and they compose nicely, so you can start with a ball of hair and use regular refactoring tools (extract to function, move to file) to decompose them.


That didn't require the meta language and rules of hooks though, they could have added this.addEffect(callback, deps) or something to class components. To preserve back compat they could have added a new base class you inherit from to get access to new APIs.

Most of hooks could have been done incrementally on top of classes.


Imagine trying to debug a component that both has lifecycle methods and reactive hooks? That would be a total nightmare, especially when the same state is being updated in both places (because that would have to be allowed). Going all-in on hooks means that there are two distinct, independent ways of writing components, and you never have to deal with interactions between the two.

I also don't think this would be possible. Hooks are based on closures and injected state, which you can't do in a class since separate methods won't share the closure.


Only if you're constrained by the existing API of hooks. Preact signals is a good example of how class components could have been improved with reactivity:

https://twitter.com/_developit/status/1567272951136788481


useEffect is poorly designed for sure. It's the single most common source of react bugs I've seen and most developers have to refresh themselves on it if they don't use it for more than a few months because it is totally unintuitive.

A lot of third party hooks are really good though, being able to hook a dependency rather than create higher order components saves a lot of time and is conceptually much easier.


I overall agree. I use functional style programming a lot but for some reason hooks have always confused me. The component classes generally make sense to me and map onto other paradigms like flutter, vue, etc.

Sure methods like componentDidMount are a mouthful but I found it much more explicit


In my view, hooks are more about managing state dependencies, rather than functional programming, per se. So they're more useful for simplifying methods like componentDidUpdate, rather than componentDidMount. When you need to detect changes by comparing prevProps to this.props or prevState to this.state, the logic can quickly get really ugly. Instead you can just put the relevant prop or state you want to monitor in the dependency list of a hook, and it will be triggered whenever that dependency list changes.


I think many of us are still using class components and loving it. We're just not that vocal because we're busy get stuff done.


I totally agree. I actually stopped using React around the time hooks were announced. In retrospect it's still not clear if hooks were even a good idea.

Changing the core methodology of a project used by millions of developers at the time was extremely irresponsible. They basically made obsolete all React educational resources overnight. I'm sure people making money by producing React educational content were very happy about that though.


I keep seeing this sentiment here but as someone who’s used both the old paradigms and hooks - hooks are much better and simpler overall.


Your argument is very compelling. /s


There was no way to make async rendering possible with classes. It was necessary and they spent a lot of time trying different approaches that'd continue the old paradigm, but it couldn't be done.


Maybe, but would you need async rendering if React wasn't so slow?


As opposed to what? Vue is slower and Angular too. Perhaps Svelte might be faster but the programming paradigm is a little weird. Writing pure JS is bullshit - I tried it few months ago and even a very simple app - for public transport schedules - got very unmanageable very quickly.

I'm currently working on a project with hundreds of reactive components shown at any given time (very extensive financial analytics/modeling collected from over 500 data sources and real-time updated). Async rendering is a godsend. Perhaps React isn't for you if you don't see the need.


There are literally dozens of libs/frameworks faster than React.

https://krausest.github.io/js-framework-benchmark/current.ht...


Lol, you really think someone is going to stray off the well-supported path for apps like these for 1-10% gain? This app shows a loading indicator quite a lot. Speed is important but nobody cares about raw speed this much. What we care about is a well-maintained library with significant ecosystem that's still going to be there in 2030 and it's super-easy to find devs and/or get help. The libs there are beta quality at best - maybe in few years.


"nobody cares about speed but give me async rendering because React is too slow"


The point is I'm not going to compare against small libs with no ecosystem, slow maintenance, small community and low amount of developers ready to use it - these new libs sound nice but it's beta software, not something to be used in production for apps like I work on. Speed is important but not this important.

What remains is React, Angular and Vue - and out of these React wins by a huge margin, also thanks to async rendering.

I'm looking forward having another look at the remaining libs in a few years.


Just for the opposite perspective, I started using React when hooks came out and I love them. I can write the classes, I often have to for job interviews, but I think they’re a messy abstraction.

Hooks just match the way the React runtime works. Classes are just way easier to do weird bad stuff with. I’m not sure I would ever choose React if it was still class based. I’d use Ember probably which gives you more with the class-oriented API. Without the simplified control flow of hooks, I don’t see what React even offers over Ember or Vue.


I use functional components only for things without state. If anything has state I use class components because otherwise you go mad. ;)


Could you say more about this? I'm not a React user, but to me one of the OO fundamentals is "object = behavior + state". What you're saying sounds so obviously correct to me that I guess there's something pretty weird going on in React-land?


Yes, there is something very weird indeed. Functional components are called every time they're rendered (that's not weird). But they have to maintain state between calls; they can't start over again fresh for each call/render (still not weird). So how do they do this? `const [state, setState] = useState(initialValue)`. You might look at that and think, I see useState being called, so it must be called on each render, so state is still not being preserved between calls.

But here's the weirdness. useState knows whether it's already been called for a given component; this is how it tracks state. The first call returns the state (the initial value) and a setter. Subsequent calls -- occurring after the first render -- do not return these objects anew, but instead reach into a per-functional-component store and return the values that already exist there. Calling the setter doesn't set the state in the body; rather, it updates the value in the store, then triggers a re-render.

If you're wondering just how react knows how to match up calls to useState between renders, it doesn't really. It simply matches them up based on the order they're called in. For that reason, you have to always call exactly the same useState calls on each render -- no putting some in an if statement or a variable length for loop, otherwise they'll be out of sync.

There are a bunch of other "hooks" for use in functional components, but they all work basically the same way: place some data in the functional component's store, then set up re-render (which, again, just means calling the component's function again) to occur when certain data changes.


That is bonkers, to be honest.

I've used React a lot, but only via Reagent in ClojureScript.

I think the JS people are being scammed.


It is bonkers. My number of "accidental" re renders on react are greater than before hooks.

Before at least I knew what was called on boostrap moments. Now everything is run as a side effect when any dependency change. My needs on checking if a prop or a dependency has changed hasn't evolved at all. I just have the core of my side effects on useEffect.


It sounds bonkers, but one of the reasons I pushed for moving my company’s app to React was because the useState hook reminded me of Reagent’s ratoms. I believe that was at least part of their intent. The catch is that you can’t really enforce immutability or atomic updates in plain JS, so they built hooks into the library as a workaround.

There’s not much of a cognitive difference between “defining a reagent component which uses ratoms and calls a pure function that derefs, updates or swaps them”, and “defining a react functional component that uses hooks”. It looks weird to have the “atoms” inside the render function instead of outside, and there are the aforementioned limitations (“the rules of hooks”), but it’s a compromise to get the feature into JS React in a consistent, performant manner.

I’d love to use CLJS/Reagent or even go full re-frame on our front-end codebase, but that’s a hard sell at my company since I’m the only dev who’s ever played with Clojure.


It's sort of what happens when OOP is demonized for years and FP is lionized. They've created what are effectively classes but with implicitly auto-generated private property names and a lot of weird edge cases where things can go pear shaped. But hey, it's functional and 'new' so it's good, right?

In fairness, the JS world has never had well engineered OOP GUI toolkits like you find in the desktop space. If you've never used JavaFX then ReactJS probably seems pretty magical. If you have, then, well ...


You might need to re-read my comment.

ClojureScript is a functional language.

Reagent is a ClojureScript wrapper over React.

Cljs + Reagent is AWESOME.

There is a JavaFX wrapper too, with a similar API.


I know, but you didn't actually say you think React is awesome when not using JS. Given how JS specific React is, that's not a very intuitive outcome.

The comment was in response to "that's bonkers". And that has been my reaction on learning stuff like React and derived frameworks. A lot of it looks like functions for the sake of it, when objects already solve those problems but became unfashionable.


I don't know why Clojurescript's Reagent/re-frame aren't more popular given that they completely obviate the need for hooks or classes.


I think someone should make a Reagent for JS.


But Reagent is built on top of React.


React added "hooks" which are basically methods and properties implemented as FIFO queues instead of lookup tables, with terrible syntax that requires you to declare them inside their constructor (the "functional" component's... well, function).

No, I'm not kidding.

Unless something's fundamentally changed about the code since release, they even end up attached to an object representing the UI component, by the time the heart of React's runtime code considers them. It's some real Rube-Goldberg shit. I read the code because I read the announcement docs and was like "wait, it looks like they... but no, surely they didn't" but yeah, turns out, they did.


What's worse, they have interesting "rules" that one really needs to use a linter so their IDE/Text editor gives them friendly reminders. One cannot conditionally call useEffect. One needs to add all dependencies to useEffect's dependency array - BUT that has potential to cause infinite re-renders (especially when using a getter/setter pattern with useState). They encourage DEFINING functions inside of other functions. Years of CS education and practice go right out the window because some popular JS person on Twitter says, "it's fine".

When pressed about it, be ready to be hit with, "You don't understand hooks".


I agree with the others. I've started using hooks since they were introduced and I've only hit the re-render issue only a few times, which I promptly fixed as they were caused by carelessness. My strategy is to not use a single useEffect, but multiple ones for each (which reduce greatly the dependencies). Also, avoiding dependency circles between useState and useEffect.

I've used class components and I think hooks are much better than the monstrosity that the lifecycle methods would usually become.

Also defining functions inside other functions is very much the staple of functional programming.


>Also defining functions inside other functions is very much the staple of functional programming.

Isn't the difference that JavaScript runtimes don't compile them away unlike functional runtimes?


In React terms, "functional" almost always implies the opposite of purely functional. It just means that the component is declared by a function instead of a class. First time you call it, the function can assign state that it may reference in future calls, not unlike the methods of a class. How they actually go about this is however almost entirely weird.


Classes in JS are just functions anyway, and functions can have state. Saving the state of a function is a different thing, but of course JS allows that, too. Why is it weird?


Class instances are objects and it's the objects that have state. Functions can only abuse themselves as objects to store state.

function johnson() { johnson.state = {}; }

This is however shared state and the state will be reset whenever the function is called a second time. So what you normally do with a function is to pass the state via arguments and now the same function can work with different states. React could totally do this via props or as a second argument.

function Johnson(props, state) {}

Instead they changed the laws of functions so that a function can act different the first time it is called and also be called the first time multiple times if and when the function calls a functions that looks like JavaScript but follow different rules [1].

This is weird.

[1] https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at...


As far as I know, hooks use closures to store state, and that's neither abuse nor weird. Am I missing something?


Functional components are great in that they are more terse, less boilerplate.

Class components just have more lines, more boilerplate, so they have a higher cognitive load. But when you have state, you have more complexity, you can't just wave your hand wave and make it go away. You need to take the complexity into account.

Hooks are trying to do hand waving. The thing is, once you get to non-trivial use cases, the handwaving stops working. You're better off thinking a lot about where you state lives in your component hierarchy, and then limit your state to where you really need it. Once you do that the overhead of class components doesn't really make that big a deal.

The same principle applies to almost everything in programming, the more thought you put into structure, the simpler you can make everything.


I think the problem is ES6 classes just aren't very flexible or expressive, compared to systems like Ruby, Smalltalk, or CLOS. For a lot of programmers, half-assed classes are worse than no classes, even when they can help with organizing state and behavior.


This is backwards. Even in ES6, classes already too flexible and expressive: they allow you to express a bunch of things that don't make sense.


They are as expressive as SELF, maybe time to learn how to use them?


Javascript's prototypes are more expressive than its classes, but still come short of Self on a few levels:

1. Self's prototypes support multiple delegation while JS objects only have one prototype (can be fixed with Proxies).

2. Javascript objects lack a universal clone method.

3. Self is entirely message based, while JS is property based.


I'm definitely a novice when it comes to React, but I've shipped a beta version of an internal took using it. I never understood the emphasis on functional components. Everything I did using them was made more complicated and less obvious, especially for colleagues who are not familiar with React or JS in general.

React is built on components which are objects (both in a programming and GUI sense). Using OOP to describe them just makes so much more sense to me.


Functional components tend to be easier to compose. If your class component has very specific functionality that you won't need in other components it's fine but if you want functionality that will be shared across multiple components wrapping up that code into it's own hook is easier to share across components then trying to use wrappers, extending classes and HOCs.


Can you give me an example? I didn't have that experience. I extended classes for everything and it was super easy. But as I said, I was probably using react in a fairly basic way.


For example you have a button that you want to add a hover effect to. So it's got "onMouseEnter" and "onMouseLeave" handlers that sets a "hovered" state variable to true/false.

If you have that functionality in a class component, and want to share it with a new link component, then the React Class way is to create a "withHover" HOC and wrap your link component in it. withHover(LinkComponent) which will have the necessary variables and pass them as props to your LinkComponent which is "okay".

But what if you have like 5 of these little hooks? Your LinkComponent now needs to be wrapped in each (or them all wrapped into a single HOC) and has to accept the props for all of them. Or, if you're extending classes as you describe you now have class LinkComponent extends HoverClass, ClickClass, DataClass etc...

With functional components you have something like a "useHover" hook. It passes back the hover state and the "onMouseEnter" and "onMouseLeave" callbacks necessary for your link within the functional component itself. It doesn't have to expose props to it's HOC, so it's now self contained.

It seems the philosophy of react is to have a lot of "littler" discreet pieces of code be they components or hooks and not have to have a ton of dependencies between them. You tend to get better tests this way as well as it should make it easier for other devs as they don't have to know the whole system and can work on a more discreet bit.

I, personally, use function components pretty much exclusively these days. If the function gets too big with hooks I tend to just create a single hook from them, not because it's going to be shared but just to keep my code more manageable, the hooks create props and the components consume them.

To each their own. I don't seem to be frustrated by the problems many in this thread and the article share.


Ah got it. I never really had any functionality like that and had few HOCs, so this makes sense. Thanks!


You aren’t the only person, I’ve certainly heard it before. But I’m yet to hear a convincing rebuttal to Mixins Considered Harmful [1], the hooks talk [2] or the Motivation section [3] on the announcement.

The arguments I’ve heard is that it is “cleaner”, “more understandable” or the OO style is preferred. Some developers feel uncomfortable with hook magic because it introduces a more niche programming concept than OO (e.g stateful functions). I don’t find these arguments compelling. What the React team managed to do was reproduce the same functionality as class components while decreasing the footguns associated with them.

1. https://reactjs.org/blog/2016/07/13/mixins-considered-harmfu...

2. https://youtu.be/dpw9EHDh2bM

3. https://reactjs.org/docs/hooks-intro.html#motivation


I think there is more footgun in the hooks, especially rules of hooks. I worked with Junior dev and I can see unexperienced dev misused hooks more often than lifecycle.


I'm with you. I much prefer class components. So much easier to understand and work with.

I disliked hooks after first trying them on their release, and I hate them now.

I'm still bitter that a senior engineer didn't step in and prevent them from destroying the react ecosystem. I wonder if they were have been squashed if React was developed outside Facebook?


Well, unfortunately treating hooks like they're the worst thing since the devil is just the latest (and most humorous) in a long trend wherein a new syntax is added to something, and every developer thinks "okay, the preexisting alternative is now old and bad". I've been scolded many times in code reviews for absent-mindedly making a class-based component instead of using hooks (mind you, this was a legacy codebase FULL of class-based components. Are react developers just undereducated? Considering how many developers I've seen spend MONTHS "learning hooks" I think so. (Not to mention, every single React project I've been on in the last 7 years has been me and some developer who's never used React before, but has a lot of shallow blogpost-driven opinions).


I totally agree with you and you are not alone for certain.


It really rather seems like they achieved a near-perfect library for creating complex web applications, then in order to justify continued work on the project, simply kept making up unnecessary clever/cool features motivated by vibes that classes are passé.


I am in the same boat. I miss class components so much, but because of the trend it is hard to fight for it. It is just so verbose and easier to read. It is more in line with the majority of graphics/ui frameworks in the whole software engineering ecosystem. It reminds me of render loop in many game engines, along with special event triggers (mount, unmount etc.). It makes me feel like an actual programmer, rather than a "view orchestrator"...


I used to be the same when I switched jobs and had to start doing functional. I now disagree that there are ever instances a class is needed. You can use hooks to encapsulate and reuse state, contexts, etc


I totally agree. I just joined a shop that has banned new class components from entering the codebase and I still don't understand why.


Is it possible to continue coding in some early version of React that only had class components?

Has anyone branched that into its own thing yet?


Class component is still fully working as of latest React and won't be going away (at least according to the React docs). The main issue is when you work on a codebase that's full of function components and hooks it's hard to mix in class components.


I really liked the old model where Class Components were used when there was state, and function components were used when there was no state.

Hooks have always seemed so weird. And turns out it's the same for many others.


You are not alone.


me too use effect is too hard to track for anything but the trivial cases, class components are a good midway between being able to understand the program in 3 years and not having to manage one own state<>view mapping


Did you use to work in Java?


Coming from Ruby and Python, I also prefer class components to hooks. I had to deal with hooks enough in Drupal/PHP which is in the process of deprecating them in favor of Symfony classes.


Drupal hooks have nothing to do with React hooks except sharing a name. What would cause you to compare the two?


Drupal hooks are a functional approach to design compared to the OOP approach of Symfony components. As in you use functions to modify/extend existing code instead of inheritance. That's the context of the discussion, not whether they are otherwise similar to React hooks. Anyway, I just tend to think more in terms of making things with classes/objects than with functions.


Sharing the same name, I presume.


No


Maybe I’m a React apologist, but this list of complaints seems mostly self-inflicted.

> Form libraries are portly maintained or documented

The two-way data binding in Svelte saves ~4 lines of reusable hook function but doesn’t come close to covering defaults, validation, errors, dependent fields etc - all of that is essential complexity.

Write your own form field hook. The state model for a form is simple - what is a 3rd party library bringing to the table in terms of state management? I have more pain explaining what I want to a 3rd party library than I do writing a bit of code myself to do the same thing. I reach for open-source input components from a vendor for things like credit cards, but manage the state myself.

> useContext and useEffect have annoying dependency tracking; I prefer Solid’s mutable state and automatic dependency tracking.

React’s built-in hooks are positioned as building blocks with clear-cut contracts. Why dump Redux for bare useContext if you prefer Redux’s selectors? Just use Redux. If you like the Solid style of automatic dependency tracking and mutable state, just use Mobx - it’s a mature library for that style that’s been around for 7+ years, and is used in production by products like Linear and Cron.

Overall I agree that function components in React are difficult to get right for developers and a bit too verbose. There’s an onboarding tradeoff to every abstraction you layer over the framework’s APIs, but there’s large advantages too. Do so judiciously to find the sweet spot for your team & scale.


> The two-way data binding in Svelte saves ~4 lines of reusable hook function

Based on the RealWorld projects, Svelte saves you around 50% in loc vs React.

https://medium.com/dailyjs/a-realworld-comparison-of-front-e...


That’s from 2020 and I’m pretty sure that’s using class components, considering the latest implementations has a separate (using hooks) implementation.


Yeah unfortunately the author hasn't kept making these articles.

You can see the React+Redux implementation here:

https://github.com/khaledosman/react-redux-realworld-example...


To emphasize the dependency tracking part: being able to control when you want hooks to run is really powerful. Automatic isn’t always better


"Being able to write in assembly is really powerful. Higher level lang like java isn't always better"

Sure. but it is better for 99% tasks. And remaining 1% can be achieved via other APIs


Right? If anyone likes 2 way binding they should have tried Polymer. 2 way binding is disgustingly complex for large projects and that's why everyone eventually drops it.


The part about Redux and Context seems to be a complete misinterpretation of what Context is meant for. It was never meant to replace Redux, and as far as I know nobody from the React team has ever claimed something like that. State management in React is a topic discussed to death, there are plenty of options if you have specific tastes or requirements but plain old React state works perfectly fine as well (especially when coupled to server-side state libraries like React Query). But Context is not about state management, it does not seem useful to complain that it doesn't do a job well it was never meant to do.

The part about the Inspector component and the rules of hooks I don't understand. I would have put the visibility state outside the Inspector component, and then there is no need for any conditional calling of hooks.


While I agree that the intent of Context isn't state management, but its functionality in practice is nearly identical to state management.

I know and agree this has been discussed to death, so please be patient while I beat this long-dead horse.

In the beta React docs, Context is described as: "Context lets the parent component make some information available to any component in the tree below it—no matter how deep—without passing it explicitly through props." [1]

In the docs prior to that, they go over how to use the useState hook to manage state [2]. In the paragraphs immediatly following, they describe how to drill props to pass that state around to child components and how to lift it up so it is easier to share [3].

So, while Context may not explicitly be about state management, it's positioned as a way to make managing state via prop drilling much easier. It's easy to see how someone new to React would come to the conclusion that Context is about state management. The React beta docs all but say so.

If the React team doesn't want developers to think about Context as state management, they should not implicitly position it as state management.

[1] - https://beta.reactjs.org/learn/passing-data-deeply-with-cont...

[2] - https://beta.reactjs.org/learn#updating-the-screen

[3] - https://beta.reactjs.org/learn#sharing-data-between-componen...


Context is useful for certain cases, but plain old useState/useReducers are the workhorses. I think the beta docs are pretty good about explaining the tradeoffs (https://beta.reactjs.org/learn/passing-data-deeply-with-cont...).

To me one of the biggest issue is that almost everyone is deeply afraid of prop drilling. Passing props around and having some local state works very well for large parts of many applications. With hooks we don't have deeply nested Higher-Order components anymore, if you pay a bit of attention you can have reasonably shallow component hierarchies and props work very nicely then.

Server-side state is a special case, I find that much easier to handle with something like React Query. But once that is done I don't see much need for any external state management library like Redux, useState/useReducer works pretty well.

And yes, sometimes Context is useful for state that doesn't change much. But those are the cases where the drawbacks don't matter. But that is a special case, not necessary for the vast majority of state.


> To me one of the biggest issue is that almost everyone is deeply afraid of prop drilling.

Prop Drilling is considered an anti-pattern for good reason.

It very quickly turns your project into an absolute mess, making it impossible to determine where props are coming from and where data is actually set.

Keeping that clean is one of the most important things you can do in a frontend codebase imo.


That doesn't make sense, props are easily to follow and they only flow in one direction from parent to children. Excessively deep component structures are a problem, but not only because of the excessive prop drilling they cause.


Except when props are callbacks, e.g. probably a useState combo.


imo this was definitely true in my experience before typescript/solid ide support.

With tsc and vscode, prop drilling has started to make a lot more sense to me.


Yep. The article has some good points overall, but Context was definitely never intended as a replacement for Redux. Redux and Context are different tools that solve different problems, with some small overlap.

Honestly, this is a point of confusion I see folks ask about _every_ day.

Context is a Dependency Injection tool for a single value, used to avoid prop drilling.

Redux is a tool for predictable global state management, with the state stored outside React.

Note that Context itself isn't the "store", or "managing" anything - it's just a conduit for whatever state you are managing, or whatever other value you're passing through it (event emitter, etc).

I ended up writing an extensive article specifically to answer this frequently asked question, including details about what the differences are between Context and Redux, and when to consider using either of them:

- https://blog.isquaredsoftware.com/2021/01/context-redux-diff...


This conflation of Redux and Context as state management is devilishly persistent. As I see it, Redux is [state management] + [prop passing], and Context is [prop passing]. There is no [state management] "feature" of Context. You still have to use (something like) useState for [state management] with Context. As long as people try to compare them as equivalent feature sets, the confusion will continue.


> [React Context] was never meant to replace Redux, and as far as I know nobody from the React team has ever claimed something like that.

I think the conflation came more from the "community" than from the React team itself. Many people were (ab)using Redux for simple cases were Context would have been sufficient and, in the process, paying the price of having a lot of boilerplate related to writing anemic "reducers" whose only purpose was to store things on the global state, and eventually also paying the price of having a ball-of-mud of a global state where no-one could be sure of the dependencies between components, as anyone could be accessing anything on that big ball-of-mud. (Been there; not proud.)

So, when the Context API came along, with a much leaner API (no actions or reducers) and less "global-y" feel than Redux, people who were misusing the latter naturally saw the former as a good replacement


Yeah this. We use Context to apply different themes in a multi-tenant app, and we use Redux to manage global state like the header. Both are great for their purpose.


I spent about 2 years at my last job building a greenfield react app mostly by myself (around 10k sloc). I enjoyed it for the most part. But I did run into all the issues raised here, they are valid. I think the worst issue with React is the dependency arrays that get sprinkled around everywhere - in my opinion the framework is unusable without a 3rd party linting tool that points out when your dependency array is missing something. If you accidentally add the wrong value in there, hello infinite render loop!

One of the biggest level ups I had was extracting complex hooks into their own .js files instead of stuffing next to component code. This helps a lot with readability/reusability.

Overall I liked what I came up with, but it felt like a lot of inventing stuff on my own, which I'm not sure if the next developer who comes along will appreciate.


I think a lot of the problems the author highlighted become more apparent as the number of devs in the codebase goes up.

If one member doesn't understand all of the nuances of useEffect or paint useCallback, they can write a component or custom hook that another team uses and gets subtle bugs from.

For example, I need to look inside of a hook to see whether the callback it provided was wrapped in useCallback. That means I can't truly rely on the abstraction since I need to learn it's internals.


Pretty much this. I've owned entire applications and it's really fun when you're working alone. But adding a new developer that does not grok hooks (mostly because they are more use to imperative patterns than functional ones), and you will have bugs to deal with almost every single day. In a project, I was using Firebase as the backend and hooks allowed me to nicely abstract it away and use a language closer to business domain (like `useEntity(entityId)` and `useCreateEntity(entityData)`). Everything was more modular from changing the backend layer to breaking up bigger components.


I don’t know of any language or framework that guards from mangling a buggy abstraction and then exposing an interface for it.


> hello infinite render loop!

What's funny to me about this is that React people expressed so much hatred for Angular 1 for its "digest loop" and the difficulty of debugging infinite digest loops. And here we are, difficult to debug infinite digest loops in React that don't even give you the courtesy of raising an error after too many iterations.


Hmm… let me be frank about my experiences with React. I’ve been using React heavily for far over 6 or 7 years.

React is amazing. And what I see is that people find so many ways to shoot themselves in the foot. At the same time, I understand that batteries-not-included approach will lead to that result.

First of all, people get out of their skin and try to make it a complicated and entangled mess. In programming, there was always a semi golden rule, to not architecturally fuse your business logic to any particular framework. We logically isolate our app from whatever framework we are using at the moment.

I’ve given the same demo day (task) exercise to ~50+ react devs. Basically two inputs and a button to draw a pattern on an HTML canvas. You wouldn’t believe how many of them (roughly 47) completely and unnecessary implemented most of the business logic inside react components. The sad part is this app doesn’t need react at all. Or could implement 99% of the BL in pure JS and just call one function from React.

React gives an option to store business logic state in `useState` and manage it via `useEffect` and we gladly use that to our demise. Litter our code with singletone instances of a business logic because we’ve “forgot” how to do a DI without a framework. People write `<IF>` components for christ…

Second there is this immutable transducer reselect memoized concurrent proxy suspense state promotion society. Performance zealots obsessing over trillion renders per second. Which they don’t deliver, by the way, beyond todo examples. They describe how their Rube Goldberg flux redux machine works. A machine to read and write data into a JSON object.

In a nutshell, the we should critique ourselves, not the framework. IMO the framework is doing it’s job just fine. Unless we learn what really goes wrong with react projects we are doomed to repeat the same mistake again and again with next (pun intended) framework.


Where are good examples of clean, well-implemented React code by your definition? Because your comment perfectly encapsulates my experiences and frustrations in learning and using React off-and-on over the past 8 years or so.

React is the one tech that really freaks me out because every time I have to dive into it, it's a completely different beast and it feels like so many people actually writing in React are just effing CRAZY

Years ago I wrote a 12-line-or-so JS "framework" that did one-way databinding, it accepted a fragment of HTML with template strings and replaced those with the data you wanted... it could handle thousands of updates without falling over (though updating the whole table would freeze the browser for a half second) and last I checked was still in production doing fine. But now nobody understands it and I'm fielding weird questions about why X framework wasn't being used in 2015 when I wrote it. And it feels like 90% of what I do in React is the same thing! (Simplifying, sure, but my point is that React feels bloated as hell and reinvents the wheel way too much)


> your comment perfectly encapsulates my experiences

> feels like so many people actually writing in React are just effing CRAZY

Same here. We had an experienced-but-batshit-crazy dev create a React site with approximately 250,000 LOC to support 3 forms with a max of 4 simple inputs and a 3-column data table view. To this day it makes my head spin how it is even theoretically possible to write that much code for so little functionality - much less _actually do it_. And don't even get me started on how unmaintainable it is - IIRC I tried to update the string content of an error message once and it required changing something like 57 lines in 10 files (or maybe it was 1 line in 57 different files? something like that...).


> We had an experienced-but-batshit-crazy dev create a React site with approximately 250,000 LOC to support 3 forms

Holy moly. I've seen some bloat but that takes the cake.


They essentially created a unique type for every. single. variable. I'm talking like, if you needed string constant for an error message on Input 1 on Form 3, there was an ErrorLoadingMessageForInput1OnForm3 type declared for that instead of defining it as a string. The types were never reused - like if you had the same error message on Form 2, there'd be a separate ErrorLoadingMessageForInput1OnForm2 type for the same string. And then every interaction between any 2 variables had its own type of types. Like if Form 3 was displaying the error message, there'd be a type for Form3DisplayingErrorLoadingMessageForInput1OnForm3. Which of course, is distinct from Form3DisplayingErrorLoadingMessageForInput1OnForm3AndErrorLoadingMessageForInput2OnForm3. And then those types were combined to create even more types, and so on until you had literally tens of thousands of lines of _just_ type declarations for variables and every possible permutation of UI state sitting atop a recursive pyramid of smaller subsets of the permutations (and so on until it eventually got to actual variable declarations). An then all that was piped through the craziest clusterfuck of redux butchery imaginable with a similar dynamic of explosively exponential growth of references and types and states and properties and so on. Like I said, it still hurts my brain thinking about it.


That's not code written by an experienced dev like you said.

They might have worked long enough to think they're experienced, but this is proof they're just terrible if not a complete hack that's in the wrong line of business.


Yeah...unfortunately they managed to fool me (and the rest of the team) in the hiring process. It was a nice day when they were finally forced off but also unfortunately it's been an ongoing, multi-year scourge dealing with the codebase they left behind. It works just well enough that it's not worth scrapping and totally replacing yet (at least as far as management is concerned) but it's virtually impossible to make changes/updates to it and maintain your sanity.


Sweet pumpkins, I feel the pain. Architecture astronaut combined with a spaghetti aficionado. When one talks to people who have been around you hear amazing stories like that. thedailywtf material


So you're using the code of a maniac to judge an entire framework?


I created a blog and wrote a post as a longer version of a reply: https://dinosaurs-with-jetpacks.com/posts/react-problems.htm...


My god, I've been writing a response and it is already 5K chars.. I need to make a blog post of it or something...

I would love to point to a good repo, but all the apps I’ve worked with are closed source. And I haven't seen a good open one :/

Pinky promise to finish a response here or write a blog post and post a link here. But have to go now to get some sleep


Hi there. I am sorry for a delay, but a promise is a promise.

I created a blog and wrote a post as a longer version of-a reply https://dinosaurs-with-jetpacks.com/posts/react-problems.htm...


I think this is a variation of Jevon's Paradox.

The more power we give to developers - by simplifying, abstracting, optimising - the more they want to achieve, the faster they want to do it, the less effort they want to spend.

Which puts them right back in the position of working under complexity.

The reason people are now complaining about React is that React made writing 2015 webapps extremely easy. The result was our appetite and ambition stretched to 2022 webapps and we blame the framework for making things harder, not ourselves.


I agree. Thanks for pointing it out! Great observation!


Fully agree with you. I think the issue is that people think about React imperatively. "When I press this button, it should do X" or "This input should update Y".

And then people start adding unnecessary useState or useEffect to their demise.

It's hard to blame them honestly. When React is one of the first thing you learn, you don't know the other possibilities. Many probably haven't used any framework outside it. And most probably don't know what problems React help solve.

And when they start developing, they solve problems by using what they know: The React tutorial that taught them to use useState and useEffect for every state and logic.


Got a good example of business logic not being in a component? Looking to learn.


I created a blog and wrote a post as a longer version of a reply: https://dinosaurs-with-jetpacks.com/posts/react-problems.htm...


I was a huge React fan myself but when I started to use Vue and its Composition API one year ago I had tears of joy in my eyes. You have a setup function that is executed exactly once. Inside this setup function you setup your life cycle callbacks, reactive state variables and so on. This is how I wish React + Hooks should have been. Nowadays I won't even accept projects that use React anymore, exactly because of all the pain points OP mentioned.

SolidJS is following the same principle like Vue + Composition API. I think Svelte is also in the same boat. This kind of pattern is so much easier to use and reason about. React Hooks become really painful and annoying really fast.


As someone whose career success was very tied to React, I will say that "quiet quitting React" (or, nonjudgmentally, realizing my longterm interests were broader and taking action on it) has been one of the hardest career transitions I've ever had to do. The money and social validation and temptation to stay within the React-industrial-complex (explaining React to developers who just want the default thing is a very very profitable business) was very strong and I've had private conversations with many folks who got into it not having fully examined their beliefs and now feel trapped in the local optimum of React specialization as a career (which is then a self reinforcing loop as companies see it as a recruiting advantage, leading to devs optimizing for it because companies advertise for it, etc).

React is doing innovative, groundbreaking stuff with React 18 and beyond. I've done several talks on them and will use React when I have those needs. but other folks (I went with svelte in 2019, but i'll also acknowledge qwik, solid, and vuejs) are doing cool stuff too, and most people are usually not building facebook. Ecosystem for React is strong but size isn't everything; once you identify the 10-20 things everyone shouldn't DIY you're basically done (I ended on this at last week's Svelte Summit https://www.youtube.com/watch?v=A8jkJTWacow)


Timestamp ?


I prefer Angular. I never could accept writing css/html in my javascript. To be fair, my background is from XAML, so declaring the state separately and simply binding to it in my html template felt natural. The whole functional approach in React is overkill imo. It's okay if the state mutates in 90% of scenarios. Where there is really benefit from immutable states, I can enforce that on my own.


Yes yes yes! I´ve done some React at my job and also done some Angular/Ionic before. What I never understood of React is why did the creators decided to throw DECADES of Software Engineering development and comingle presentation layer with logic... To separate Views from Logics was an agreed good practice in Software Engineering since I was in undergard school 20 years ago.


I disagree that React is doing anything controversial actually. Angular has logic in it's views, what do you think the handlebars syntax is? The only difference is that they added new syntax to JS instead of adding new syntax to HTML.

And how much logic you put into a component is up to you. Your components can be almost entirely view logic, with any other data fetching or computation offloaded to other regular js files.


That's fair. Why write html in javascript, when you can write shitty javascript in the templates (via ng-if and ng-for)?


Because you will inevitably need to use control flow, conditional rendering, and computed values in your components. And creating proprietary HTML syntax (ie ngIf) to cross reference variables defined in the JS anyways. So why not use JS and gain access to powerful array manipulation, ternary operators, map/reduce/filter functionality, etc instead of leaning on an inferior template syntax?


I actually much prefer how react handles this, I think this very early react talk makes a very good point https://youtu.be/x7cQ3mrcKaY?t=183


I think the title is a reference to this wonderful song by LCD Soundsystem: https://www.youtube.com/watch?v=-eohHwsplvY


How did you manage to share the song without also sharing that amazing mashup?

One of those rare exceptions, where overlaying another song improves the original: https://www.youtube.com/watch?v=huEtJw7pfLk


OP here. I'm glad at least one reader noticed that. You're my hero!

By the way, all section titles in this article are song or album titles.


I define myself a backend engineer, I am not super skilled in javascript and frontend framework. That said through out my career I did some front end work and I went from jquery, angular, react and vue. I must say that Vue was the one library easy enough for me to be productive in few days: I built an entire application in just a couple of weeks. It has now become my go to choice when I have to do fronte work.


Been using React as the view library for 8 years worth of applications that real-time manage fleets of robots worldwide (think config CRUD app + Google Maps + Dashboard + live camera/lidar views + joystick controls).

I generally empathize and see what a lot of authors are saying when they have these commentaries. But I just cannot get past the reality that for all its issues and things worth complaining about, React has never really been "in my way" when it comes to the only goal I really care about: shipping a maintainable product on-time.

I think that comparing a 10 year old library to much younger libraries can be useful in some cases, but is still apples to oranges, given that younger library still has to survive growing up and not having the same claimed fate.


Any general coders wondering about React as their first front end framework - just use Vue. It’s easier, makes quite a lot more sense, has a “one true way” approach regarding many topics and can be comfortably learnt in a day. It’s easier for others to understand your code too.

JSX yuck.


I’m an embedded/backend dev looking to tinker with some frontend stuff for the experience and out of curiosity. I’ve been leaning towards react because it’s so common and what my team use, but I’m finding it pretty hard to get into.


Would you say Vue 2 or Vue 3 would be better for someone venturing into Vue? Also, have you used Svelte much?


Easily Vue 3, the dev tooling/xp + docs are much better over Vue 2.


Oops yes this is a very good point I missed.


Vue 3 is more exciting, but I'm stuck on Vue 2 for my real work due to dependencies. Much of Vue 3 has been backported, and you can use Vue 3 like Vue 2, so it doesn't matter too much... probably go for 3 as it's the standard now.

I've looked at Svelte. I was deterred by lack of ecosystem. Vue's is just big enough to be workable, I think Svelte doesn't offer enough to reach the Vue/React size - probably.


Vue 3. Apart from the fact that it is modern and has more features, It uses proxies, so it doesn’t have the vue2’s reactivity gotchas.


Vue + JSX is amazing


Does anyone do server side rendering these days?

I fail to see the point in SPA apps for the majority of web apps. At my work we have an ancient Dojo frontend and a newer react one being build. Its a few list views that the user can filter and a few forms with validation. It's a ridiculous amount of complexity to avoid loading a page. I could do almost everything for half the effort with server side HTML from Django and a little bit of JQuery.

I ask at my work why we are doing this and no one seems able to give me a decent answer but we carry on down this path regardless.


I feel the same!

I work on regular ol' websites, that have some pages containing some moderate interactivity – so a few years ago the project adopted React to handle the frontend. I've found the experience mostly OK, but I sometimes get the urge to simplify things by leaning more on server-rendering / maybe using the URL to capture state...

and then realize I can't, and that this is Just The Way It Is Now. Because now all our devs expect to use React (or more accurately, its vast ecosystem of 3rd party functions of varying quality) to accomplish anything, and we forgot to screen for hires who can write their own JS+HTML or who understand how the response/request process works in a web application. (oops!)

"React hires are easy to hire for" so that often drives decisions, but I am skeptical my project ever needed React (or any hyper-optimized-for-SPAs-feature).


It just makes adding simple stuff so slow. Instead of a query, and and HTML template, you have a query built on top a shambles of a system that outputs JSON, passes it to another monstrosity that is our Dojo frontend. I have tried to create some static pages, but everything is so baked in to the mess we have, getting around the login is a major obstacle.


You should try again and reconsider if your team truly doesn't have an answer.

Most everyone using React should be using Nextjs or similar level of frameworks. Server rendering comes out of the box. On the other hand, it really isn't too complex anymore. With Next, Sveltekit, Remix, Nuxt, and friends, you get simple, hardened tooling out of the box. And you've decoupled frontend from api which many teams find very helpful to split responsibilities and allow certain features to move at different paces.


> Does anyone do server side rendering these days?

Yes, in React, with Next.js.

I'm going to have to dynamically create html and attach event handlers based on data either way. Much rather do it all in Typescript than remember Django templates DSL and still do javascript, for the result of worse UI's, poor 3p library support, and awful state management between frontend and backend.


Django temples are pretty simple. They are basically HTML with a a few constructs that you can put variables or loops in. Way simpler than React and Typescript.


So is React, but React also provides hooks to manage state in a sane way that is left to ad hoc interaction between random js funcs and django


Or with Remix Run which is great


Hotwire, unpoly, htmx and other html-over-the-wire tools are making it easier to do most of what you’d use react for without the tooling headaches.

https://dev.to/rajasegar/html-over-the-wire-is-the-future-of...


yeah django's approach to forms is not the worst

thinking of forms as a model that can be rendered is really valuable IMO. most UXes would be 10x easier to write if we had better standardization around the 'schema to UX' step

'form first UX' would also reduce the work of building cross-platform apps

guessing django is ramping up on its AJAX, but I think a real forms standard would need to understand AJAX -- users aren't going to remember to scroll down to a 'save' button. realtime validation also an AJAX issue, typeahead as well.


Yes, we are trying to move over to FastAPI, which looks reasonable, but I struggle with the fact that there is no one source of truth for models.

Is there anywhere good to find out what I have been missing out on having not kept up to date with Djano for the last few years? I really miss using it and am looking for a job using it again.


I'm on fastapi with my current project -- I love the powerful type support for interfaces.

I'm using tortoise as my ORM; it feels like sqlmodels is worth exploring as an alternative -- sqlmodels is designed to integrate well with pydantic (so you DRY in messages) and with sqlalchemy (so you get their migration support).

I'm not sure if there's a fastapi / pydantic tool for generating form UX, but it might be doable to write one if not. (though styling could be tricky).

I notice myself still spending a lot of time writing basic CRUD routes. I don't know if this is a tools issue or just unavoidable.

I'm open to a tool like postgraphile to automate API on top of a DB schema, but I'm worried about the loss of control over messages, RBAC, and query design. I wish there were a python tool for mostly-declarative API route stubs -- would be simple to customize, and the purely-declarative routes could be shipped off to a postgraphile-like tool in the future.

I wish fastapi had better auth built in, but then again I wish this about django too -- I feel like I'm endlessly shopping for a third-party user auth server and haven't found it yet. Auth + admin were a huge investment at the beginning of my project, and in retrospect feels wasted.


Yeah actually the front end world at large has been moving away from the SPA pattern...

See Next, Nuxt, Remix, SvelteKit, Astro, Qwik City, etc.


I do. I'm an extremely happy user of Unpoly.


Regarding the Inspector/isVisible complaint:

When you want to have "early return" in a component, it's possible to just split the component into two to introduce an "inner" component that contains whatever comes after the early return point in the original component.

Any local variables from before the early return then need to be passed as props to the new inner component.

However, naming this inner component is always an issue for me. Typically I just name them Inspector2, Inspector3, etc. until I have an implementation that works. Then I can start thinking about how to refactor the implementation into something that I can give sensible names.

It's really a code transformation similar to async/await where you derive a state machine from a block of code by identifying transition points. In async/await you have transitions at the await points; in components you have transitions at the early return points. In async/await, no one is forcing you to name the individual states or even write them out explicitly - the compiler takes care of it. Then why do I have to write out the state machine explicitly and name the states explicitly for function components with early return? I would love for React to have some facility like "Consider the rest of this component as a new sub-component; as if this component now returns a single Element pointing to whatever is in the rest of this component". But it's probably a Hard Problem™.


This is exactly the use case for HOCs and why I continue to be old man yells at cloud about how the "hooks replace(d) HOCs" zeitgeist is missing a key benefit.

Wrapping components lets you have layers that don't have to care about what's going on inside. HOCs just let you write those layers in a way that can be composed. In your example, `isVisible` could be its own HOC, and then the inner component can have whatever name it needs.


...and that's why I switched to Vue nearly four years ago. Best professional decision I've ever made.


Are you finding much "professional traction" with Vue? I really like Vue and use it for personal projects but React seems to dominate the job postings.


Less jobs, less developers. It adds up.

Also, building a team is much easier. If you bring six React developers around a table, they will have six different ideas about the parts of the ecosystem they like and use.

Six Vue developers? They’re ready to kick ass from day 0.


Vue is mostly used in China, where there is a preference for Chinese tech.


That's probably not the reason why it's heavily used in China.

More likely there was some early draw based on Evan You being the figurehead and eventually a community that built up Chinese language documentation around it that made it more accessible to Chinese developers.


This is true. I'm a Chinese developer and I have saw too many developers here using Vue because of it's good Chinese documentation. I used both Vue and React in my projects, I think one advantage of vue is it makes some concepts explicitly. Like the computed property, its more obvious than the way you do it in React. Vue's document is simple at the early days of the framework, that made it more accessible to new comers, especially people who was trying to migrate away from AngularJS, and didn't want to take Angular 2.x.


Really? What are they using for things like containerization, observability, testing, or even compilers and operating systems?

Really curious if there's an alternative word for all these core tools in the west.

From my understanding Vue was heavily adopted in China because it was the only major framework that had its docs translated into Chinese by Evan himself (initially at least). Guessing this isn't accurate nor the case?


Vue isn't "Chinese tech".


One could argue that it's not that React can't handle increasingly complex situations for you and that's why you spend more time on them, but that frontend as a craft has evolved due to React having solved the easy parts and has raised the bar, and therefore these complex situations belong to the next breeding site wherein the community is arguing about new solutions all the time, at the current time. It's healthy to retrospect how we got to this breeding site, yet there's always a certain doubt or even bias that what brought us here today is not what takes us forward tomorrow. It's like the reverse of Shiny Object Syndrome.

In time, I believe React can still take us forward.


What React does is no longer novel. People have both cloned React and have made other libraries/frameworks that accomplish the same thing differently or even faster in some cases.

Frontend craft has also become too complex in general. We really need to step back and decide whether all this fucking shit around SPA, SSR, route splitting, transpiling, everything-as-a-type, "me too" features between frameworks, overemphasis on trendy designs, package managers that wrap around other package managers, REST or GraphQL or RPC, etc. etc. etc. Much of which serves mostly to create corporate careers for developers more than to actually serve users.

React takes us forward in the sense that most of us don't want to go back to direct DOM manipulation or jQuery, and it's simple enough that it doesn't come with the same baggage as Vue, Angular, Ember, and so on. Even if React itself were to fade, the institution that is React I think will continue on for the foreseeable future.


> React takes us forward in the sense that most of us don't want to go back to direct DOM manipulation

There was recently a demo of what a Todo MVC app might look like if written in vanilla JS with today's apis. It looks fairly decent; I could see myself going back to something like that:

https://frontendmasters.com/blog/vanilla-javascript-todomvc/


It's definitely feasible and even pleasant to write a frontend app in vanilla JS, if it's relatively simple. I hate to be that guy, but... does it scale?

Perhaps it can. I haven't really tried to write a large scale frontend app in vanilla that is similar in complexity to apps I've worked on that have millions of users. Maybe it's feasible, but it would take a lot of dedication to "do things right" by the developers on the team.

Also, reactive templates pretty much kill any desire I would have to by relying on direct DOM calls. With something like React or Svelte alone, there's practically no disadvantage to using them even strictly for rendering besides added file size. With vanilla, it would take more effort to make things efficient because you don't necessarily just want to call render() whenever something changes. It's really nice having a templating system that allows you to change things surgically without doing a lot of extra work rerendering things that shouldn't actually change.

However, I think vanilla JS rendering definitely has a place in terms of writing small, purposeful, modular components. Frameworks should make it straight forward to use vanilla components so that things that would be more succinct in vanilla can be written as such.


> Much of which serves mostly to create corporate careers for developers than to actually serve users.

I'm a developer that's done with this, but it brings in VC money so in my experience it serves mostly to create opportunities for CEOs to get some more money on the table via buzzword pitches.


As an early beta user, I also agree. I think the issue with many modern libraries is that they don't know when to stop. Like that guy who keeps adding visual mods to his car, or that TV show that keeps creating mediocre seasons.

I took a risk on React back when there were minimal components and zero form libraries and started fading away from React once hooks were added. Redux is still pretty nice, and overall still use React because I much prefer it to anything else. But we're definitely in the long-term bloat phase which you can tell by the popularity of things like Vue, "React Lite" libraries being built, etc.


I was using React earlier for many years, but nowadays Svelte and SvelteKit (file based routing). I feel I am more productive (might be an illusion), but at least I am less frustrated.

More here:

https://kit.svelte.dev/


Is Svelte still overly dependent on Rich Harris? He's great but that reliance put me off Svelte.


He was recently hired by Vercel to work on it full time so I wouldn't be too concerned about the future of Svelte


I believe there are at least 3 full time core developers now.


The 'issue' with forms and front end is that we cram the entire kitchen sink into the front end code, handling everything about them via onChange: validation, error messaging, options etc.

There's very little need for a

  onChange(e) => setFormValue(e.target.value)
and all the extra work that comes with that.

There is an absurdly simple solution which removes all the 'cruft' the article bemoans: use uncontrolled form elements that then send the form data to the server and have the server do the validation, error messaging etc.

In this approach, the client gets back into the business of pure network calls. When the server sends back a response parse it and update the UI. This is trivial with some conditional rendering of error messages, styles etc.

But rarely is this done. This approach is why I really like using Remix. It encourages this paradigm by coupling the server side code that runs on a form submission in the same file as the client side code.

All this becomes blissfully easy.


Function components are a useful tool, but for the life of me I can't understand why the community currently builds everything with them.

A lot of React code I run into these days would be simpler and less verbose with a traditional (non-function) React component.


Mostly because functional components are understood to be the direction the framework is headed, with class components still supported for backwards compatibility reasons only.

They'll almost certainly never go away without a major version bump because it would break way, way too many sites, but at some abstract level people feel class components will have a shorter shelf-life than functional. And certainly, any given third-party integration to React in the future is allowed to just say "We only support functional components" (with the corresponding hit to popularity, of course).


Thanks for commenting about the community sentiment.

Interesting that you didn't comment at all about my take on functional components not being the best tool for every job in React. Curious – do you have an opinion?


If I understand correctly, the team is pretty clear that if they had written React from scratch today, they would have gone with functional components and not class components.

The major issue is life cycle. When is a class component instance created or destroyed? The answer is "whenever the framework feels like it," and that's a really ugly model for instance life cycle. Additionally and most importantly, it means that member variables on a React class component instance don't work the way that members are expected to work; you just can't rely on them having any particular value because the framework can create or destroy an instance when it feels like it for performance reasons. What good is a class and instance abstraction if when you try to use member variables (one of the key features of object-oriented programming) you're highly likely to just break the model in hard-to-debug ways?

Because the framework isn't using class component instances like instances are supposed to be used, the React team is tossing that model to the curb.


It's less code. And if you add hooks (for the reasons specified in the docs), you can have a smaller and more manageable codebase. But hooks differs so greatly from the easier to grasp lifecycle methods and state as component object's property that it's easy to have bugs if you do not grok it.


Since quitting React I've been happier with my day to day. Phoenix Liveview came in clutch and showed me I don't have to put up with these kinds of self-inflicted problems.

If you're tired of React and the npm lunacy, I recommend you take a dip into Elixir and Phoenix Liveview. Take it for a spin, see how much better it is for you and your users. It's _sane_. You don't have to "split the context" anymore. xD


What are some resources (book or courses or videos or blogs) you'd recommend for learning Elixir and Phoenix?


I can recommend this book currently in beta, that has been pretty good at keeping up to date with most developments in LiveView.

https://pragprog.com/titles/liveview/programming-phoenix-liv...



Easily these three courses: https://pragmaticstudio.com/

Phoenix Liveview, Elixir & OTP, and Full-stack Graphql with Phoenix.

Best way to learn Liveview.


Give react-admin [0], the post author’s react framework, a glimpse. If you develop an ERP/CRM like react app, you‘ve probably rebuilt parts of react-admin already, but you did it worse. Ah, and their source code is a breeze of fresh air.

[0] https://marmelab.com/react-admin/


If you are using that many refs you built it wrong - from the React documentation (https://reactjs.org/docs/refs-and-the-dom.htmlhttps://reactj...

"There are a few good use cases for refs:

  Managing focus, text selection, or media playback.
  Triggering imperative animations.
  Integrating with third-party DOM libraries.
  Avoid using refs for anything that can be done declaratively.
...

Don’t Overuse Refs:

  Your first inclination may be to use refs to “make things happen” in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to “own” that state is at a higher level in the hierarchy. See the Lifting State Up guide for examples of this."
If you are using refs to talk to your child inputs you've made a mistake. React talks about RAISING THE STATE - for complex forms you need to make all of your inputs controlled, you need to manage the state at the highest level. You need to push those changes down to child components, none of them should have their own state.

React gives you some nice tools to handle most common use cases but you can still make less than optimal decisions.


Salut Marmelab

The best way we found is a custom useForm hook (simple to code, using useState's):

    const { submit, getProps, isLoading, error } = useForm({ onSubmit: cb, initialValue: {} /*optional*/ });

    return (
      <form submit={submit}>
        <input {...getProps('firstName')} />
very flexible, you can use other wrappers than form or input

react-query is another super useful lib, you could use useMutation() for implementing useForm actually


We tried to use other frameworks but finally came back to React for only one reason. It's easier to hire for React. The talent pool for React is almost 10 times that of other frameworks.

And for now, this reason is good enough for us.


Vue is learnable in a single day. React is almost as easy to learn.

Just hire React devs and give them a couple of days with Vue, no problem


There is a difference in being able to write something that runs and writing idiomatic something which uses all the libraries idiomatically that runs.


If you think everyone, with React on resume, is in the latter category, then I have a bridge to sell to you.


It's more than a couple of days but I have done exactly this and it works fine.

In general Vue holds high conceptual similarity to React so React devs just "get it" straight away. However nearly everything is simpler / easier than it would be in React, so they learn it extremely fast.


Good point. But then again, if the engineer is good, switching between say React, Vue and Svelte shouldn’t be too hard. EDIT: To clarify, I mean picking up one of the three if you already know another one.


I 100% agree. I find it troubling that people are 'hiring for React'. How does a developer possibly learn React without learning the core concepts of HTML, CSS, Javascript and thus adapt to any library? It doesn't make sense to me at all.


That would seem so right? I thought so exactly too. This works when your engineering team is small. But once you go beyond the first level of engineering and its mostly maintenance and updates, the people who apply for the job are not interested in learning new things. They have learnt one thing and want to apply that skill 9-5 and go home. For those roles hiring for react is easier.


I really hope React doesn't handle dependencies automatically. There have been many frameworks that have done that in the past. It does not end well with an application of any decent size.

A pre-compile step that statically adds dependencies to your code might be a reasonable compromise, but those dependencies do need to be explicit.

The rest of the stuff makes a lot of sense though.


Why not? Having to manually manage the dependency array is tedious: in fact, not specifying a required dependency is a logic error anyway, so having the compiler do it is basically preferred in all cases.


Because the dependencies for hooks have to do with re-rendering the component or recomputing the value, not with the usage of the dependencies themselves. That cannot be inferred by the framework without taking a one-size-fits-all approach that probably fits no one particularly well.


Huh? react-hooks/exhaustive-deps does exactly that: it statically infers dependencies and is very noisy if you forget one, and the React team recommends that you always have it on. In fact, the React docs have this to say, right in the documentation for useEffect (https://reactjs.org/docs/hooks-reference.html#conditionally-...):

    The array of dependencies is not passed as arguments to the effect function. Conceptually, though, that’s what they represent: every value referenced inside the effect function should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically.


The useEffect dependency array defines the values for which you want the effect function to trigger any time those values change.

It is not always the case that you want an effect to trigger for every value used inside of an effect. Sometimes you only want an effect to run once (i.e. the empty array passed as deps). Sometimes a value changes too frequently to list as a dependency: https://reactjs.org/docs/hooks-faq.html#what-can-i-do-if-my-...


Not to mention some of those variables auto-included are pointers to arrays/objects which won't trigger a change if their contents change, so you actually need a hash (or something more clever and specific) of the contents which should trigger a re-render... e.g. rendering the contents of a list sorting would want to listen to the 'sortBy' state rather than the list contents - even if the component wouldn't have used sortBy otherwise...

(this is all just bringing back painful memories - hopefully which aren't the same problem now? - from a project where I was the only developer on the team learning these intricacies, and having to figure out why everyone was getting infinite render loops or static components in weird situations, even as they blindly followed their linter useEffect suggestions... Needless to say, our code lucked ugly as hell after all this was done "right".

In retrospect I might have done all this at the app state level, pre-processing the inputs for each component with something like a 'usesEffect' boolean and a 'changeTriggers' array, then some generalized auto-reader util functions to parse that with default boilerplate behavior, just to get that stuff out of my frontend components... I suspect that would only move the problem up, but at least then you're just modifying json instead of also muddying all your templates. Subcomponent wrapping or something like that could work too. Idk. Gross stuff. Was unfortunately necessary with a ton of asyncronous calls and big data lists.

Maybe DB/API-fetched State > Frontend Parser & useEffect/Async Logic > Actual JSX Component Rendering separation...? (so - Model Controller View?) If it wasn't all already inherited legacy code mighta structured it like that more, instead of just rawdogging API results in JSX.


The documentation you linked itself says to structure your code such that you are not taking dependencies inappropriately, not to omit bona fide dependencies from the dependencies array:

    Specifying [count] as a list of dependencies would fix the bug, but would cause the interval to be reset on every change. Effectively, each setInterval would get one chance to execute before being cleared (similar to a setTimeout.) That may not be desirable. To fix this, we can use the functional update form of setState. It lets us specify how the state needs to change without referencing the current state:


React is bad in the same way C++ is bad. It's not really, but it does take a while to learn the ins and outs. In the end, the pattern React provides is much more powerful when used right. But it's not a one size fits all, a lot of the time you don't need the flexibility if you're new to it and just want to get something done.


React and other client-side frameworks are great for apps where you need a highly responsive UI, but for many websites, server-side frameworks (Rails, Django the many spinoffs) are easier to write and maintain than SPAs. Yet there seems to be this idea that every "modern website" must be written with a JS framework like React.


I'd like to know how a newcomer would feel after reading the tutorial of the monster you created, React.

Take React hooks at its purest for example. I can't imagine the WTF feeling in a newcomer's mind, when the useState(<default-value>) helper function returns the "reactive" variable and a function you have to use to update it (!) do you realize how tricky you end up with your technical DOM optimizations?

Same with useEffect(), where you probably will have your whole function defined right into the first argument, and a list in the second one, very lost in your IDE. Who would expect that an empty array of dependencies would trigger it once? Why we should track all those dependencies at first place?

When recommending a frontend framework, I found Vue to be more dev friendly. However, it's currently in a long migration crisis, because documentation shows the 2 different APIs you can choose. I know that the differences are well explained (although they don't even say that's to be retrocompatible with Vue2 mindset), but for a newcomer's mind, it's like asking: which pill do you want to take? red or green? Choose your own adventure!


The thing that has kept me tied to React is the support for native mobile and desktop development. Expo has been a really nice environment for mobile development compared to some other things I have used in the past. EAS is also pretty handy. It looks like Svelte has improved in this area, but my past experiences with NativeScript were not very inspiring. Is anyone using Svelte for production mobile or desktop development?

What are peoples thoughts on Svelte vs Solid? I know Lit/native web components are out there as an option as well. I have past experiences with it when it was Polymer.

If anyone is looking for something very lightweight they may want to consider Alpine as well.


I’ve tried Svelte, but it seemed a lot harder to work with than React. Solid on the other hand is very straightforward. It has a hooks-like appearance, but it’s quite different as functional components are executed only once, so you don’t have silly dependency tracking issues. If I had the time, I’d throw myself into a Solid project.


> And I thought that reference counting was a native feature of all languages with a garbage collector. But no, I have to micromanage dependencies myself because you don't know how to do it.

So annoyingly enough... There's not anything inherent to the language that makes it impossible to get a list of closure references for a function, other than it's not something JavaScript exposes. In a hypothetical future version of JS, this could be a first-class feature of the function API.

... because what JavaScript really needs is yet another feature to support one framework's special-caee needs. ;)


> There are two kinds of programming languages: The ones people complain about and the ones nobody users

- Bjarne Stroustroup


> What's next for us? You tell me.

I'm gonna say something crazy here, but hang with me: hypermedia.


didn't it fail like 20 years ago, why do you think it'll succeed now?


unfortunately HTML didn't make any significant progress as a hypermedia for a decade and a half, but some folks (myself included) are trying to fix that (unpoly, htmx, hotwire, etc.)

an enhanced hypermedia model offers a lot more interactivity often at a fraction of the complexity, and w/ the benefits of the REST-ful architecture (flexibility, etc.)


to draw a desktop app analogy, I guess these things need a back-end as a GUI application that has to deal with all the presentation logic, and thin client that remote desktop to that. While the current SPA model would be RPC with fat clients, your call.


Throwing my message in a bottle here, in hopes someone can answer:

What is currently the best way to handle the complexity once you have a ton of asyncronously-loaded JSX components which have complex conditional rendering logic based on multiple inputs and datatypes? (including defaults, local variables, and all kinds of other stuff)

At this point I'm inclined to just handle all the data processing logic and when-will-it-render logic in some intermediary controller and then keep the visual templating barebones and strictly separated, though it feels quite un-React-like to do this, and almost more trouble (and certainly more boilerplate) pushing vars through the stack and separating Controller / View than to just let my JSX be messy with useEffect hooks. I suppose this is when I should use a React class component? Or a subcomponent? Or a custom hook..? Or maybe I should just modify (global) state - even grosser from data duplication perspective, but at least then all the data processing is in one clearly defined format instead of scattered throughout templating files.

Last I checked (and burned out) this was the major React hurdle, and the downside of React's simple-by-default templating. This complex stuff got real ugly real fast. What's the elegant solution here, if any? Any improvement?


I'm happily using React as a low-level renderer (using Reagent) - I would welcome splitting this codebase up into a pure DOM-diffing renderer and state/event handling on top.


How has nobody mentioned the insane complexity monster that is React 18 / Suspense?! I mean, it makes sense once you understand it, but who is going to understand it?

React's concurrency features should have been broken off into a separate, opt-in library, not packaged into React core, and they sealed their own coffin with this release. That said, suspense is awesome once it's fully understood. Give the public a few more years to get it, though.


suggesting the concurrency features can simply be broken off is evidence that you may not understand them as well as you imply.


Sorry, to clarify: What I'm suggesting is that React 18's changes were substantial enough to have been broken off into a separate library, not maintained inside of React. I don't mean to diminish the teams amazing work here, but they're overkill for 90% of the developer community who are already having a hard time understanding all of the abstractions that have made it in since hooks were added. All of this is _overwhelming_ given how simple React was at one point in time.


Amen. React 18 was the moment where they forgot they started as the V in MVC.

Concurrent React was a mistake, and the hooks they had to add to make it work too.

The main example I always cite of where the React team is naive is mousemove handlers:

- there is no guarantee that react will re-render between two mousemove events

- even if it did, creating a new mousemove handler after every move is ridiculous

- avoiding this using the `setState(s => s)` form doesn't work if you have multiple pieces of state or need to invoke other callbacks

Therefore, every mouse dragging UI I've built has used useRef instead, mutating state directly.

The answer from the react team to this seems to be.... nothing. They just say it's bad to mutate state and that it will lead to bugs, seemingly not realizing that so will useEffect for the reasons above.

I think OP is wrong, and that people who have never built an app with undo/redo don't know what they're talking about when it comes to front end dev... but the React team is definitely chasing the wrong ideas.

Also, forms utterly suck as a UI, and every form abstraction I've ever used was terrible and ran into a wall. It just seems pointless to try to optimize for it.

If some people want to make forms easier because it's most of what they do day to day... hint, they're atrocious front end developers.


> Amen. React 18 was the moment where they forgot they started as the V in MVC.

Yep, exactly.


Concurrent react actually makes your app less concurrent: https://github.com/facebook/react/issues/21668

5yrs in progress, it’s still not documented let alone fixed. I tried to look at the code, and they make giant PRs and are experimenting with priority queues and bitmasks, which seemed pretty off in the weeds to me.


Oh wow. I was always skeptical of "concurrent React" (the scheduler approach seemed insane to me), but this seems like such a basic issue, I'm surprised this ever shipped in any form.


Yeah, it seems suss AF.

IIRC it also only bales out during the DOM update phase; not during the calls to render() and then reconciliation(?). And if it bales out, it has to re-render everything again when it comes back to make sure the state is consistent(nothing has changed).

The exact details are fuzzy and that may be incorrect but the impression I came away with after reading an engineering post about the deets was that:

* The risk of thrashing seemed very high

* Debugging performance issues seemed like they were going to be a nightmare. Worse than right now. Worse than hook hell.

This line from the song Taro comes to mind: "Do not spray into eyes. I have sprayed you into my eyes.


> it also only bales out during the DOM update phase; not during the calls to render() and then reconciliation(?)

It's exactly the opposite.

React splits work into two parts: the "render phase", where it loops over components and asks them to describe the UI they want (returning JSX/elements); and the "commit phase", where it has determined the changes that _need_ to happen to the DOM.

The render phase is the part that can be split into many pieces. React can render a few components, see that 5ms has elapsed, and yield to the browser, then pick up where it left off and render a few more components. Or, it could render some components, pause, see a high-priority user event happen like typing into an input, and set aside the partially completed render pass to go re-render based on the input update. Then, after the input render is done, it can pick up where it left off with the other partial render, "rebase" it onto the current UI contents, and continue from there.

The commit phase is _always_ synchronous, start to end, and that's where the actual DOM updates are applied.

Some more details:

- https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-...

- https://github.com/reactwg/react-18/discussions/55

- https://reactjs.org/blog/2022/03/29/react-v18.html#what-is-c...


Thanks for the correction and references.

Sounds like a nightmare.


Not sure what you mean by "nightmare" - can you clarify?


* The risk of thrashing seemed very high

* Debugging performance issues seemed like they were going to be a nightmare. Worse than right now. Worse than hook hell.


I think you're really misunderstanding how React works here.

There's no "thrashing" involved, in the sense of "make DOM update A, then need to make B that reads layout or does reflows right after".

- React does a render pass based on a state update, compares the element tree from this render vs the last render, and determines _all_ the necessary changes to make the DOM match the newly requested UI

- It then applies all those changes together, synchronously, in a generally efficient way (ie, modifying just specific attributes to existing DOM nodes if possible, vs recreating the DOM from scratch)

Which "performance issues" are you thinking of? Excess renders? DOM-specific reflows?


As someone who built a product that is a form builder that uses React, https://keenforms.com, the best thing I can say is this;

Most of these libraries are fine for simple to medium complexity forms. However once you cross a certain level of complexity these libraries become impediments rather than tools. I probably could have used a redux implementation but build my own state management API with a mixture of object oriented as well as functional programming. The values of the inputs persist so you want objects, but hiding/validating/calculating need to be reset for each change so I used a functional approach for these other features.

React is not perfect and its easy to paint yourself into a corner. However as someone who used to write js for IE6 and has forgotten more js libraries that you can imagine (Dojo, ExtJS, Backbone, Ember, etc) I can tell you right off the bat its the best tool for the job. Not perfect, just like Javascript. Just know and accept its limitations and you should be able to get React to do what you want.


Can definitely agree with his pain point about forms. I've been through most of the libraries, and the one I liked the most was Formik, because it felt like I could actually get something done. react-hook-forms is beautiful when it works, but the documentation is byzanthine - even when I know exactly what I'm looking for (and I've seen the page before), I often can't find it.


Formik hasn’t been updated in years, is riddled with bugs and performance issues, and very likely will never be updated again. Not what I’d want in a JS library.


What are the bugs and performance issues? I’ve been using it for years without problems.


a library that has re-render issues due to its architecture. but there are solutions for this like FastField https://formik.org/docs/api/fastfield


this is an unpopular opinion, most people including myself would say the opposite. react-hook-forms seems pretty natural and closer to html form & plain javascript, while Formik is (was?) this bizzare thing that forces jsx and controlled inputs upon us devs.


Yeah, I agree that react-hook-forms feels much more natural and straightforward to use compared to Formik. It's just a shame it's so poorly documented.


What is poorly documented about react-hook-form? I like the documentation a lot, and it's creator is EXTREMELY responsive regarding github issues & discussions and on their discord as well.


I think the documentation is usually pretty great if you can find it. Somehow I never seem to be able to.


I keep saying we need a state-ful GUI markup language standard so we don't have to re-re-re-reinvent real GUI's with JS+CSS+DOM. Those weren't meant for real GUI's and retrofitting creates bloated, buggy, ever-changing messes. GUI's have been around more than 30 years, why can't we network-ify its common and loved idioms?


I know it's not the point, but you can generalize the input handler in the first example by using the name of the input field as a key — in most simple forms, at least:

```

const Form = () => {

  const [formData, setFormData] = useState({ firstName: '', lastName: '' });

  function handleChange(event) {
    const { target } = event;
    const { name, value } = target; // Destructuring in steps to make it easier to figure out where values come from.

    setFormData({
      ...formData,
      [name]: value
    });
  }
  

  return (
    <>
      <input name="firstName" value={formData.firstName} onChange={handleChange} />
      <input name="lastName" value={formData.lastName} onChange={handleChange} />
    </>
  )
}

```


even better, wrap those props as

    <input {...getProps('firstName')} />
and make a custom hook returning that getProps function


what about Vue? its html approach(instead of React's fully JS approach) seems more beginner friendly to me as a non-frontend professional, is React (much) harder to learn relatively speaking(comparing to Vue that is)


It's time to make server side HTML templating trendy again.

I think frontend technology took things too far.

Imagine the possibilities of using HTMX and any server side technologies like Elixir, Go, or Rust.


Waiting for React Recoil to become the standard, it's amazing!


I've been using it for the last two years. Don't you feel it's quite low-level and also quite problematic to have to keep thinking about caches all the time?


I have never used Recoil. How does it compare to Zustand?


Recoil = Jotai (mostly equal.) Check out the comparison doc https://jotai.org/docs/basics/comparison


recoil is a winner


apparently they lifted atoms


Using an opinionated library can help with some of these issues. Personally, I love https://mantine.dev.


I doubt web devs would ever accept React as the de facto JavaScript framework and we definitely shouldn’t if it wants to keep evolving but most of the articles against react these days seem to be the equivalent of frat boys negging and mocking woman just because it’s the cool thing to do.

I’m sure there are some good points being made out there but those points Are getting lost in the noise which is a real shame.


Relatively new react developer here (still learning in fact!), I liked this article although it shook me a bit and made me wonder "am I wasting time with some of this stuff? maybe I should be looking ahead to the next 'best framework'". Id be interested in hearing people's thoughts: what would be best to learn for maximum applicability in the ~3 year timeframe?


Hmm. Toughie.

React kinda ate the web world well, so it's not a terrible bet that it'll keep it going for 3 years...

If you like data layer / DB stuff (and if you're strictly a frontend dev) my suggestion is to just get comfortable with SQL / Postgres / SQLite, and just dbs in general, as that stuff has remained pretty darn stable for a while. Only really replaceable by even-simpler (though less versatile) approaches like giant plain key-value stores, file-system-style storage (NoSQL), or added versatility to Excel spreadsheets (lol it may be more viable to let companies just keep using those than moving to a DB nowadays just to let office workers use what's comfortable). I learned SQL 15 years ago and still glad to have it now surprisingly - though it's maybe sometimes more powerful than I need. But good value there.

For frontend: JS, React, npm, docker containers, maybe Vue?... that's about as deep granularity as I'd go for predicting what'll keep another 3 years. Libraries, state management, all the tooling, etc etc - you'll probably relearn more than 3 times over during that... Welcome to (a hopefully well-paid) hell.


It's easy to second guess your tech choices based on various thinkpieces and comments when you're new. React will still likely be the top framework in 3 years. There are a lot of powerful network effects in being one of the oldest component based frameworks in JS. It's also held up strongly in the nearly 10 years since it was released. That being said I do agree with other comments that you should consider yourself a web/JS/HTML dev first and foremost independent of any framework.


Depends on what you are learning for. If it is for a job, then react has the most openings by a large margin and will likely stay like that for a while.


Don't call yourself a react dev, it's unlikely this framework will be around in 10 years time (see what was popular in frontend dev 10 years ago). Call yourself a developer and try to learn the core tech, if you're a web developer that means javascript and html.

All these libraries are built on JS, understanding JS is the safest bet you can make.


Learn the theory, not the framework.


Completely disagree. Theory is useless without application. For some people, the best way to learn is to start making projects immediately. Theory will come later.


lol this is the wrong job for that. Join a game development team that uses assembly and C and cares about filling a gpu efficiently if you want to learn real programming. Here theory is philosophizing about the best way to organize a garbage dump to take our mind off the shoveling.


Useless rerenders are really hard to avoid in the latest react, mostly because they changed the rerendering logic of useTransition, breaking some of the state abstractions built on top of it. Had to downgrade and started to think about using class-based components again. Hooks are very beautiful but too weird, weak and leaky as an abstraction, unfortunately


You mean they changed the edge-case performance characteristics of an experimental alpha API? It feels hard to get up-in-arms about that.


I don't think you especially need to try to prevent useless re-renders, as long as it doesn't slow down the app


This kind of thing is exactly why my old boss went and created his own minimalist framework built around using native code: http://www.domxjs.com. Its explicit purpose is to allow developers to learn and utilize the platform, rather than learning a bunch of libraries.


Hardly any mention of Ember in the comments. Is it no longer considered a viable alternative to React?


I’ve been using React ever since that David Nolan article and ridiculed Ember all the way. Now I’m wondering if maybe I need to give it another look.


I haven't had the opportunity use Ember much, but I like the philosophy that it's built on (and its original author, Yehuda Katz has a pretty good rep as a solid thinker).


I love hooks, but the main problem with hooks is that when you have a problem, you usually have to fix it in hacky ways. hooks were a revolution yes, but since the foundation was quite weak, everything they added on it unfortunately made it worse.


Props to marmelab's react-admin, and the ng-admin that preceded it.

If you need CRUD without adopting some "low code" platform and its half dozen containers full of weird databases, react-admin is a fine choice.

I have wondered what svelte-admin would look like.


React Admin works really well with Hasura (there's an adapter) for whipping up dashboard apps.


When ppl whine about Swift UI, this sort of post kinda seems to highlight that growing pains issues are perhaps similar across the board.

The difference is that Microsoft languages may have better ppl working on developer documentation, who knows...


I’d argue, although this can happen with other frameworks, the high level of abstraction makes it worse with React. As soon as you’ve signed up with that ship, you’re going down with that ship.


the fundamental issue with hooks is that it's too hard to ensure you have access to the latest state inside the hook. why would we ever want something other than that? react has failed us.


Come to the dark side, we have cooookies https://github.com/cheatcode/joystick


I took a very brief look at your project. I saw reams of documentation, which is good, but not a single FAQ or a comparison table answering perhaps one of the most important questions to somebody who's already familiar with existing frameworks such as react, angular, and vue, which are:

What distinguishes your framework?

Who should use it?

What does it do? And more importantly, what doesn't it do?


> but not a single FAQ or a comparison table

This is on my list for the 1.0 release. Unofficially...

Edit: You motivated me to rough something out, take a look here: https://tinyurl.com/joystick-comparison

> What distinguishes your framework?

Simplicity and stability, primarily, and second: scope.

The current crop of frameworks seeks to overcomplicate APIs and are indecisive about how things should be done (as evidenced by the introduction of patterns that are "the way" one day and then a few months later are "deprecated"). This leads to a lot of confusion at the community level which makes it hard to build software that can endure overtime (I came to this conclusion through teaching developers and realizing how much time was wasted chasing the proverbial rabbit of indecision).

Even worse, these frameworks introduce their own languages/syntax which are foreign to what a beginner would learn (HTML, CSS, and JavaScript). This not only creates confusion and slows down the learning process, but it also creates the long-term nightmare of developers not understanding the fundamentals of the tools they use to build. Eventually, you hit a drop-off point where people think that, for example, JSX is HTML and in a pinch where they can't use React, are ineffective or incapable of completing the task properly.

By contrast, Joystick is designed to be stable, long-term, from the beginning (i.e., no random "hey, we're deprecating all this stuff you depend on for this more confusing API that's less descriptive"). It's also based on the core technologies of the web: HTML, CSS, and JavaScript. I don't introduce any hacks or sytnax tricks to render the component. It's plain HTML, CSS, and JavaScript. This means that the transition from learning the basics of the web to shipping apps is far smoother (and an individual developer is less likely to make mistakes/get confused as everything looks consistent with where they started).

I also intentionally designed the component API to be fixed long-term. So, a component you write in Joystick today will look the same 10 years from now. My focus will be behind the scenes, improving performance and security. This matters less to developers and more to businesses (my target) as a lot of time and money is wasted on developers who are more focused on tinkering with technology (and making messes) than actually building the thing they're supposed to build.

For scope: Joystick is a full-stack framework, not front-end only. The UI part (@joystick.js/ui) is designed to snap in to the back-end/server part (@joystick.js/node). The advantage is that you're not wasting time trying to stitch together disparate parts that may or may not work together (or even worse, may or may not be supported long-term).

> Who should use it?

SMBs, startups, and freelancers/contractors. For SMBs/startups, it's a solid framework for shipping custom software for your business (or a consumer/b2b SaaS) that you can rely on long-term. So, build it today and maintenance is limited to some patch upgrades and new features/improving existing features. Never a surprise refactor being plopped on the roadmap, distracting you and your team from delivering value to customers.

For freelancers/contractors, remove the overwhelm of juggling a bunch of disparate codebases across clients that each have their own shifting requirements (i.e., standardize what you ship, full-stack). This allows you to take on more work, but also, make your long-term support more predictable as the framework you're building on isn't going to rug pull you down the road. This allows you to build a better business with happier clients.

> What does it do? And more importantly, what doesn't it do?

It allows you to define routes on the server which when matched, render some HTML, CSS, and JavaScript using a component framework that's a light abstraction over those core technologies. It also makes it easy to define a JSON-RPC API that can be called directly from components, giving you complete transparency into the flow of data between the client and server without any ambiguity. In addition, it adds the necessary wiring to start and connect drivers for databases to your app, piping those drivers to where you need them (namely, your routes and your API endpoints/handlers).

The back-end is just a plain Express.js/Node.js app so anything you can do in a standalone Node project, you can do in Joystick without any limitations. So, if you want to use a third-party package, just run npm install <blah> and it will work.

All of this is backed by a built-in SSR/hydration implementation so all you have to do is write your routes, API, and components. No time wasted on wiring the front to the back-end. All of that is automated via the lightning-fast build system built around esbuild (which is implemented/configured out-of-the-box) so you can just run `joystick start` and get to work in a few seconds.

Thought it sounds obnoxious, what Joystick doesn't do is get in your way and it isn't a ticking time bomb of deprecation. It allows you to actually focus on the product you're building, long-term.


Tangentially related: https://xkcd.com/927/


The number of people who have sent me this exact meme for daring to offer an alternative is quite illuminating of why it's so hard to make progress. Not picking on you, but dogmatic thinking is why OPs article even exists.

Don't substitute memes for thinking. Evaluate what I've built on its actual merits.


Respectfully, I don't have the time or interest to, and to be quite honest while I am qualified to implement just about anything you want in vanilla JS, jQuery, [old versions of] Angular, React, or Vue2, I'm very likely not qualified to judge a brand new one on its merits other than just a superficial comparison to the ones I've used before.


So why post something snarky and try to discourage me?

Serious question: what was the motivating factor that made you take the time to reach for that cartoon and respond to me with it?


It's a joke - and a pretty common/unoriginal one at that. Calm down.


Don't tell me what to do. You acted like a clown and got busted. If you're going to open your mouth, be able to back it up—otherwise sit down and be quiet.


The biggest problem I have with React is that it’s not reactive.

And the biggest problem I have with hooks is that they make functional components non-functional.

This is starting to look like a pattern… :)


I have a message from the future. The JSParty podcast episode 244, recorded live but not part of their feed yet, is "Is React only great at being popular?"


What do u think about https://mol.hyoo.ru?


Yeah... my opinion use the DOM... it was a great invention... Mustache and JS class with async,await - really what more do we need?


I just use Remix and use React in it's simplest form. Working for me so far but it might not work for big complex apps


I use next.js with react and typescript and mostly it's a good experience


love the way this is written


Agree with a lot of this, but, some quibbles:

1. yes, un/controlled forms are messed up and need work

2. yes, contexts should replace Redux and Redux should go away. but in practice having a few contexts is pretty manageable. Currently we use Redux for all the dynamic state and contexts for everything else and it works pretty well. It is quite easy, also, to write your only little `useSelector()` wrapper around a non-mutating context value (ie: the context has a callback on changes, you listen and filter updates, then update a `useState` to trigger rerender)... but but maybe this a bit too abstract to actually want to do.

3. yes, forwardRef is silly.

4. yes, useEffect is kinda broken. My main issue which wasn't discussed much here is that the difference between `useEffect(..., [])` and `useEffect(...)` is insane. The latter should not exist, or have a different name entirely.

Otherwise, I really don't mind tracking deps _that much_, although I hate that it's hard to have an effect that updates 'on some local variable changes but not others', so in practice I pretty much ignore the lint warnings all the time.

It all feels like "there's a DSL waiting to be written for this stuff, similar to how JSX makes createElement() more ergonomic, but it doesn't exist yet".

That said, Solid doesn't seem like the answer. Solid's even worse: now you're using JSX for if/else statements, instead of the actual DSL you want that doesn't exist yet. Good luck running a debugger on that. (Although actually, if the Solid AST ends up in the Devtools view, that's pretty good. But still: this needs a fully-featured DSL).

5. +1, yeah, the continuing addition of weird hooks feels like a mistake that will eventually be regretted.

6. The right way to do your Inspector example is to have a parent component that decides whether it's rendered, and a separate child which does all the event listeners. It is a bit weird to me that React doesn't allow this to be done in one place. The closest thing is defining another component inline in the first one and then immediately rendering it. But for readability it's best to just have two separate components.

7. +1 to old docs getting in the way. I'd love to see a React 2 with a new name that deletes all the class component stuff entirely so that all of the docs about it are up-to-date. I've been toying with trying to work on this myself.

8. Yeah, fuck FB

9. Yeah, I'm not going to any of the other frameworks either. React is great, it's just ... not... great enough. I am in the middle of writing a series of blog posts about exactly this and I haven't finished yet but anyway here's the first one that I have written about why I like it so much? https://alexkritchevsky.com/2022/09/17/react.html


Nice blog post, the part about jQuery UI is spot on. There is lots of talk here about how a bit of jQuery is all sites need, but it always turns into a giant pile of complexity when writing all of the transitions rather than just the state that you want.


> Dear React.js,

> We've been together for almost 10 years. We've come a long way. But things are getting out of hand. We need to talk.

> It's embarrassing, I know. Nobody wants to have that conversation. So instead, I'll say it in songs.

Am I the only that finds this open letter format extremely cringey? I almost didn't want to read the article after that intro. The content was excellent otherwise.


By the same extension, would you consider your comment worthy of the same classification of "cringey"? How you feel about the delivery is not relevant to the topic, and if you had opted not read to it, it would not be the person in the arena that would be at a loss because of it.


> By the same extension, would you consider your comment worthy of the same classification of "cringey"?

No, but I think your comment falls squarely in that category.


Ah, the ol' "no, you are" response. The mark of quality conversation.


Have a great day! Hahaha


It may be due to the codebase I'm working on, but I doubt it since I assume I have decent colleagues (I'm in a FAANG), but I just fucking hate React.

I spent years working on Angular before changing team, and there everything makes sense instantly. It's just normal programming, normal MVC, normal everything, and you basically only need to learn about the syntaxic sugar for data-binding and stuff like this.

In React it seems like they reinvented the wheel and they thought a circle was too easy so they made it in a 5 dimensional shape. You have 18 ways of doing anything and they are all deprecated, your logic and your template are mixed which turns your application into an unreadable mess, every single aspect is overengineered to death, requiring you to call useState() to have a fucking boolean that you can update, everything is stored in a variable or declared as a function instead of in classes, etc.

I'll have to give a try to React from scratch where it's not on an existing codebase, but I don't think that's the real issue.

It's been more confusing for me to go from Angular to React than to learn a functional language after years working with imperative ones.


Funny because every time I need to work on anything angular I'm constantly thinking how over-engineered everything is and how much simpler it is in react.


Sure, if you have only a very basic 1 page website with no routing, no backend calls, no components to reuse, etc. React will be a simpler and better choice.

If you have anything more complex than that, like a real web application, Angular is an actual frontend framework, where React is just the modern jQuery.

Angular is for software engineers, React is for web developers.


Thanks for confirming Angular is over-engineered.


Have you read the article?


I have an Angular 1 app I built in 2015 that's still in use today. Went back to it and it was refreshing in so many ways.

A lot of people really hated it but it's opinions and structure helped promote a more maintainable codebase. I don't miss tuning watchers and the digest cycle though.

All the React projects I've inherited are nightmares. I'm comfortable working on them but they are harder for junior and mid-levels to hop into.

The number of ways to do things in React is a benefit and a curse.

We had so much prop drilling early on. The idea that components should only have what they need is nice, but you need some data to flow to children. And when the UI needs to change on a prop drilled codebase, holy shit, refactoring is a major PITA.

Luckily we have some alternatives to avoid the prop drilling but it's so fragmented.

If something like Mobx was just part of React from the beginning, the ecosystem would be in better shape IMO.

I identify with a lot of the issues the author stated.

React is just at that place where you need a TON more discipline to produce quality code in a team environment.

And because of that, there will be a mountain of shitty codebases in React to inherit, cleanup and maintain over the next 5 years.

That being said, I'm still a big fan of React and Vue though.


Have you given a try to Angular 2 and above?

Angular (Angular 2+) is honestly lightyears ahead of what AngularJS (Angular 1) was, so if you already preferred AngularJS over React, Angular will be a walk in the park.

I feel like a lot of people who talk about Angular being bad are actually talking about AngularJS and have never tried the newer versions.

For collaboration and onboarding new people, it's hard to do things badly in Angular, and it's easy to refactor when they are done badly, so it's a great choice.


Have not tried it yet but curious thanks for the info.

I kind of just shifted into Vue and then React after Angular 1.

Most of my team has never used Angular and the components available for React are so nice I'm a little hesitant to invest in Angular.

I also have yet to inherit an Angular codebase so I have to weigh the time investment.




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

Search: