Hacker News new | past | comments | ask | show | jobs | submit login
Things you forgot (or never knew) because of React (joshcollinsworth.com)
526 points by inner_square on Aug 15, 2023 | hide | past | favorite | 629 comments



> Vue uses a templating language closer to default HTML than to JSX, which makes it much easier to write conditionals and loops in template files, without having to reach for workarounds like map and ternaries

I like react/jsx precisely because I can use language constructs like filter, map, reduce, etc, instead of a custom implementation of basic things like if statements and loops. I find this much more ergonomic and didn’t realise some people see this as a “workaround”.

Worth also pointing out that when you write these templates, as strings or template literals, they might resemble HTML in appearance but really have no relation to actual HTML except what they output after processing. All of the added directives also have no equivalence in HTML. You’re just writing JS indirectly.


This. Most of the value-proposition of JSX is that it is just JavaScript and as such you just write code logic like you would normally do. Need to filter some items? You can do that with the Array.prototype.filter method you already know. Do you need to return a list of components based on some list of object values? Just use Array.prototype.map.

I never really understood those that see this as a weakness and would rather learn a more limited set of template string functions that work kind of like, but not entirely like, the native JavaScript collection functions.

Yes, using a ternary operator in JSX to conditionally render components/values looks a bit ugly, but nothing is stopping you from making a wrapper component like:

<If cond={...}><div>Conditional content</div></If>.

Also with JSX/TSX scopes behave exactly like they do in regular JavaScript, because it is regular JavaScript. Templating languages often invent their own form of scoping mechanism.


> nothing is stopping you from making a wrapper component like...

I'd suggest avoiding that, since the inner JX expression will be evaluated even if cond is false. In the best case this just means some unnecessary allocations, but in other cases it can cause unexpected errors (e.g. you check obj != null then try to use it inside the if).


> ... the inner JX expression will be evaluated even if cond is false.

Well, actually. it don't have to be. Just React decides to compile JSX in that way.

Vue 3 also supports JSX. But it keep the content of children lazily evaluated.

Their compiler compile a JSX `<Parent><Child /></Parent>` to structure like `h(Parent, {}, { default: () => h(Child, {}, {}) })` . So the child jsx tag is never evaluated unless the Parent component want to.

It's really not a syntax limitation because JSX never specify that the children of element must be eagerly evaluated.


> It's really not a syntax limitation because JSX never specify that the children of element must be eagerly evaluated.

That seems like a dangerous reinterpretation of JSX. It's just a literal syntax, it's not meant to be lazily evaluated.

Having a JSX compiler interpret <Parent><Child /></Parent> as h(Parent, {}, { default: () => h(Child, {}, {}) }) would be like having a JS compiler interpret

   let parent = {
     child: {}
   };
as

   let parent = {};
   Object.defineProperty(parent, 'child', { get: () => ({}) })
That's just... not what that syntax means. It should be

   h(Parent, {}, [ h(Child, {}, []) ])
Saying 'JSX doesn't specify it' feels like playing a 'there's no rule that says a dog can't play basketball' card.


It's a framework specific DSL anyway. (Unlike e4x, which is actually a standardized feature). There isn't a spec decides how it must be interpreted. And it also don't matter as long as the specific framework that use jsx output standard javascript that browser can understand.

In practice, every framework interpret jsx in slightly different way. React has own. Vue has own. Solid has own. And even react itself interpret JSX in 2 way (the new and old jsx compiler). So I feel there really isn't a rule that you can't compile jsx in some specific way because the output is never part of the specification of jsx from the beginning.


Interesting, I haven't used Vue so I wasn't aware that some frameworks do it differently.


Good point. You'd have to pass the stuff to be rendered as a function that would be run if the conditional is true. In any case you just add another allocation, scope (the anonymous function), etc. But some people might like the "syntax" a bit better.


Yeah you have to do

  <If cond={...} then={() => 
    ...
  } els={() => 
    ...
  } />
so the `then` and `els` branches only get evaluated if needed


We use ternary extensively with in JSX. Keeps the logic in vanilla JS

{ some_condition ? (

  <H2>It was true</H2>
) : (

  <H2>It was false</H2>

)


Even though I'm a JS programmer myself and I do use similar constructs once in a while, I have to admit that this gets dangerously close to the Greenspun's tenth rule... In times like this I miss proper Lisp macros.


Which has ugly untax IMO


> Yes, using a ternary operator in JSX to conditionally render components/values looks a bit ugly, but nothing is stopping you from making a wrapper component like:

Couldn't you put that in a function that returns the correct JSX element or am I misunderstanding the problem? Something like:

  renderThing(number) {
    if(number > 0) return <div>...</div>
    return <div>...</div>
  }


  const Page = () => {
    return <div>{renderThing(someNumber)}</div>
  }

Simple ternaries are fine IMO but thats what I do when the logic gets complicated. I never used a nested ternary in that situation, for example.


You have to be careful with code like the above in React. Using a lower-cased function that returns JSX but is not rendered with react.createElement (either directly or via the JSX syntax) can lead to confusing violations of the rules of hooks as it relates to exact ordering of calls.

This is because it doesn't get registered as it's own component, so conditionally called children with hooks may cause errors.


The render function is a pure function returning jsx based on the input, not invoking any stateful operation like "functional hook".

So this style of code is fine in react


Does simply uppercasing it avoid these concerns?


Plus, the power of being able to treat JSX as any other JS object means that you can use standard JS constructs like loops - slightly contrived example:

  const items = [];
  let runningTotal = 0;
  for (const item of someArray) {
    runningTotal += item;
    items.push(<li>Item {item}; running total {runningTotal}</li>);
  }
  return (<ul>{items}</ul>);
The closest example I can find in Vue would require a computed property to implement something like this.


Disagree. I would argue your example is hard to read compared to the equivalent in Vue, and it mixes business logic (computing the running total) with the rendering logic.

  <script setup>
    const items = [1,2,3,4,5,6]
    let runningTotal = 0

    const getRunningTotal = (item) => {
      runningTotal += item
      return runningTotal
    }
  </script>

  <template>
    <ul>
      <li v-for="item in items">
        Item {{item}}; running total {{ getRunningTotal(item) }}
      </li>
    </ul>
  </template>
No need for a computed property. Plus, getRunningTotal can be unit tested, or extracted to another file for reusability.


You've still mixed the logic, just in a horrendously oblique manner. If you rendered the list twice the second list's running totals would be wrong from re-use of the global variable (in what is meant to be render-only logic).

If you're after keeping the concerns separate you would need to precompute the running total for each item.

See also: mustache(5) which completely embodies this philosophy.


Extracting function to separate fine in react would be equally easy . You just extract and import it.

It is just that above example is so short and readable, that you don't have to bother.


Does syntax highlighting or lsp stuff work for things like v-for?


Yep. There's a vscode extension.


I don't think this is a good way to build JSX from lists. Better to keep components smaller. Also this way will show React linting rules, like the "key" requirement.

  return (
    <ul>
      {someArray.map((item, idx) => (
         <li key={item.id}>Item {item}; running total {idx + 1}</li>
      )}
    </ul>
  );


It's technically possible, but it looks horrible and should be avoided because of lack of readability. Keep the templates plain and simple, and store your business logic elsewhere.


I liked JSX a lot when I was using React. However, writing business or view logic in templates is a maintainability nightmare. With JSX it's very tempting to do this and I did this often, but it's still a mistake and I regretted it every time I visited my spaghetti JSX months later.

When it comes to comparing React with Vue or Svelte, the templating is not the critical factor.


The JSX bits in a React codebase aren't templates, at least in the traditional sense where a template is a static file that looks like some desired runtime output and contains some "slots" which are analyzed at build time (or program start time) and then filled in with dynamic values at runtime. JSX kinda looks like that, but there is actually no "templatey" stuff happening at build time, i.e. React does absolutely no analysis whatsoever of your JSX and has no idea what it contains until each new time a component renders at runtime.


Stricly speaking it's a render function indeed, but it does serve the same functional purpose as what people usually call "templates", i.e. defining a dynamic view only once.


That’s true, but the technical differences between a render function and a traditional template is arguably the biggest fundamental difference between React and most other UI rendering tools.


I totally agree. Templating is not the critical factor indeed. The templates shouldn't contain business logic so they should be simple by default. If not then you're following an anti-pattern.


I get using plain JS, but JS's lack of expression-statements (see rust for contrast) just makes most of it EXTREMELY awkward.

Ternaries, booleans that cast to JSX, switch statements wrapped in IIFs...


Once you try any languages where (almost) anything is an expression, it is hard to accept statement-oriented languages


That's true. But in JSX you have the extra constraint that you can't really use imperative code so this magnifies even more.


Indeed, having if-then-else being an expression (as well as switch) would be great in JSX. It seems there's a proposal for a match expression in TC39...


The crazy part is that there's not a really good reason why we couldn't make if..else function as either a statement or expression depending on the context. I think there's a proposal to do that.


Indeed, at least there's a TC39 proposal for that. It should be the default for all statements and it's shocking that python went to define the new match clause to be just a statement and not an expression


This discussion never ends. It's so subjective and totally not important at all. Templates shouldn't contain complex logic anyway, only formatting logic with some for loops. You can learn any syntax in 30 minutes if needed. The battle isn't fought on the hills of templating logic. It's sad because there are many interesting differences other than templating logic between frameworks, but they are less superficial so they get little attention.


But you want to avoid using to much code in HTML, because this isn't "page.php?page_id=welcome" anymore..


Especially with copilot, which is clearly well trained on React and JS, I find I often just need to write the first few characters of an array method or other common method and it will generate 10 or so LOC that are at least 90% of what I want.


In practice with Vue you tend to write that stuff in JavaScript (eg in a computed property) and keep the HTML as simple as possible.

I've done a lot of Vue and your bit of React and overall I prefer the Vue way here.


You know you can use JSX with Vue right?

https://vuejs.org/guide/extras/render-function.html


GP was reacting to this statement from the article:

> Vue uses a templating language closer to default HTML than to JSX, which makes it much easier to write conditionals and loops in template files


In defense of those directives and template languages, they compile down to efficient operations that every developer can take advantage from. I like that `v-for` is likely more efficient in regards to how it operates than how an average developer might write such a function, especially when dealing with nested data or more complex situations. Other efficiencies can be gained by using a template language as well via the compiler.

Not that you can't with JSX (Solid and Qwik use JSX and have transparent ways of doing optimizations as consumer of those frameworks) but its not currently the default, most (if not all) optimizations must be done "by hand", is a big tradeoff for some places.


This can be the case, but as I understand it typically isn't so, at least with most big frameworks. For example, I believe Vue templates are typically translated to a hyperscript-like render function that has a similar efficiency to the average React render function. Indeed if anything, I would imagine Vue would be slightly less performant, because the v-for loop is quite abstract and can handle things like looping through objects, so there must be a reasonable amount of machinery to handle all the different loop cases.

The state of the art is less about handling things like loops, and more about reducing the amount of work needed to render static elements. For example, say you have a single component that renders a static table, and in each cell of the table you need to render something dynamic. In the classic vdom system, you'd construct a `table` node, with a `tbody` child, which in turn has `tr` children, which was contain `td` nodes, and then finally in the `td` nodes you render the dynamic content. This works, but most of the content isn't actually changing, only the contents of the `td` nodes. What modern frameworks like Solid and Svelte do is to compile that whole nest of nodes into a single HTML string, and then add instructions that specify where exactly the dynamic content lives. That way, on the initial render, the browser is doing more work natively, and on later updates, only the new content needs to be checked and changed. I know there's a library for React that adds similar capabilities there, albeit with a few more constraints than in other frameworks.

I do know Solid does for-loops differently than in other frameworks, but this is less to do with efficiencies gained by compiling, and more about how to optimally use the signals system that it uses for reactivity. Apart from that, I don't really know of any optimisations that would make something like `v-for` any faster than `.map(...)`.


the Vue compiler does do optimizations you can't get if you were to write the components by hand, most of the time.

I did only use `v-for` as an example of sorts though, and in the common case, `v-for` vs a regular `for` loop are similar if not the same, IIRC, but in some cases where your children may show or hide based on downstream data, it can be more efficient


In general I really like React but after spending years tinkering with JS and seeing my codebases rot away faster than I could keep up due to ecosystem/tooling churn (I started in 2014 when React was ES5 and still using mixins), I started replacing my frontends with regular server-side rendered ones. I enrich these with vanilla JS and some smart things like using async fetch and the history API to seamlessly replace content when clicking links. There are of course solutions like HTMX or Turbolinks that do similar things but it's really easy to make something simple work with just JS.

With some of these tricks the resulting application feels very similar to a real SPA. Of course if you're really building an application in the sense that a lot of the computation and state handling happens in the browser you will still need to use JS, but even then I would just go with vanilla JS in most cases. That said my experience is from building mostly CRUD-like apps alone or in small teams, so I can see the benefit of more complex toolchains in larger organizations.

But yeah, browsers and JS offer so much out of the box, most people don't seem to realize how easy it is to do cool things without relying on frameworks.


Ok so this is topical for me right now. I somehow managed to avoid the world of react since it became a thing. All the code i was writing was pre react and we kept the old frameworks, and that’s was all good and well.

Fast forward to today, i took over a project that is full react. What a mental shift. Having said that, sometimes i love it, sometimes i hate it. A friend put it best when he said “i struggle to predict what might be trivial and what will take a full day or two”, and that’s my experience too.

I found myself just the other day wishing i could await the setting of a state variable, it was making saving a file in a complicated form a little difficult. I found a work around but i don’t love it and i know the next time i come back to work on it I’ll be scratching my head at what i was trying to achieve and why i did it this way. Naturally i over commented my rational here.

I do miss writing in basic js and server side code, it’s probably slower over all, but i do miss it for the simple things being predictably simply and the hard things typically being predictably hard.


You don't need any of it. You can write vanilla JS, using ES6 classes, as web components and be done with the whole front-end framework game. All you need for data-binding is an Observable of some kind that can loop through listeners for events and call their handler. Component classes all have a render function so that React kids feel at home. Those components are registered using CustomElementRegistry.define [1]. Tools like vite help roll up all that code and styles into a minified bundle but doesn't include all the crap that these "modern" frameworks add. Take this from someone who has been writing web sites since 1996. You don't need any of those frameworks unless you're looking to give away control of your product to the roadmap of the framework or need to hire a bunch of people to accomplish something quickly and all they know is React.

[1] https://developer.mozilla.org/en-US/docs/Web/API/CustomEleme...


I'm assuming that someone who "took over a React project" isn't trying to remove all the react from the project. They did mention they found both up and downsides compared to their old work.


> You don't need any of those frameworks unless you're looking to give away control of your product to the roadmap of the framework

Have... Have you seen the roadmap for web components? 20 more specs just to barely patch holes in the original design: https://w3c.github.io/webcomponents-cg/2022.html


someone should write up some documentation for the standard APIs and how to use them but then give the website a name. People would think of it as the next amazing and shiny JS framework but, in reality, it's no framework at all just a name. That would be good medicine for the front-end dev community.


er, so is the advice here to write your own framework instead of using a framework? because writing and maintaining your own framework is not a trivial exercise and is a massive project on its own, which is why a lot of people reach for a framework in the first place...


Didn’t know about this API, very cool! Could you point me toward a repo that implements this style?



Not sure if this is what you settled on, but I'd just initialize the state variable as null and then put it into the dependencies of a useEffect that fires when the variable is set


It’s a mix of that. This introduced a race condition and a frustrating rendering experience, but yeah it’s a flavour of this.


I realize this is unsolicited advice, however this sounds like you're hitting the "DOM has an imperative API but React is declarative" barrier, because React (until `use` ships at least) has no way to just await reactive values, you can:

if sufficiently complex, you may want to look into `useSyncExternalStore`[0] which can be used to store and update state (IE maintaining UI reactivity) in a microcosm.

Otherwise, I'd recommend framing it as a series of dispatch-able steps, which maps well to `useReducer`[1] possibly in combination with `useEffect`

[0]: https://react.dev/reference/react/useSyncExternalStore

[1]: https://react.dev/reference/react/useReducer


> I found myself just the other day wishing i could await the setting of a state variable, it was making saving a file in a complicated form a little difficult.

It used to be that React.setState would accept a callback function to fire after the state was set.

The newer setter function returned by useState doesn't have that anymore I'm pretty sure. Tbh I've never tried though.


if you need to await a setState call, you're prob structuring your logic in a less-than-efficient way. in whatever handler is calling setState, you should compute the next state in the handler, setState(nextState), then use that nextState for whatever comes next.


I don’t know, i agree it wasn’t in the react style but it was in the style of basic logic

On change detect new file is there, Set file to variable, Call api to save state.

The issue is setting the variable and calling save is now a race condition.


Yeah, for my personal apps I just write offline-first apps. I need to make it so I can build apps as efficient as I can as I don't have a lot of free time. So, I wrote a little library under 1kB that just finds where I left off and re-centers/focuses there. It makes for dead simple applications.[^1]

I also created an HTMX-like library that is focused on forms so it stays to the HTML speck pretty closely. I need to make a couple of corrections to it. But it is amazing how far it can get you and much smaller footprint than HTMX. Granted, it can only do a fraction of what HTMX can do.[^2]

For anything stateful I just use web components.

[^1]: https://github.com/jon49/mpa-enhancer

[^2]: https://github.com/jon49/htmf


Can you talk more about more of the tricks you use, with server side rendering and light JS?

What about things like real-time (pushed preferably) updates based upon db changes, or another API finally sending streaming results, etc


Tools like HTMx [1] and Turbo [2] have pretty elegant and simple solutions to deal with Websockets.

[1] https://htmx.org/extensions/web-sockets/

[2] https://turbo.hotwired.dev/handbook/streams


Polling is fine for 99% use cases. Even Amazon does this.


This sentiment makes sense up to the point where you are being glared at by a sweaty PM that can't understand why your foo widget can't be moved to the other side while blinking and ajaxing because HTMX doesn't work like that


Uh... what? You can totally do that easily. Not that you should, but this isn't harder to do in HTMX.


I’m using this approach for a side project and it works great. Just traditional express, tagged template literals (with some xss escaping helpers) and stimulus + turbo. Using vite for bundling and reloading on changes.


I used to do this too. Express + PUG templating. Maybe a little <script> injected VUE on the front end for some light client side stuff.


What language and/or framework doesnt have this problem?

- Ruby - if your Ruby/Rails app falls behind, you will be paying back debt to get it up to date

- PHP - if your Laravel/CI/Cake/Slim/Symphony App falls behind, you will be paying back debt to get it up to date

- Go - if your Go app falls behind, you will be paying back dept to get it up to date

- Python - if your Django app falls behind, you will be paying back debt to get it up to date

- Elixir - if your Phoenix app falls behind, you will be paying back debt to get it up to date


Having spend over a decade in Python backend/JS frontend ecosystems at this point, I can confidently say from my experience that Django backends are much easier to update than React frontends. If you import every bleeding-edge nonsense through pip that you can, there can still be problems, but Python has a better culture around this, so it's usually easy to steer teams away from doing this. In JS, importing every bleeding-edge nonsense through npm that you can is the only culture I've found, and this problem is pervasive enough that even guarding your direct dependencies doesn't isolate you from it, since your dependencies are likely to introduce bad dependencies of their own.


"I like python because I picked python."

Literally not one argument here that makes any point.


All 5 of those age better than React. Also, you are conflating languages and platforms.

Counterexamples / Retorts:

- https://catonmat.net/5-best-programming-languages

- https://stevelosh.com/blog/2018/08/a-road-to-common-lisp/

Choose ecosystems free of hamster wheels, friend.


Of course any system will require maintenance. The question is more about the significance and frequency of the maintenance required.

You can take a Ruby on Rails app from 2005, and it will mostly look the same as a 2023 Rails app. You'll need to update some gems, use the newer routing DSL, and update the environment configs. But that's pretty much it, after nearly 2 decades.

Contrast that to a React app written 5 years ago, where you'd pretty much need to completely rewrite everything (class components => functional, use hooks instead of callback methods, etc.)


A React app can be written in 2023 the same exact way it was written in 2016. You don't need to use hooks. React has literally barely changed at all since its creation. Hooks are a choice. Function components are a choice.


I've just updated a codebase from Django 3 to 4, about to do another one. It took very little time, with 0 breaking code changes and a mandatory postgres update to 12+.

Even going from pandas 1->2 and celery major version bump (5, I think) caused 0 problems. Mature codebases like these tend to be careful about backwards compatibility.


As someone with over a decade of Django experience, _very little_ has changed in Django since it started; you can bring up a very old app to speed in a matter of a couple of days.

I've had to spend a week moving a 3 year-old React app to the latest versions and failed because certain dependencies were just a mess.


I have CakePHP code bases that are over a decade old and still run fine.

Go is backwards compatible.


I have years-old Go code that just keeps running. PHP is very stable. I've found Python to be a PITA sometimes. Javascript rots faster than anything else I've encountered.


No don't you see, it's their preferred language so its maintenance and churn don't count.


10000% this.


I have 10+ year old sites on PHP 5 and Laravel 4.x that the client doesn't want to pay to upgrade.


Web Components have got to be the single most overrated web feature I've ever witnessed in the many years I've been messing around with browsers. You know, even WITH React and no Web Components, there was already a pretty reliable way to integrate third party libraries into React without a ton of glue: the DOM. Like for example, if you want to integrate a text editor like Monaco or Quill, basically all you have to do is give it a DOM node and tie together whatever props/events/bindings you want. You don't really need monaco-react, which is not even a large library to begin with.

The main reason why React is still popular is, drum roll please... The programming model. JSX is not an antiquated idea, it is still one of the better ways to integrate the UI part of a JS application into the JS part directly. I greatly prefer JS logic inside of my HTML versus a bespoke template language specifically because it's easy to compose and construct complex logic in.

I've been messing around with Svelte a bit in spare time. I really like Svelte and will probably continue to use it, but the two things I will note is:

- The integration with Web Components is imperfect and doesn't really hit me as something I would seek out.

- The templating logic in the HTML feels decidedly inferior versus just being able to use JS logic and JSX. Try doing a for loop where you count up; the best answer I could find on the internet was to construct an Array using `Array(number)` and enumerate over it...

What I really want is actually more like React's programming model with Svelte's "compiling down to nothing" mantra.

But this Web Components fervor, I know people get very heated about it, but I strongly believe that in 10 years it's going to be one of those grotesquely complex legacy features nobody can get rid of.


SolidJS sounds exactly like what you want https://www.solidjs.com/


That looks great. It doesn't mention compiling down to nothing, but it definitely offers the programming model of React Hooks without needing a virtual DOM, which is already a good innovation, and probably something I'd like more than Svelte.


I find Solid's model pretty damn close to "compiling down to nothing". I chose Solid for my project because I wanted to support plugins that used other UI frameworks. I recently got a Svelte plugin working with the SolidJS router. I could probably make it prettier... but it's literally a call to Solid's `createComponent` with the Router and an anchoring div to which the Svelte component is mounted. Ezpz.

https://github.com/AlexErrant/Pentive/blob/main/example-plug...


I'm a big SolidJS fan, it's pretty much become my default framework for little things, and I highly recommend it.

It is very small and very quick - one of the fastest frameworks out there - but also not too complicated or lean. The signals system takes a bit of getting used to, particularly if you're coming from the React world (e.g. there are no render functions, rather each attribute is reactively updated when its data dependencies update), but it's also incredibly powerful once it clicks. Also, once you get down to it, almost everything is just native browser elements, so if you need to integrate with another tool or library, it's usually really obvious how that should work.


Problem with Solidjs is lack of mature ecosystem.


Once upon a time, I remember one of the plans for React was the ability to compile components into web components. Your code wouldn't have to change at all, but it would mean CSS couldn't leak in/out of the component boundaries like it does now. I think it would've also made it easier to use a React component in other frameworks, since all they'd see is the common web component interface instead of the React interface?


> I remember one of the plans for React was the ability to compile components into web components.

This was also the case (-ish) for Vue, Svelte, Solid. Their authors were really bullish on web components in the beginning. Now they are all on the scale from extremely negative towards them to completely indifferent.


While JSX is very well suited for programmatically defining your UI, it's about all that React is worth these days. You know about string literals right? You don't need JSX and in-fact can get away with:

   render(props) {
      return(
         `<div>
         {props.value}
         </div>`
      );
   }


My perspective is that JSX is all that React has to offer. And lots of developers - myself included - were doing "JSX" a decade before React arrived. Because it, like, super obviously a good idea.


It must be obvious to everyone else then but not me, would be good to get an explanation. My first reaction, and still reaction, to JSX is loathing at the mixing of JS + HTML. JSX's site says that this is a way of recognizing they are tied together and the focus is on separating concerns instead of technologies. Yet Angular manages to do a similar thing through its components, and still achieve separation of HTML/JS.


Angular is a fucking abomination on this front.

Angular doesn't separate concerns at all, it just ties it all together with an entirely new and un-intuitive DSL that you have to now write in the HTML.

Just look at your DSL here: https://angular.io/guide/binding-syntax#types-of-data-bindin...

You abso-fucking-lutely are writing code in your html, you're just writing a crippled version of their custom DSL instead of plain old javascript.

Frankly - I much prefer to write plain old javascript instead of learning a new bastard language that isn't useful anywhere else.

JSX achieves that relatively well. It's not entirely plain old javascript. But it's about as close as I've seen anyone get for a template language complete with data binding.

EJS https://ejs.co/ was my pick before JSX. For similar reasons - I don't want to have to learn a dsl which is just a shoddy wrapper for the JS anyways. Just let me write the damn javascript.


EJS was my pick as well. Shame. I feel like Preact is closer to nirvana but then Svelte comes along. Ideal state: I want a tag, that represents a class, that binds its attributes to properties and subscribes to changes, that encapsulates this within the tag class, including styling.

I’m very fricking close to this with web components and default Vite build. The only gotcha is having to bring along a few utility classes I wrote that glued it all together. Fewer than 40 lines.


> and still achieve separation of HTML/JS.

Why is this important to maintain? People have been complaining about this since the beginning, but I've never seen anyone actually articulate what the problem is.


Before React and this generation of frameworks, we had jQuery. In the jQuery world your site should work without JS. The page downloads, it's a usable page, and then your script starts attaching to elements to make the page more dynamic and responsive, if possible. If not, you still have the page.

It seems to me that progressive enhancement was a genuinely great idea, but somehow the true concept got lost. Nowadays some insist it's ok to have a site that won't begin to do anything without JS, but at the same time it's not OK to mix JS into the HTML code. That somehow we're preserving the purity of HTML as a display layer just by putting it in a separate file.


The biggest pet peeve of mine is when I'm presented a UI that doesn't function because the javascript hasn't loaded yet.

Do not show me a UI if it doesn't work when I press/touch it. More, if I visit your site and your UI doesn't present itself within 1-3s, there should be some alternative UI presented that explains why (rather than just a white page).


Forgive a bit of snark, but…

So PHP?

Mixing html and code is a pretty old paradigm.


That exists in every react app today so what’s your point? Are you arguing against it? If so, other than what I described (web components) how would you build a view? Web components or react components are supposed to be self-encapsulated so you can just add them to your view. Code and all. We are talking about view model code or presentation code.


I'm just saying that

> were doing "JSX" a decade before React arrived

is another instance of "rediscovering old paradigms". What I'm not saying is that this method of building a view is unnecessary, or wrong.

> If so, other than what I described (web components) how would you build a view?

There are many ways to create a view. Programming history is littered with them anywhere there's a UI to be created. Will they interact nicely with React? Probably not most of them, but it doesn't mean they do not exist.


More specifically, for the web. <script type="text/template"> arrived over a decade ago and it's taken us this long to get a <template> standard, let alone a document.createDocumentFragment(). These things take time. I know we are quick to adopt the good and then be shocked it takes so long for the rest of the world to standardize on, but it only reinforces what paradigms "work", and which ones don't by which paradigms become standards. Time will tell.


I don't think OP is arguing against "self-contained components" (with template and code), but about "presentation and business code mixed". I really like Vue's solution compared to React - the template is strictly separate from the logic driving the template. Same file, but seperate areas.

I've previously updated some components in a design system to Vue 3, where I followed the HTML results set by the React implementation. Reading the Vue 2 components worked almost immediately. The React components were so over-complicated that I sometimes literally had to follow the browser inspector instead of understanding every twist and turn in the code. I have never seen a Vue codebase that is as unreadable as the average React codebase with mixed business and presentation.


PHP? That's back-end (and fortunately I've never had to use)

I'm taking about HTML/JavaScript front-ends. The ideas behind JSX go back to at least 2004 when I first began using that paradigm.


Regardless of where it runs, the paradigm is very similar.

On a separate note, the attitude of "That's back-end" that permeates HTML/Javascript development is probably one of my biggest pet peeves; the disdain for what programming languages and GUI implementations have offered in the past hinders learning lessons from those implementations.

And that only holds us back.


"That's back-end" is how you can tell a good javascript dev from a bad one. A bad one doesn't know where the express/bun line ends and the browser begins. Be glad.

Also, GUI development has traditionally been a shit show. From Qt/WinForms to WPF to now using Web tech because the whole industry threw up their hands. There's MVC, MVVM, MVP, you name it to describe a proper UI->data relationship and all have failed to breach the boundary of their domain. Components, like ECS in game dev, are one way of solving this issue. Because we have to separate our markup from our logic we have JSX. I really wish I could do something like:

    this.view.set(<div></div>);
but the reality is this. If you're developing a UI using code, you don't need markup at all except for the specific element/display you are representing. Almost all of my webcomponents are just a div in a document.createElement and the rest is built up using the same. document.createElement. It's tedious, it's error prone, which is the argument for JSX. I don't need to create a Nav component and a Nav Bar component and a Nav Item component and a Nav Menu component, etc. I can just create a Nav Component and handle it all from there, simplifying my UI view code.

In the end, all of these work arounds are simply because we have to deal with the final product, html and we (myself included) get stuck behind the default tags because thats what we know. We don't need any of it. Define your own. Treat the page like it's one giant empty xml document and everything's derived from a div and see if the browser treats it any different. It doesn't. So your entire body could be made of:

    <article>
       <post>
           <post-title/>
           <post-author/>
           <post-body/>
       </post>
    </article>


> I don't need to create a Nav component and a Nav Bar component and a Nav Item component and a Nav Menu component, etc. I can just create a Nav Component and handle it all from there, simplifying my UI view code.

That seems like arguing you don't need functions in your programming language and can simplify it by inlining everything.


IYKYK, some cough frameworks cough have this idea of nesting nests of nests in order to have proper look and feel. I won't name names, but it became something people got used to and it's horrid. One or two parent->child stylings is one thing, but the aforementioned framework had up to 8 in this Nav functionality.


> the paradigm is very similar

I disagree. I believe you're referring to the paradigm of mixing markup and code, which I never did.


PHP is how I'd describe Astro.


what's going to make sure you didn't type <div></dib>


my ide... VSCode checks string literals for things like this.


Not exactly universal


Watch out for html escaping.


Assume props is pre-sanitized.


Ron Howard voice: in fact, props was not pre-sanitized.


you know about injection vulnerabilities, right? if you really want to spaghetti code your app with string representations of html, you can also use `dangerouslySetInnerHTML` in React.


You would do it as a tagged template literal rather than with plain string templating, similar to Postgres.js


For your div demo, sure, heck even the "todoapp" might work well enough with it.

But please, build something proper with just that and presumably a .innerHTML = ...

Let us know how it goes :)


I have many times and you've probably seen it in the wild but I won't give myself away that easily. A Fortune 50 does this with great success.


The point is you're susceptible to XSS attacks with that code.

But with a "tagged template" it should be easy to treat the variables before actually doing the templating, without making the code ugly.


It’s just an example


Hmmmm. Does that do escaping and such, or are you boned when an angle bracket shows up? Plus if the nodes are already parsed in your code it kinda sucks to stringify them so the browser can re-parse them.

Not to mention holding focus and other element state, would that just get blown away and replaced with a whole new element every time? (Where react does tree reconciliation to avoid unnecessarily blowing away and replacing elements)

Maybe you’re only addressing the point about programming model, but this approach seems like it has some issues.


I am indeed only address the point about the programming model. In react, state and bindings are one and the same (using useState). In mine, your class is the binding to the element, render is only called once and you're free to subscribe to any on* events back to your class functions you wish. onclick="this.click" just works in my world. You need a bit more than the 5 lines I showed but it's trivial. No shadow-dom, no reconciliation, no unnecessary blowing away of elements at all, and no reparsing the tree.


The shadow DOM is a great alternative to using iframes to get style isolation from the larger app, but everything else about custom elements/"web components" has better alternatives in user-land.


Each loops over anything with a length property:

    {#each {length: 3} as _, i}
https://stackoverflow.com/questions/58213585/svelte-3-how-to...


That's not really a huge improvement over just making a sparse array though, is it? Looks more confusing to me. Could be wrong but I'm pretty sure e.g. Array(1000000000) does not actually allocate much.


I'm not up to speed in JSX, how is it be better there? Don't one normally map over an array to loop? You cannot use for-loops inside JSX?

Or do you create an array of JSX-elements, like

    let elements=[]
    for (let i=0; i < 10; i++) {
      elements.push(<li key={i}>I'm number {i}</li>)
    }
    return <ol>{elements}</ol>;
Does not seem like an improvement to me.


It's just JS: You can do that, or you can use any helper method, or write your own helper. Can't really do that in Svelte.


captain obvious here, Polymer became LitElement which became the invisible Lit.dev (branding direction on par with twitter becoming x); pretty much state of the art on top of web components; not that anyone noticed, as I said--meetup.com keeps prompting me to take over one of the web component meetups where the (or one of) lead of the project can't seem to muster the effort. a bit frustrating when the lack of awareness is so profound and extensive--as evidenced by many of these comments, over many years. I'm sure many more projects will make the mistake of choosing React and Svelte before the conclusion mentioned here bubbles up.


I think JSX was a mistake and just using hyperscript would have been better for the ecosystem. I think frameworks peaked with mithril and have been downhill ever since.


Mithril wasnt back then what is it now.


I'm not familiar with how its evolved but I really enjoyed using it around 2015-2018.


How does one "react" to changes in a foreign element? Mutation Observers?


Those other tools you're using almost always give you a set of callbacks or events they will fire.

Just use the normal event handlers. If you're tied into a store (ex: redux/zustand/recoil/context/etc) just update the store from the non-react library and things will work themselves out just fine.

You can watch the DOM with mutationObservers, but if you own both pieces (react and non-react) why would you bother? They can both coordinate just fine.

MutationObservers really shine when you happen to missing an eventHandler you want in a library, or you're running on someone else's DOM so you don't control both sides (ex: you're an extension content_script).


I don't know.. Imagine you have a react component that needs to interact with something written in svelte...

I'm not convinced that people are building integration APIs for consumption by external code. That means no JS events (redundant since it uses stores or signals and whatnot) and minimal callback availability to hook into a component state.

One might not control the code if this is from an open-source library for instance.

Maybe the premise is "don't do that" , but then people still wanted WebComponents at some point. So seems there exist use-cases for component interaction. Or were people mistaken in the first place?


I don't understand your comment here.

I own both sides of the stack. Say I have a react component that happens to mount a svelte component in the DOM.

I expect Svelte code to be running somewhere (I wanted to use a svelte component, I have to initialize that stack).

I expect React code to be running somewhere (The main page is react, for example).

I expect to have some sort of signaling or state management solution (say a redux store, since the main page is react).

I can just update the redux store from both stacks. The store emits the correct events whenever it's updated - all subscribers are notified - react-redux does its magic and conditionally re-renders my react tree based on the new state.

I can do exactly the same thing in Svelte - subscribe to store events, see an events when react changes something, update my svelte app in response.

---

And it's absolutely not limited to redux... I can do the same thing by hand with global state, or by emitting custom events in the DOM, or any of a hundred other ways to get these two apps to work together. I own both sides - making them play nice is normally trivial (if not always quick, and sometimes tedious as all get out).


The state that is handled by svelte is not automatically visible to react and vice-versa.

That's the whole point of the question.


I guess my response is: "So make it visible". Because that's easy to do with any manner of methods.

Sure - each library is going to do its own thing with regards to how it manages it's internal DOM and state, but that does not matter at all.

All you care about in wiring them together is:

"Can I call some js code in response to state change in svelte?"

and

"Can I call some js code in response to a state change in react?"

and the answer to both is a resounding "Yes!".

So now I can easily make the state of one visible to the other... I just run some code in response to a change on either side that updates the state of the other - done.

If you want to get adventurous - you can automate the entire thing away with a proxy store, so it happens everywhere by default.


> I don't know.. Imagine you have a react component that needs to interact with something written in svelte...

this doesn't happen in practice... like at all...

is your implicit assumption that anything written in react will automatically work just fine with svelte but not the other way around? why would react -> svelte be any easier than svelte -> react, and why is the burden on React to solve interoperability problems between competing frontend frameworks?


That was an example, you can take it any way you want it (angular to react, react to angular etc) ... Don't get triggered. That's not the point.

Of course it can't happen if it's not easily if at all feasible. That doesn't mean that people don't want to do it.

The fact of the matter is that it seems to me that WebComponents are an attempt at solving an interoperability issue. Or am I misunderstanding?


> React's programming model with Svelte's "compiling down to nothing" mantra.

Solid JS!


I think the people expressing negativity about hooks are a small minority. Hooks are a massive step up from class component lifetime methods, and the composability of hooks can lead to some very clean and powerful code if you know what you're doing. We're using hooks at work, with rules-of-hooks linting, and I can't remember the last time we had an issue or bug because of hook semantics


I think they're a bit of a mixed blessing. The way they can decouple business logic from view logic is absolutely fantastic. But having to wrap everything in useCallback and useMemo to avoid re-renders is a bit of a footgun and a step backwards from class components.


Like others I disagree that you have to wrap _everything_ in useCallback/useMemo.

However saying you only need those for performance reasons is wrong.

There are cases where avoiding re-rendering (thanks to useCallback) is avoiding an infinite loop.

I created a codesandbox[1] to illustrate this. Wrapping the "reset" function in a useCallback solves the infinite loop.

If your initial reaction is: "you should not create logic like this" or "you're adding unnecessary stuff" please note that this is a stripped down version of a real use case, where things make more sense.

The point is that it's hard to come up with a rule as to when to use useCallback. The best I can think about is: "if you don't have direct vision on where your function will be consumed, wrap it in useCallback". For example, when your function is defined and returned in a hook or defined in a parent component and given to children.

The point is that any of those children/consumers could have this function in a useEffect and so list it as a dependency of this useEffect.

[1]: Warning, clicking "Start" creates an infinite loop in your browser. https://codesandbox.io/s/intelligent-rgb-6nfrt3


This example doesn't resemble anything someone would actually write though.

There's no reason to reset before setting data again, and I'm not sure why you'd even consider putting the functions in the dependency array for the useEffect in usePets.

I can imagine reasons you'd want to setData in a useEffect (maybe when something else changes, or the user performs some interaction, you fetch new data and then set it), but the dependency would be the thing that indicates that action has happened, and not a reset function returned by a custom hook coupled with your data and setter function.


I tried to address your type of reaction in my "If your initial reaction is(...)" sentence, but that failed.

The point is not that this code is good or bad. It's that it is possible to write such hard to predict code.

Remember this is a stripped down version of some code running in production.

Now to address your specific points anyway: "There's no reason to reset again": in the non-stripped down version, the hooks rely on a third hook (let's call it "useToken") and needs to react accordingly to this change of token to fetch new data

"I'm not sure why you'd even consider putting the functions in the dependency array for the useEffect in usePets.": unfortunately react-hooks/exhaustive-deps is here to warn you. You can disable or ignore it but I guess you expose yourself to a real missing dependency? Genuinely very keen to hear if you use this rule in your projects and what you do in such cases (where you use a function in the useEffect but do not want to re-run the effect each time this fn changes). To me it's such a weird/unnatural thing to list functions as dependencies because almost all the time functions do not change.


Ahh well the setter functions are excepted for the exhausted-deps rule, which is why I hadn't encountered it: https://legacy.reactjs.org/docs/hooks-faq.html#is-it-safe-to...

> (The identity of the setCount function is guaranteed to be stable so it’s safe to omit.)

Maybe in JS it still warns in your example because setData is passed in from calling useResource, but at least with Typescript I'm pretty sure eslint infers this


> The way they can decouple business logic from view logic is absolutely fantastic.

It’s a great idea to decouple business logic from view logic, but then hooks are the wrong place to start. Last time I checked, you couldn’t use them at all outside of a React component. That’s just a terrible place to put your business logic if you want it to be isolated from the specifics of your view.

I’ve mostly moved away from React, so maybe this has changed recently, but it seems difficult considering the fundamentals of their design.


The problem that hooks solve really nicely is when you want per-component state, but you duplicated versions of that state (and surrounding logic) in different components. With class-based React components you had to use things like higher order components, or manually add the state properties into each component. With hooks this is all neatly abstracted away.

You don't always need this. Sometimes your business logic can just be a pure function. But where you do (and IME this is quite common), hooks are super nice.


Best practice in general is not to use either of those hooks unless you notice performance issues, or have a good reason to, React is optimized pretty well and unless there are serious numbers of rerenders happening they aren't noticeable.

Josh Comeau has a nice overview of useMemo and useCallback, one of my favourites: https://www.joshwcomeau.com/react/usememo-and-usecallback/#w...


The problem is that they don't work to fix performance issues unless they're implemented all the way up the tree. So if you have a perf-sensitive view, then you'd better hope that your "application frame" components (or anything higher than the perf-sensitive component in the tree) are optimised to avoid re-renders. And it's a massive pain to retrofit this in later if you haven't been strict with it from the start.


Hooks are a step in the right direction, I just have a feeling that having to wrap in useCallback and useMemo and having to add dependencies manually can't be the final step of web app development. I look into the author's suggestions for the next generation of hook api in other libraries. However, I still don't want to rely on those libraries in large long living projects.


The React team is testing out a compiler time approach to useMemo instead.


We wrap very little in those methods and things are just fine.


My understanding is you don’t usually need useMemo and useCallback, unless you’re seeing performance issues and your profiler is pointing at un-memoized code as the culprit.


I sometimes check React discussions and it's full of new made-up terms about managing issues that are uniquely caused by React or some previous iteration of a React technique. What happened with the simplicity of just "generate some boring ass HTML DOM in JSX, and it applies the diff to the actual DOM". That's it. That's the entire value proposition of React and it needs no hooks, handles, states, immutables, events, data trees, properties, arguments, components, nothing else. Oddly that still works just fine, but no one uses React this way anymore.


> I sometimes check React discussions and it's full of new made-up terms about managing issues that are uniquely caused by React or some previous iteration of a React technique.

In other words, you're checking React discussions and finding discussions on how to maintain React code. What were you expecting to find?

> What happened with the simplicity of just "generate some boring ass HTML DOM in JSX, and it applies the diff to the actual DOM".

React happened, which does just that but transparently and effortlessly. In fact, React does it so well that a concern is to prevent it from applying those diffs when being updated when it doesn't need to.

> That's it. That's the entire value proposition of React and it needs no hooks, handles, states, immutables, events, data trees, properties, arguments, components, nothing else.

React does not need those features if you are using React for things other than developing graphical user interfaces, which by their very nature are stateful, emit and react to events, handle properties, etc.


Only if you're working on super simple projects. Or don't want reusable code.

How do you share data fetching logic across components

How do you share a common UI functionality like toggling states, starting timers, across components?

People are now more concerned about clearly writing business logic while stiching together React lifecycles methods, instead of the other way.


Lots of assumptions. And they're all based on the fact React must be some all-encompassing framework, like all other frameworks are or have become, and there's no other way to organize your app, possibly, unless it's dropped from above, from the framework, and is intricately interwoven and coupled with it.

But there's another option: don't use React as a framework, use it as a library. And do your modules/components/reuse/fetching in your own plain code, while using React as a display layer. You don't even have to use React for the entire UI.


> Lots of assumptions. And they're all based on the fact React must be some all-encompassing framework, like all other frameworks are or have become, and there's no other way to organize your app, possibly, unless it's dropped from above, from the framework, and is intricately interwoven and coupled with it.

This is a silly argument to make. People don't want to onboard onto a myriad of little reinvented wheels just to put together a GUI. This is well known to be a major mistake, and the root cause of failure of countless projects.

People are paid to deliver features and fix bugs, and not to peruse through npm like they are playing Pokemon. React solves their problem by solving developers' problems. Don't you understand the value of using a standardized tool that answers all your problems?


People are paid to deliver features and yet the forums are full of why this and that is annoying in React and how version X.Y.Z is replacing it with something else that will be the next annoying this that people in the forums will discuss. I sense lack of alignment between intention and results here.

Knowing how to architect your app remains important, and once you know it, it's trivial. For those who refuse to learn it because they deem it a gargantuan task, frameworks will keep trying to provide a "generic" solution, but a "generic" solution is by necessity overcomplicated, overengineered, and bloated, because it's trying to address EVERYONE's concern and specific needs.

At no point in time will a monolithic "everything solution" be simpler than a specific modular solution to a specific modular problem.

React started with the promise of simplicity, and being a library, not a framework. Somewhere along the line this ideal was lost, this happens often. And it happens often because many small elegant solutions start with the intent of replacing the status quo bloated behemoth framework that everyone hates. What they don't realize is that with lack of understanding of why frameworks end up like this, this is the fate THEY will share one day. Entropy is a b**ch.


> People are paid to deliver features and yet the forums are full of why this and that is annoying in React (...)

Online forums dedicated to frameworks are filled with questions on what the framework does and how it works. No news there. What did you expect?

> Knowing how to architect your app remains important, and once you know it, it's trivial. For those who refuse to learn it because they deem it a gargantuan task, frameworks will keep trying to provide a "generic" solution, but a "generic" solution is by necessity overcomplicated, overengineered, and bloated, because it's trying to address EVERYONE's concern and specific needs.

I'm sorry, you typed a lot of words to actually say nothing. So you don't use all features provided by a tech stack. So what? That is not bloat. Writing software is not a game of bingo.

Also, reinventing the wheel when a fully working and tested wheel is already available is a very dumb mistake and a fundamental failure in the decision-making process.

> React started with the promise of simplicity, and being a library, not a framework. Somewhere along the line this ideal was lost, this happens often.

I don't think this is remotely true in any way. Undoubtedly React greatly simplifies the work of putting together working and full-featured SPAs. The concept is so good and so extensively proven that React is already being used to develop native GUIs in desktop applications.

Your comments reads as if you're tilting at a React windmill. It's ok if you like vanilla JavaScript, but you're not being honest with yourself if you're failing to understand what problems React solves, how well Reacts solves them, and why the whole world has basically standardized around it.


> annoying in React and how version X.Y.Z is replacing it with something else that will be the next annoying

Interestingly enough, React is probably the only major frontend framework that is obsessive about backward compatibility.

I had to pull a component from an internal project into my codebase recently. The component was still class-based. Worked without a hitch in the modern hooks-only code base.


React went from class components to function components and from lifetime callbacks to hooks. These concepts are completely orthogonal.

There exist design choices that would end up with a different combo. Class components with hooks or function components using lifetime callbacks.

Yes, hooks — basically sub components with possible effects and yielding values, or DOM output — are a terrific idea and much more functional and principled than explicit lifetime callbacks.

All the dependency arrays and non-conditional checks etc are because of the function components approach and don’t have much to do with hooks.

I feel nearly every discussion on hooks mixes this up and makes the whole conversation just weird and confusing.


> All the dependency arrays and non-conditional checks etc are because of the function components approach

And because of React's design choices. Reactivity can be achieved without explicit dependency lists.


I think you're underestimating that.


I'm not a hardcore React user; I'm currently working with React, but I came here through jQuery, Angular 1, web components, and Vue. I've done two React projects: one really tiny one as an assessment where JSX was an eye-opener; components were classes, and React was simple and fun back then.

Now I'm working on a gigantic React project, and I'm surprised it's still working. It's all based on function components with all the hooks, higher order components, middleware components, and tons of other stuff. It works, and it's clearly maintainable, but it's not pretty. Endless useEffects after each other make it hard to see what's going on. Every change requires changes in half a dozen files at least; DRY is clearly not a concern here.

I'm not a React expert, but I think function components and hooks were a mistake.

One thing that strikes me is that years ago everybody was excited about ES5 finally adding classes, and now everything seems to be moving away from classes.

I think JSX is still a cool idea and an interesting alternative to templating, but I also think that if I were to pick a frontend framework now, I'd go with Svelte.


If you have lots of useEffects and the code is confusing, that just means you're not writing your code well. I've architected and shipped multiple react projects that generate min 100M + USD in revenue, so I'd say I'm well versed in production react. It is weird, sure. All web technologies are kind of weird. But it works great for large web applications.

Keep your functions small. Re-use is key - whether its hooks or components. Keep state sane by writing small functions that handle a couple state items internally, or create a parent state using context around a group of components.

React gets a lot of hate, but most of it is unfounded. It is just a tool. I see people write 800+ loc react components and wonder why it is "so confusing". The problem is obvious. The goal of using any technology is to make money, nobody cares (end of the day, just being real lol) about any of these esoteric practices that happen under the hood with effects, etc. Write good code and most problems disappear.

Unless you're working at Meta on react, or you have some burning desire to build tools like this (and honestly only <5% of devs who contribute will contribute something meaningful), there's no reason to pick so many fights with these tools.

Just use it by accepting its features and limitations, and craft your UI project well enough that it is maintainable and keeps printing money. Anything beyond that is a waste of time/effort.


Any good resources to learn more on this (working with production react)?


Endless useEffects is an indication that useEffect is being used incorrectly. In mostly projects you should only see a few instances of useEffect.

This might be helpful https://react.dev/learn/you-might-not-need-an-effect


If the same problem pops up a lot when using a framework, then at some point the framework is to blame. Yelling at developers "you are doing it wrong!" is meaningless, frameworks should naturally lead people towards the correct behaviors.

React does no such thing.


Not a problem with the library, but a documentation issue. The advice around how to correctly use useEffect was a bit ambiguous in the old documentation, but thankfully is much better in the new docs.


I find Angular much easier to reason about than the current state of React/Next. Which is funny because the biggest criticism of Angular years ago was its learning curve. Yet React seems to have become even more convoluted.


React and angular both had much bigger learning curves than vue. But between google and Facebook, I don’t think vie stood a chance popularity wise, even though I think it was the better of the frameworks at the time.


Vue didn't stand a chance? I think it's pretty popular, isn't it? The company behind it doesn't matter that much to the popularity.


Oh i dont think you remember when Facebook launched React at their big conference. It absolutely does matter.


I wasn't there, so no, I don't remember that. Thing is, plenty of technologies launched by large companies at big conferences have failed to catch on. And plenty that were created by just some people without a big corporation have been wildly successful.


One reason you don’t want a class for every component is that standard JS minifiers won’t compress method call names, but can compress imported function names. So the cost in the minified bundle between a class component and an equivalent function component is huge, multiplied out by the complexity of the component.

`this.handleClick` vs `c`.

I still use classes for building data structured but don’t think creating classes should be encouraged by a framework.


> So the cost in the minified bundle between a class component and an equivalent function component is huge

Does this actually matter though? It's going to be gzipped anyway right?


Gzip compression will eliminate the repetition on the wire, but smaller uncompressed bundles will parse and start executing faster than larger bundles. For us this is most noticeable on Android which has the slowest hardware on average of all the platforms we support.


They can do it, it is just turned off by default and require more advanced configuration.

https://github.com/terser/terser#cli-mangling-property-names...


I don’t know any codebase that’s enabled these kinds of transforms because the compiler doesn’t know if a type’s properties will be introspected or iterated, so the transform is likely to break at runtime


> One thing that strikes me is that years ago everybody was excited about ES5 finally adding classes, and now everything seems to be moving away from classes.

For me the key advantage is much less boilerplate, readability and portability. The problem with `Stateless` components up until the introduction of hooks is that if you wanted state you had to write your component as a class so you ended up with components written in two totally different syntaxes with one being much more heavy on boilerplate.

The last key advantage i see is it brought the "React Components" way of sharing to logic. Previously every piece of logic you shared had to be connected to a react component, so you ended up with many "Providers" that were just a div with logic. Now with Context and Hooks you can easily transport that logic without the use of a Provider (well you still need one with Context but that a slightly different story).


Makes sense. I'm not sure I've ever written a stateless component. Almost every non-trivial component is bound to have some sort of state, doesn't it?


> Almost every non-trivial component is bound to have some sort of state, doesn't it?

No, not at all. Any nontrivial component is going to have some sort of conditional rendering, but whether the inputs are supplied explicitly as function arguments or implicitly as state is for the most part orthogonal to what you do with them.


The article starts by a quote of Alex Russel, paid by Google to specify Web Components between 2008 and 2021 - a technology in direct competition with React at the time. He is not a technologist to track or quote to get unbiased framework opinions.

I don't agree with most of the argument here, to the point where I think we live in totally foreign echo chambers that rarely exchange ideas. I didn't get any new idea out of this article, it didn't inspire me to do something I already tried 10 times in the past.

The website loads fast, and that's great. 10% of the CSS is unused. and that's a small blog. In the non-themed CSS, it's close to 50% unused. You could consider it a non problem - at scale dead CSS is complicated to manage, at least for me.


> paid by Google to specify Web Components between 2008 and 2021 - a technology in direct competition with React at the time

I’m personally of the belief that we should assess arguments, not employer. Someone working on a competitor to React can make very valid arguments against it, they’re often some of the most knowledgeable people about the drawbacks of the framework.

I’m personally not a fan of Alex’s abrasive style but I’ve seen plenty of his critiques of sites written in React-based stacks and they’re usually evidenced with bundle analysis, burn down charts and so on. They’re not unfounded.

(I also disagree that Web Components are a competitor to React. Frameworks like Preact and Svelte are interoperable with Web Components and build on top of the API. React chooses not to but that’s neither here nor there)


> (I also disagree that Web Components are a competitor to React. Frameworks like Preact and Svelte are interoperable with Web Components and build on top of the API. React chooses not to but that’s neither here nor there)

Used to work on Web Components (the browser side.)

Although we didn't take it as a competitor, in hindsight it was - at least in a sense. Both are component-based technologies, and the expressiveness of React and ES6+ made WC less relevant. I think WC is still nice to have, but it is no longer a must-have as it was originally envisioned.

The JS ecosystem has largely solved the problem by themselves without browser vendor's help (besides improvements of JS itself.)


Neither Preact or Svelte produce web components by default or use features like Shadow DOM.


I’m not sure how that’s relevant to the point that Web Components is an API that can coexist with frontend frameworks.


I don't feel it's fair to brand "web components" as a technology that was in direct competition with React. I think the nuance matters.

They may have been solving similar problems then, and they may be optimized for different things now. But Web components are a web standard, and React is not. Pushing for web standard technologies is inherently unbiased because that's just betting on the platform. This results in pushing for platform improvements (like declarative shadow dom so it plays well with SSR, etc), and then everyone benefits.

IMO it'd only be a bias take if web components were branded as having no issues whatsoever, or that they are the most optimal solution for everything. I think it's okay to say, "web components currently don't solve my problems and that's why I'm looking to use something else like React or Solid". However, I've not seen this sentiment shared when it's the other way around with React. It's always "no one got fired for picking React" instead of actually evaluating what will deliver the most value to your users.


> Pushing for web standard technologies is inherently unbiased because that's just betting on the platform.

There's a ton of politics around web standards, and you can bet if Google manages to push through Web Environment Integrity, I will not consider people suggesting to use it "unbiased because it's a standard"


That's a fair point. I didn't consider that


> I don't feel it's fair to brand "web components" as a technology that was in direct competition with React. I think the nuance matters.

Nuance doesn't matter to most proponents of web components. When they were introduced, for the first few years they were explicitly marketed as platform-native solution that makes frameworks obsolete.

Now the rhetoric seems more nuanced, but it's the same. It's only been upgraded to "build with lit".

> IMO it'd only be a bias take if web components were branded as having no issues whatsoever, or that they are the most optimal solution for everything

Mostly they are billed like that. And any voices criticizing them are either ignored or blocked.


I'd take that point further and state that React is in no competition with anything.

React was invented because Facebook had very interactive/stateful UI as well as large teams of developers working on the same codebase. The then conventional jQuery soup approach didn't cut it.

Should the web platform come up with a standards-based approach to solve the same problem, then this is not "competition", it is a blessing. It's not like React earns Facebook any revenue. Ideally, it wouldn't be needed or exist at all.


React has more implementation of its components model (preact, react, solidjs, inferno,…) than web components (chrome, ff partially and safari partially), is more used and is more indépendant from the current web monopoly. Anything w3c is now a standard to keep dominance.


Interesting article. I’m going to play devil’s advocate and come at it from a business perspective. There are huge advantages to sticking with an industry standard. It makes it much easier to hire devs. If you’re a dev it makes it much easier to get work. Having a big ecosystem means less building from scratch. There are huge network effects at play. In order to get serious traction in a market with network effects, the alternative doesn’t need to be a bit better, it needs to be 10x better. React displaced jQuery because it was 10x better. None of these alternatives strike me as being 10x better at this point. Sure they’re a bit easier for devs and a bit faster, but I’ve never had a customer complain that the app took 500ms to load instead of 250ms. There’s other things they care about a lot more. At some point another framework is going to displace React, but I think React still has a huge advantage at this point.


Yeah, I'm currently working for a project that rewrote their whole platform from Vue to React simply because they couldn't find enough Vue devs.


A well put together article.

I still remember the day when angularjs was a new thing(around 2015 perhaps) and as a newcomer I was sucked into it. Just loved the thing. A year later, there were news about Observable JavaScript objects. So objects could send a notification about themselves having been changed. And when do so, do DOM changes could be done accordingly, without having to implement a render algorithm and having to compare shadow nodes with new render results to see what changed every time any data change occurs. I don't think we are past that with React, and as the author mentioned there should be absolutely no reason for a developer to worry about rendering performance (the amount you have to use react, with for example useMemo, useCallback) and is something to be looked after and questioned.

Another argument of mine[0] would be the definitions that have been introduced by react. Component, state, hooks. It seems like we have forgotten about what they are actually called, and its function is in the context of programming (functions, variables, events, etc.). And so people become solely a React developer and can't really see a way out. (from the article: "And maybe—just maybe— your current satisfaction comes, at least a little bit, from simply not knowing what you’re missing.")

[0] - https://medium.com/@ngergo/describing-how-react-works-in-com...


> there should be absolutely no reason for a developer to worry about rendering performance

i have a csv with one million rows. should i load the entire thing into memory and render 1m * column_count dom elements?

> Another argument of mine[0] would be the definitions that have been introduced by react. Component, state, hooks. It seems like we have forgotten about what they are actually called, and its function is in the context of programming (functions, variables, events, etc.).

a Component is a Component because it represents a node in the React tree. not all functions are Components.

state is state because it's more than a variable - updating it triggers re-rendering. a normal JS variable does not come with this reactivity.

hooks are not events. they are wrappers for reusable logic.


Lots of nuggets of truth in the article. Dev Experience vs User Experience is mentioned.

On my part, I never jumped on vite, because the only argument I've heard for it, is faster dev builds. But my current builds are fast enough (I grew up with 40+ minute compile/link cycles in C++).

And I don't have a week to change my current scaffolding. If you do things right in your company you never have a week to change such a tool. Because that's a week you could spend on relevant features and bugs. Heavily advocating tool changes are fast-track to become a "problem engineer".

Also, yes, React has aged very poorly, and even more so, the ecosystem around it is rotting hard. It's moldy.

But it's still very good and is almost perfect. Maybe instead of writing a new framework, we should consider doing a React 2.0 with batteries included.


If a 30 second build can be cut to 15 seconds, for 20 engineers, assuming a conservative 10 save-file commands per workday (HMR!): this change converts ~216 engineer-hours per year from non-productive to potentially-productive. Given an average 40 hour work week, you could task one engineer on this change for five weeks and still come out ahead.

This is the calculus. Vite isn't built for the "lone ex-C++ dev" shop. Its built for teams that can run this calculus and realize that, 80% of the time, investments in speeding up the software development lifecycle are among the highest leverage, most direct correlates to productive output a software shop can make.


I completely agree. On that note, giving devs maxed out computers also save time and money on the long run, most companies still don't do it.


Seems like an excessively conservative approach imo. If advocating for tool changes wasn't important sometimes, I don't think it would be relevant to cite some much slower process.

Sometimes the tools suck, and sometimes you need to improve that situation, ideally in a gradual fashion. Sometimes they're passable, and there are other priorities, but usually tools start showing their rust eventually.

I also think it's extreme to say it's aged "very" poorly. It provides a relatively productive way to express UI as composable state machines, and now it just has a solid ecosystem of viable competitors.


> Maybe instead of writing a new framework, we should consider doing a React 2.0 with batteries included.

Besides what's already in NextJS, what are the batteries you're thinking of?


For one, built-in global state management like zustand. Context is too clumsy and iirc, causes unnecessary renders.


I strongly agree that the industry often prioritises DX over UX but

> I never jumped on vite, because the only argument I've heard for it, is faster dev builds

I wouldn’t assume Vite is worse than its competitors for UX just because it doesn’t explicitly say it’s better


I feel like something lost for (web) programmers is how to construct complex systems in a “do it yourself” yet practical manner.

My hobby of doing game dev (driven by automated testing) has taught me so much about patterns of abstraction, boundary making, and modularity. Domain driven design makes so much more sense given my stint in hobbyist game dev. (buyer beware: game dev pedagogy is awful and many lessons I’ve had to discover myself)

In my day job as a web dev I notice that my team/company think exclusively in our framework and we seem to push everything into the framework. I wish we treated react as just a view layer but so much more gets pushed into react. We’re so hooked on the sauce that writing anything outside of react is defacto considered an anti pattern.

I know there has to be a better way but before I can know what that is I’ll have to understand why people adopt what I’ll call “framework brain (rot).” I kinda suspect programmer pedagogy is fueled by clickbait pretenders who find it easier to teach frameworks than the tough stuff like how to make a complex system easy & practical to build. Let me know what your speculation on this subject might be.


> I kinda suspect programmer pedagogy is fueled by clickbait pretenders who find it easier to teach frameworks than the tough stuff like how to make a complex system easy & practical to build.

There's a lot to balance making these decisions at a project's inception. NIH bias can cost you a lot for no benefit beyond self-satisfaction. There's a good chance making something with a current stable framework and migrating to a new one down the road will have taken far less time than making the initial RYO version. You'll also be able to hire people who already know how a big chunk of your codebase works, and lots of your underlying functionality is already documented.

Additionally, pedagogy is very different from practice. Most of the time when young me decided to do something the hard— but "more elegant" and "simpler" "more correct"— way rather than using a library or something, it was because I didn't actually know how hard the hard way was. Those are mistakes you only make once. It's true that some people use frameworks because they don't understand how to do what frameworks do under the hood. A lot of other people use frameworks because they know exactly what it takes to recreate what that framework is doing under the hood.

That obviously doesn't work if your code uses very little of what the framework offers— but they are generally designed to bring a lot to common use cases, and can save you vast amounts of time, energy, and money if judiciously applied. Just like any other tools, they've got their good use cases, bad use cases, and ways to outright abuse them. A good understanding of your requirements, the preferred methods to address them, and the current tooling available is the way to decide which of those scenarios a framework would fit into.


What has been lost can be gained again.

It's like C developers smirking and demeaning web developers because "kids these days don't know anything about computers or memory management" as if they truly believe that that's true because newer devs aren't smart enough to understand it, rather than the ground truth that it's just not relevant to those newer devs, and that they could easily learn everything the jaded C dev knows, if it became relevant/useful again.

I definitely believe that a devs exposure to various languages/frameworks is important though, even if they only work in one domain. Someone who is a React dev will try to apply a React spanner to everything they do, but then again someone who is a C dev will write C-like React code (or just outright refuse to engage in web dev).


I think the changing demographics of developers counters this argument.

I think it takes a special kind of person to grok C and C++. If offered C/C++ on the one hand and JavaScript/Python on the other, very few people in the world will choose C/C++.

Back in tha day, when C and C++ were the only games in town (and programming wasn't as lucrative), the industry naturally filtered for these people. Today, it lets more people in than ever before. These new people, it can be reasonably argued, are not as smart as those select few from yesteryear. The fact that they're not exposed to the mind-scrambling vagaries of architecture differences, which means the barrier of entry and attrition rate are far lower, should pump that intuition, no?


You’ve hit it on the head. A well written react app will have a lot of code that isn’t in hooks or components and is instead imported by those. That said anything to do with the presentation of the app should be within react, with important exceptions.


> My hobby of doing game dev (driven by automated testing)

I'm kinda curious about this. Do you have any good resources on automated testing for games?


Nope! It’s all synthesized knowledge from other sources. I’m simply reading, doing, and thinking a bunch to work out what makes sense.

If you ask about automated testing for game dev you quickly learn there is very very little desire to entertain the subject. I’m unclear why.

At some point I’d love to share my insights as videos and/or a blog series.


no one ever got fired for choosing react though. that chart library? already exists. mobile? react native. some weird combo box autocomplete ui component? someone already wrote that, just reuse it. dev tooling with debugging and profiling and all the memes. new hires know where to start.

ecosystem is king


> ecosystem

If only the article had dedicated a section to how React trained us that things need to be built specifically for a certain framework, and how no other modern frontend framework is as stubbornly incompatible with the platform as React is.


IDK, I think Vue is pretty incompatible with the rest of the JS/TS platform — e.g. its templating language is pretty custom, and components built for it won't work in say, Svelte. Same for most frameworks; Solid isn't more compatible, it's just different (arguably better? With the drawback of a smaller ecosystem, because it's younger, and because no one ever got fired for choosing React). Svelte has its own unique lifecycle system; etc etc.

This isn't really any different from frameworks in general: JQuery had its own massive ecosystem that assumed JQuery was being used; trying to use something from the Rails ecosystem in Padrino was unlikely to work well; Vim vs Emacs; etc etc. Frameworks accumulate ecosystems around them and have since pretty much the beginning of programming — I don't think React has nefariously trained ecosystems into the community; I think people tend to build libraries on top of other libraries they know, and React is popular, so it's the basis for more libraries (the ecosystem).


You can use a “meta” framework like Astro if you want, but micro front ends sound like hell. Nobody has really achieved portable non trivial components in a way that doesn’t come with a steep price tag, and web components have never taken off.


This. People who disagree - why not write in Haskell?


We write in Elm.

To elaborate further: I don't believe ecosystem is king. Success can mean different things to different people, and is not always a single dimension of "popularity units".


We have one Elm project at work, and frankly it is a nightmare because no one wants to take those tickets and everyone avoids it like it is radioactive. Personally I have had to do quite a few of them and every time I find it worse compared to React, people just seem to hate it and it is very difficult to find people who want to work with it, so that project is now being rewritten in, guess what, react.


I’ve had to deal with a nightmare Elm project. The difference is, I know what I’m doing. I solved all the problems, created examples to lead other devs and everything was fine. Have your company contact me if you need help.


i could say the exact same thing as a React dev.

> I’ve had to deal with a nightmare Elm project. The difference is, I know what I’m doing. I solved all the problems, created examples to lead other devs and everything was fine. Have your company contact me if you need help.

I’ve had to deal with a nightmare React project. The difference is, I know what I’m doing. I solved all the problems, created examples to lead other devs and everything was fine. Have your company contact me if you need help.


Frankly, I've worked with a couple React projects that are exactly like you describe, too.


The key difference being the team has 20 people that are fluent in React, vs the guy that decided to write it in Elm and left last year.


I've seen those React projects get rewritten.


Many reasons not to use Haskell, not just the ecosystem.

Source: 7 years of Haskell in production


ghcjs is not production ready imho

shipping as wasm is not an option as it increase bundle size for very little gain (unless you're running something super performance intensive).

We would need a bridge between sane languages and a JS framework, not just JS in general.

5 years ago I would have done a Haskell -> hyperscript bridge to build frontend applications. Today I would do a Rust -> Solid.js bridge to build frontend applications.

Logic could be compiled down to JS, UI could be compiled to Solid.js components.


People suggest adding other languages to browsers all the time. Why not - because then you get bombarded with thousands of “why you need that”.


One of these days an LLM will translate ecosystems to less popular platforms. Or at least it will write the glue logic.


Isn’t the irony of this that LLMs will only have enough training data to generate meaningful code for popular frameworks?

Less popular platforms will get more isolated rather than less as the wave of generated code that “works out the box” only works with stuff like react…


Javascript is the ecosystem. The majority of those react libraries are thin wrappers on vanilla javascript libraries.


this one's my absolute favorite: https://www.npmjs.com/package/react-public-ip?activeTab=code

Not a single bit of "React" in the code. It has absolutely NOTHING to do with React. But I've seen it in projects I've inherited... just because, "we're using React, may as well get the React version of the library".


If I thought I could deliver a better product and faster with Haskell, I'd use it.


They would have. In 2014 when React was new, the obvious safe choices were Underscore or Angular. Maybe Ember if you were clever. React would have been new and required a lot of justification.

Likewise Svelte is mature and well understood enough that like React, enough nobody could get fired for choosing it either.


People & thinking like this makes frontend development more complicated than it already is. I refuse to work with people who has this thought, had to make my HN comment ;) I think automated acceptance testing in browser is king rather than unit tests on the frontend.


> I refuse to work with people who has this thought

So you refuse to work with people who do not want to re-invent the wheel for a shiny new framework because it is "better"?


the problem is that every framework comes with only three of the wheels you need, but in each framework the missing wheel is different, so you will always end up "reinventing" a wheel that another framework already has, because if you switch to that other framework, you'll have to reinvent a different wheel instead.

if you don't want to reinvent a feature that another framework has a solution for, then i'll ask you to show that this other framework solves more problems than the current one, and it's worth the cost of switching (or switching back).

but, like you, i don't like to switch to a new framework just because it promises to be better.

i prefer to avoid switching frameworks as long as i can. i'll only switch in a project when i run into a problem that the current framework can't solve at all.


Well, I work for a Fortune 100 company and our standard is Vue, so, yes, using React could potentially get me fired ;-)


You have posted this reply in multiple threads on this post. Is it really that clever?


> no one ever got fired for choosing react though.

Probably because they had already moved on to do the same thing at some other company for more money.


It might be hard to swallow but: there can never be real progress on the frontend without having a programming language that is powerful enough to properly support the developer.

Programming languages are always laughed upon and most of the time I hear frontend developers telling me that frameworks are what's important, not the language. But I think typescript shows how impactful a better programming language can be.

Unfortunately, even typescript - despite of how great of a language it is - isn't capable yet to support even basic cases.

For instance, using the features of the language to describe a nested structure of components, each of which has different dependencies that are a subset of its parents dependencies. Such a thing cannot be expressed with typescript, so frameworks/libraries all come up with their own way of doing that and in consequence giving up on typesafety and hence making it way harder to understand things and way easier to make subtle mistakes.

I hope we will see major improvements on that front eventually. However, powerful programming languages are hard to learn and take time to master - something that is often doomed to not survive in the frontend world where things are fast-paced.


> For instance, using the features of the language to describe a nested structure of components, each of which has different dependencies that are a subset of its parents dependencies

I may be misunderstanding you, but this seems tractable with React.memo. Merely encode the dependency or lack thereof in the propsAreEqual predicate.


> I may be misunderstanding you

I think so, but I probably haven't explained it well. Let's assume the following structure:

<Outer> <EditListElements> <UIElem>1</UIElem> <UIElem>2</UIElem> </EditListElements> </Outer>

Let's say EditListElements is a generic 3rd party component.

How does the definition of the props/dependencies of the elements look like?

I would like it so that when I define `Outer`, I define some props that outer needs (e.g. let's say it needs an A and a B) and then the actual props to initialize it become A, B and <Props of EditListElements>. But EditListElements is a 3rd party component, which itself derives its properties based on the children it uses. And so on.

One of the reasons to do it like this is that if I have a big, nested graph of components and I add a required dependency value to some component down the graph then all the intermediate components should have the props "automatically" updated and I will have to pass it to one of those components (potentially the very toplevel component) to satisfy the compiler. Then, it will be passed down automatically to where it is needed.

The way this is currently "solved" in react most of the time is to move those required values to some global store or so which is then accessed or at least accessible by all components. It quickly leads to a big ball of mud and it is tricky to see what a component needs (and what it doesn't need) by just looking at the component in the graph.

Hope that makes it more clear.


If Reason/ReScript didn't fumble the bag, with their fork/rename, things could have been better.


The operating system you are using is written in C.


Let's assume so. What's important though: If it had to be completely written again from scratch today, would it be done in C?


I don't know, but this point is already refuted:

> there can never be real progress ...

> without having a programming language that is powerful enough

Historically there have been plenty of interesting powerful languages on the periphery, but most of the useful stuff is not written with them.


no, it would obviously be written in ocaml


It's funny how the author complains about React, then goes on to talk about "web components", probably one of the worst features of the web. Not all "standards" are good and deviating from them is not always bad. React has also reinvented itself multiple times, in loose chronological order:

- React launched

- JSX became the official recommended way

- CSS-in-JS became the way

- Context was invented

- Hooks were invented

- Server-side components


- Switching from class-based components to function-based (this was before hooks, when everyone started using Redux & similar instead of class components' state)


The Collinsworth law of internet headlines: Whenever a headline contains the word you, the author meant I.


I'm still waiting for Web Based interfaces to catch up to where we were with Visual Basic 6 and/or Delphi decades ago. It seems like this is a hint to move in a better direction.

Today I learned what a Web Component was, and there's a lot more boilerplate and manual copying of properties than I'd like, but it seems better than digging around in the DOM with JavaScript.

You all have my sympathy. It would be so much easier if we could just run mobile code without having to worry about all of the side effects it could cause. (Including the extreme side effect of taking out our systems completely).


As someone who’s only dabbled in “modern“ front end (mainly a small project built with web components, my bread and butter is native desktop/mobile), I can’t help but think what continues to hold the web back from achieving something like VB6 is its batteries-not-included nature.

As long as it’s necessary to re-invent wheels by building basic widgets from scratch, there’s going to be limits to how good the developer experience of front end web can be, as well as high churn because the common base that’s being built upon is so tiny. It’s like building a skyscraper atop of a food cart: technically possible, but all “solutions” are so stilted and full of trade-offs that there can be no consensus and inordinate amounts of energy get burned on constant re-engineering of the stilts.


> I'm still waiting for Web Based interfaces to catch up to where we were with Visual Basic 6 and/or Delphi decades ago. It seems like this is a hint to move in a better direction.

This is pure insanity, we left those in the dust decades ago. Those were horrible interfaces.


This guy is crazy to write an opinion article without examples (only the opinions) and without expertise or understanding of the history, the current solutions, and their differences.

React is bad is youre bad. Its much more fundamental than other frameworks. It also paradigms shifts from imperative to (more) functional. So if you are not comfortable with closures and side effects (like the author), you will get lost.

None of the pattern from any framework is new. Theres only so many ways to design systems, you either use callbacks, observers, or events. All have their pros and cons (where imo observers and events are inferior due to their quick branching factor in larger codebases). React gives the option to use any of these.


> It also paradigms shifts from imperative to (more) functional. So if you are not comfortable with closures and side effects (like the author), you will get lost.

I don’t think it’s that simple. I write in a functional language for my day job, yet React hooks style components still give me headaches because they are leaky abstractions where you have to know what they’re doing under the hood anyway.

This argument feels a lot like 15 years ago when C++ developers were saying C++ is bad if you’re bad. Some are probably still saying it, but its pitfalls and crippling complexity are pretty widely acknowledged at this point.


I found this a frustrating and misleading post:

1. Starts talking about empiricism, does not actually deliver on it

2. Talks a lot about how React-things are old-actually, and then talks about signals and two-way data-binding as if there wasn't a time before React where these things were also pushed. React's non-adoption is not an accident I think, and these kind of posts would be more interesting if they would leave the surface-attacks and actually engage with the philosophy behind React's approach[1].

3. Quoting Alex Russel suggests you are more interested in heat than light (which is what he is known for where I'm from)

4. Distorted guitars are good actually.

[1]: https://gist.github.com/sebmarkbage/a5ef436427437a9840867210...


That gist looks like a bit of a list of strawman arguments to me. Most of those have never occurred to me, but lets look at one that has

"Stale closures in Hooks are confusing"

Seb gives an example under that section that they call confusing. I don't understand why. The syntax makes it very clear when the values are checked - if its in a closure, its clearly at the time of the click - if its not in the closure, its clearly at the time of rendering, so no, they are obviously not equivalent.

The problem with React hooks is that they behave very differently from all normal JS code. In normal code, most functions that contain closures in them run once and the closures run zero or more times (depending on the consumer of those closures). In React, the render function runs many times, but the inner hook closures run a different (could be smaller, equal or greater) number of times, where that number may depend on the number of times render runs or the number of times other closures run.

You can easily create a mess this way; React realized this, which is why the official documentation recommends not modifying state from within useEffect. But current frameworks (e.g. Remix) already do this, and this already causes problems with batching (see https://twitter.com/oleg008/status/1680290734644002816). Additionally, dependencies between multiple useState and useEffect calls can easily be non-obvious - they may be embedded within custom hooks.

In a mutable / signal based framework that really pays attention to all these details (like MobX) there is a consistent way to how things work based on a relatively simple dependency tracking mental model (MobX based signals can be implemented in about 50 lines of code if we're willing to forego the nice proxy syntax). So not only is state management way easier, its also on average less prone to these kind of issues.

In essence, React state managements makes things harder with the promise of making state easier and more consistent to manage long term, but doesn't really succeed in delivering on that promise. At least not when compared to more newer interations of mutable reactive state management (like MobX) which support all the goodies (automatic dependency tracking, automatic batching, automatic disposal of unobserved state and computed values etc)


> The problem with React is that behaves very differently from all of your code. With most functions that contain closures with them, the function when called runs once and the closures run zero or more times.

I don't think I agree with that generalization. I probably could not even make a generalization about what normal closur-ing does or should look like.

> In a mutable framework that really pays attention to all these details (like MobX) there is a consistent model to how things work. So not only is state management way easier, its also on average less prone to these kind of issues.

My experience with MobX and the greater observable-industrial-signal-complex is that accidental loopiness very much can and does still happen. I have seen codebases with complex MobX computed-changes-graphs that senior engineers were clever enough to write but not to debug. And I was not aware of tooling which helped keep these graphs in line.

That said, I agree React's hooks have friction to them. I just tend to be in the camp of "I prefer my computational change graphs to be gated by a bit more boilerplate".


Forgot to add this:

> I probably could not even make a generalization about what normal closur-ing does or should look like.

I would say the key reason why this looks so wrong is that it essentially breaks lexical scope. The closures "look like" they are the same values from the scope above, but they are actually values from previous runs.

I would be hard pressed to find another library API that breaks lexical scope reasoning for its closures in such a way.


> My experience with MobX and the greater observable-industrial-signal-complex is that accidental loopiness very much can and does still happen. I have seen codebases with complex MobX computed-changes-graphs that senior engineers were clever enough to write but not to debug. And I was not aware of tooling which helped keep these graphs in line.

My experience is completely the opposite. I've worked on large, complex interactive editors writtein in MobX and its been pleasently easy to reason about. Some tooling is built into the framework (cycle detection, strict mode). The design guides you towards making the right choices (prefer computed over autorun, etc) and makes those choices easy to use.

And unfortunately, with useState, useMemo and useEffect you can make the same cyclic dependency spaghetti (e.g. useEffect can easily setState). Unlike with MobX however, everything is harder.


Huh interesting, do you happen to have a link that goes into cycle detection? If it comes with MobX out-of-the-box, I can say that it did not seem to have kicked in for our use cases (but maybe it's an opt-in?)


I think its always been built in, but pertains to `computed` values only. Its still possible to create cycles but you need to combine `autorun`, timers/nextTick/similar and actions to do it - definitely not something thats needed in most code.

Some other methods for tracing and debugging complex graphs are described here https://mobx.js.org/analyzing-reactivity.html


Neat, thanks for the link!

I vaguely remember my colleague having a reason for why his abstraction did not fit in the computed box. Probably something related to async, so it might very well have been because of that


What do you mean by:

> Quoting Alex Russel suggests you are more interested in heat than light

I know he's said a lot of harsh things about frameworks like React, Css-in-js, etc, but I've read all of them from the perspective of "these things are hurting the UX a lot more than you think".


I'm right now only finding this one, not sure if some older tweets are gone. I remember him as someone who does more anti-marketing than furthering discussions.

https://twitter.com/slightlylate/status/1595328476956876800


I just see him stating an opinion? It’s a valid one.


I had a PM suggesting we move from using git to dropbox because github is "hurting the UX".


Honestly, if that's what the research shows I think that needs to be considered. It'd be healthy to challenge those claims, and engage with how and why your revision control tool is hurting UX.


False. React is perfectly fine. It seems the writer didn't really take the time to understand it. It was essentially rewritten from scratch a few years ago, and hooks are modern, simple, small, make sense.

useMemo memoizes a single value/"variable" for the most part. useCallback memoizes a function.


Absolutely this. React is just a renderer and 6 hooks, all of them bound to the respective functional concepts which make it a simple and beautiful tool for creating user interfaces. Comparison to web frameworks is incorrect here.


I know many developers who want nothing to do with frontend work because of two main factors, 1. The obsession with bleeding edge technology and 2. The developer community being disproportionately composed of young and/or new and/or self-taught developers who "discover" new paradigms constantly. Those factors create a constant churn in technologies in which nothing is learned and everything is repeated every six months to two years. It's like watching mayflies argue about politics.

This article feels much the same.


That's what made me so confused about the framing of the article, because it seemed like it was going to go the other way.

> Things you forgot because of React

Ah, this is going to be a back-to-basics, here's how great vanilla JS, HTML and CSS can be.

> I used to only listen to new music, updating my tastes with each week, and was never really satisfied. Then I discovered that there were certain genres that didn't update each week, and were timeless and satisfying.

Ok, this is definitely a back-to-basics, don't jump on the flavor-of-the-week

> React is old news now, here are a dozen new flavors of the week.

Wait, what..?


I was laughing at the line that hooks are as old as his kid (as if this made them ancient) followed immediately by the comment that his kid is going into pre-k.

His kid is... drumroll... 4 years old.


That's a really curious perception of time. I consider everything as old as my kids spanking new. My oldest is 16.

I wonder what causes this (except me being old, but still, I thought this even when my oldest 4 as well).


People should kick off a bunch of things on when their child is born to remember timescales are relative.

Buy a green banana. Buy a certificate of deposit. Plant tomatoes. Cellar a bottle of wine. Plant a redwood tree.


I made a wine kit for each of my children - it makes 30 bottles and we drink one a year on the birthday itself.

I've found it helps for scale and as a bonus you get to see how a wine really ages over time.


You probably know that not all bottled wines age well, in fact only a handful do. Usually high sugar content is important, because the sugar preserves the aromas and keeps them from evaporating. Alcohol content, acidity and tanins also play a role.

Most bottled wines are meant to be drank right after bottling or in up to 5 years, white wines less than that. They get more brown or orange as they oxydize. Prosecco and sparkling wines are usually better if they're from the previous year.


Perhaps you could argue that high initial sugar matters but final sugar content definitely does not. I only like my wines dry with no residual sugar remaining after fermentation is complete. A decade on my big reds are tasting fantastic.

I've had exactly one bottle of white go bad on me and it was somewhere in that 8-10 year range. It can definitely happen and would not recommend a white for this kind of thing . . . but this is also how you learn.

For someone not wanting to go the "make it yourself" route, I'm sure if you went to a good wine distributor and said you were looking to buy two or three cases of something you want to cellar for a good long while they would be happy to steer you in the right direction.


Having a kid is a major milestone so time perception might be tied to that moment


Speaking of timeless music:

    A change, it had to come
    We knew it all along
    We were liberated from the fold, that's all
    And the world looks just the same
    And history ain't changed
    'Cause the banners, they all flown in the last war
- Won’t Get Fooled Again, The Who


Meet the new build system, same as the old build system


Exactly, I feel cheated and I'd like my time back.


This article seems completely filled with nonsense.

After YEARS and THOUSANDS of projects proving that 2-way binding causes massive problems, the author insists I shouldn't believe my lying eyes. This may sucker devs with only a handful of years writing frontend code, but any dev who lived through those years won't be buying what is being sold.

"Hooks are outdated" is also false. I used Knockout and signals YEARS before React. Signals are NOT better. At a large scale, they are fragile and nearly impossible to debug because EVERYTHING in your entire app is a moving/mutating target. Just because they "aren't afraid" doesn't mean they aren't coding horrible bugs everywhere that will come home to roost from seemingly unrelated code changes in another part of the app.

The author claims that you can port libraries between other frameworks easily. This is absolutely false. The only "portable" solutions are going completely headless then making wrappers for various frameworks and if you do this, then React is no different than any other framework.

Bragging that you can't understand the difference between useMemo and useCallback after reading the docs (one is general memoization and the other is function-specific) isn't a dig at the framework so much as an indictment of the author.

Benchmarks are another interesting area. The actual delta between React and other systems isn't as massive as some seem to believe. More importantly, React's ability to defer rendering of some elements gives it the potential to feel faster to the user (which is the important metric).

I find the React is "hard to learn" claim fascinating. When I used AngularJS, it took 1-2 MONTHS to write basic stuff. Becoming an expert required 6 months to a year as you slowly learned the entire AngularJS codebase debugging stuff like the digest cycle. I taught a LOT of people to code React. 1-2 days to learn those basics and 1-2 weeks to know everything. The core React API has grown, but it's still not very complicated. Other frameworks may be quicker to learn, but in my experience, the difference is not huge upfront and there are almost always weird edge cases that haven't been documented that you'll run into (and that's without the signals edge cases).


> Bragging that you can't understand the difference between useMemo and useCallback after reading the docs (one is general memoization and the other is function-specific) isn't a dig at the framework so much as an indictment of the author.

Yeah, it is fairly obvious (though, to be fair, it wouldn't hurt to point it out) that:

  useCallback((...args) => {
    <*statements*>
  }, [<*deplist*>] );
is effectively identical to:

  useMemo(() => (...args) => {
    <*statements*>
  }, [<*deplist*>]);


Are they "effectively" identical or they just identical? What's the difference?


Effectively as in "they have the same effect". The difference was stated in the comment that you replied to: One is for general memoization, the other just for functions. You can use useMemo exclusively if you prefer.


But it does reflect so much that’s wrong with the React development.

Creating a first class hook whose only purpose is to wrap another first class hook, all so you can pass in a function rather than a function that returns a function.


I hear what you’re saying. I think in the abstract it seems like an unnecessary helper function. But in a historical context it makes sense.

About a year before hooks was introduced it was discovered by multiple teams that inline anonymous JSX functions could create big performance issues. This was particularly felt in react native development. The solution back then was to do the whole .bind(this) to your callback methods in your react classes.

Because of this (my guess) is the react team wanted to make it extremely obvious how you could use closure state as opposed to private method callbacks when they went intro hooks, without teams having to worry about taking a performance penalty with inline callbacks. It was not obvious to me (and I’m sure many others) when hooks came out that you could memoize functions before rendering.

Again, I get the redundancy point and maybe at this point it could be deprecated but I think you have to think about where the community was before hooks.


Memoization is saving things in memory, it's a tradeoff of memory for fewer function calls. It doesn't work with all possible callback functions (because they need to be pure based on their inputs and dependencies for the saved values to still make sense), and also you don't always want to spend the memory on it (some smart memory use is going to be more performant than the function calls, too much memory use is its own performance problem).

The two hooks have different names because they make different trade-offs.


They are identical in their effect[1]. At one point they were almost identical in their implementation. Looking around at the (much larger) current React source seems to indicate that this is still the case.

[1] https://react.dev/reference/react/useMemo#memoizing-a-functi...


In this specific case above they work the same, useCallback memoizes the instance of a function passed. useMemo memoizes the execution of the function it is passed. but both have valid separate uses.


Two-way data binding is a foot-gun for sure (I also worked in a large knockout codebase circa 2010), but man is the alternative a PITA when you’re just filling in a form. And the problem only shows up when you start propagating two-way data back up the tree.

If someone wants to invent a framework where two-way form binding is easy, but the data can’t leave the component without being dispatched as an action, I’m in.


The framework you're looking for is more or less Vue.

(some will probably disagree, but I think most that have used Vue significantly won't)


I too thought Vue would be a solid fit for what they described.


useReducer is what you're looking for


React is ridiculously hard to “self learn”. Not because React is necessarily confusing, but because React docs are extremely confusing and the transition from class components to function hook based components means you can search for a problem and find answers only for class components, whereas the function component solution is buried deep if it even exists.

And we know it’s confusing because the React docs themselves reflect the confusion. A great example is useEffect, where the original docs quite clearly state that useEffect can be used to handle side effects, whereas the new docs say it’s used to “sync” components (and I don’t remember if it explicitly says not to use it for side effects, but that’s the common understanding people have now).


> whereas the new docs say it’s used to “sync” components (and I don’t remember if it explicitly says not to use it for side effects, but that’s the common understanding people have now).

other way around. useEffect is for side effects (hence the name) and are _not_ needed for "syncing" state with props.


Thank you. I never understand why frameworks have two way data binding and signals, both are heavily bug prone. React still reigns supreme.


> Bragging that you can't understand the difference between useMemo and useCallback after reading the docs (one is general memoization and the other is function-specific)

Right, the first argument to useMemo must be a function, but the first argument to useCallback need not. That's what you meant, right?


useCallback makes sure that you don't recreate a function you need in a component at every re-render but only when its dependencies change. It returns a function.

useMemo returns a value which is the result of calling the function it is given once the dependencies change.

So useCallback is basically useMemo called with a function that returns a function.


> useCallback ... returns a function.

It returns something with the same type you gave it. If you give it a function it gives you a function back.

In typescript it's declared to take a function but in practice it doesn't check, and can be used to stabilize the identity of anything.

useMemo otoh _does_ only take functions.


> everything is repeated every six months to two years

Same feeling looking at the new Vercel SQL library. Oh wow now you can write SQL right next to your client-facing code, such convenient. You have just rediscovered PHP.

To be fair, frontend frameworks solve a problem. Application can get too big that you cannot manage all the states imperatively. Declarative UI building really help to keep the UI separated from the logic. But then management get greedy and and try to shove all the features they can think of into one single big app. Like, if you went to a page and click a button, going to another page will let you know that you clicked that button and shows up some nice CTA so you won't forget. Frontend people scramble around trying to create new abstraction to keep their working surface manageable. Then you get workflows where to get the result of an API call you have to dispatch a thunk action so it would update in the global store (my example may be antiquated, I'm away from React & Redux for a little while), instead of just, you know, call it and `.then()` update the UI.

Maybe if you have an app that is twice bigger than a normal app, maybe, I don't know, split it into two apps instead? The problem of web development app right now, I think, is because people are being monolithic where it should be independently modular, and then try to cut up your backend service into pieces when a single monolith works fine.


PHP can't run in the browser.


Ah but that's not what I am referring to. If you take a look at Vercel Postgres page [^0], you will see that Vercel is marketing a new way of writing server side rendered code, where you can write SQL code right next to the HTML-ish code for the frontend. So I'm just merely making a (meant to be humorous) comparison with PHP.

> PHP can't run in the browser.

Well actually, WordPress did it [^1] [^2]. They compiled PHP to WASM, so you can run our favorite web framework in your own browser.

I see your point anyway. Systems evolve. Tooling has to follow suit. PHP cannot achieve some of the feat today mega stack can. The problem arises when we apply the latest bleeding edge technology meant for systems that have to serve millions into our little MVP that may have less than 1000 users in your first few years.

[0]: https://vercel.com/storage/postgres [1]: https://developer.wordpress.org/playground/ [2]: https://github.com/WordPress/wordpress-playground


You don't need a mega stack to attach an event listener to an element. PHP can't do that.


I dont think you are listening what he is saying. The vercel sql library is serverside javascript. This could be any language. What the library reinvets is pattern that has been criticised, hated and laughed at not that long ago. Especially in this form of raw sql mixed in between html.

It was specifically the react/you-must-have-api crowd who bashed PHP bacause of this.

I guess in the end PHP was what people wanted all along.


The Vercel SQL library doesn't mix raw SQL and HTML. It can't, since that'd easily allow public db access on the frontend.

What people wanted was the speed of a server-rendered starting point and the flexibility and performance of client-side templating and interactivity. JS/React can deliver this, PHP cannot.


Wow i just said that it is server side javascript because you were claiming ... and that its mixing raw sql with html template like what was hated in PHP. Have you even looked at https://vercel.com/storage/postgres - its right there in their example.

You are either trolling me or you are not really sure how these things work?


You could do that with PHP backend + any frontend framework during the last 2 decades before.

OK, now you can do it using just one JS framework i guess? But is it a revolution? A breakthrough?


You couldn't do that before. Combining a PHP backend and a frontend framework meant you had two different html templates.


Thats not true. You had one .php file (or more, if you use includes) where everything was located: the HTML, if necessary any JS via <script> and interspersed with <?php … ?> depending on what dynamic stuff you wanted to output.

And this is parsed to one output file that is sent back to the browser.


What are you event talking about? Are you aware that any touring completel language can output JSON... what two different html templates?


I'd say don't give anyone bad ideas, but we are too late:

https://github.com/oraoto/pib


Sorry friend, WordPress already beat you to it: https://github.com/WordPress/wordpress-playground


When I was starting out in the industry, I wasn’t even a programmer yet when a lead developer sat me down and taught me about the pendulum swing. At the time it was closer to six years to two decades. It’s clearly gotten faster in the era of Stack Overflow, but if you’re seeing six months to two years, that’s ridiculous (you’re not, the situation is).

That conversation accelerated the first ten years of my career by making me more effective. I knew people who made it farther with less work than I did, but mostly I knew the reverse. So I in turn have talked about the pendulum swing with more people than any other topic.

In the Expanse, Amos talks about The Churn, which is a related phenomenon.

“When the jungle tears itself down and builds itself into something new. Guys like you and me, we end up dead. Doesn’t really mean anything. Or, if we happen to live through it, well that doesn’t mean anything either.”

If you come through chaos unscathed it doesn't mean you were good. It just means you were lucky. Don’t let it go to your head.

The motivation of people with 3 years of experience is to jump on a bandwagon that mutes the effectiveness of having 15 years’ worth of experience. You’re dragging half of the industry down in order to pull yourself up. That’s defecting, and we all know how that turns out.


I've been doing web development since 1996. I've witnessed the ebbs and flows and hype trains.

Svelte's the real deal. How do I know? Because it's not a new API or paradigm. It's the old web just better.

It encourages HTML and sane CSS, not just wrapping them in endless boilerplate. It compiles to efficient code rather than making you write all of it over and over again. It takes all the lessons from the last decade and a half and distills them into familiar web development patterns.

   <script>
   <style>
   all your HTML
   + bare minimum of logic to solve your problems
I haven't been this excited about a new web technology in a decade, so coming from an old school web dev who learned off of view source in 1996, take that into consideration.

And while I prefer Svelte, Htmx is doing a lot of the same work; not new APIs; just embracing old ones without all the boilerplate.


I love svelte too, but I would argue that the way svelte extends JavaScript by making reactivity a language primitive pushes svelte beyond "the old web, just better".

https://gist.github.com/Rich-Harris/0f910048478c2a6505d1c321...

https://svelte.dev/docs/svelte-components#script-3-$-marks-a...

https://svelte.dev/docs/svelte-components#script-4-prefix-st...


That's where this part kicks in:

    "It takes all the lessons from the last decade and a half and distills them into familiar web development patterns."
That includes reactivity and state management—two concepts that weren't adequately covered by the old web.


Well, CSS itself is a problem, because it is not component-izable and composable. I only use inline CSS now, not because it the very best aproach, but at each it keeps my projects sane after years.


It is in Svelte. Take a look. You write normal CSS as you always have, and Svelte takes care of scoping it to just your component by default.

React really made people think they couldn't expect any better.


Have you noticed that Lambda is just FastCGI, Cloud Edition?


+ multi-availability zone redundancy and resiliency, multi-region deployment options, and edge computing at CDN endpoints.

Other than that, for web functionality, they're identical! ;-)

Then of course there's the ability to supplement authentication on the backend, detect file uploads for background processing, etc. All of which are outside the scope of FastCGI.

But you don't care for Lambda. That's fine. You do you.


That only works if you think that basic HTML and CSS where at any point good platforms for building complex applications. Many people (me included) wouldn't agree with this. In that case, saying that Svelte doesn't help overcome any of those fundamental limitations of web development would not be a selling point.

Things only get worse when you add vanilla javascript to the mix.


Every web app no matter the framework boils down to HTML and CSS at its core. The furthest you can get from those is ratcheting up the number of <div> and <span> elements, then of course making the mad dash to reintroduce the lost functionality through heaps of JS and accessibility through aria roles.

Or… you could use the tags most appropriate to the problem with accessibility and SEO automatically coming along for the ride.

PicoCSS is an excellent example of what can be accomplished with just a sprinkling (~10KB) of CSS over plain old HTML.

Browsers can do so much more than they used to out of the box today. We should take advantage of that rather than silo it away in one-off React-based APIs.


Compiled languages boil down to assembly, but I wouldn't like to write them as assembly files with a few higher-level constructs sprinkled through the files.

You may disagree that html and css are that bad. But I think it was always a mess, specially when you go beyond linked documents and add any kind of interactivity and forms. There's also inherent limitations like "select" dropdowns offering very little functionality and mostly ending up as custom components in all projects I have worked in.


You seem to be taking the position that Svelte does not allow for components for cases like custom dropdowns where HTML falls short on its own.

This is not at all the case. I highly recommend actually looking at Svelte examples before commenting further.

That said, there are a lot of folks out there who don't know that, for example, combo boxes and accordions are possible with plain HTML.

    <datalist>
    <details>
    <summary>
PicoCSS is a great resource for seeing what's possible with just plain HTML and ~10KB of CSS.


I don't have knowledge about Svelte so you may be right about it solving all those issues. My contention is with regards to the general idea of the article and some comments that seem to indicate that everything was good in the web development world before React introduced a bunch of problems. React did introduce some problems, but to sell me on migrating I'll need to see that the new framework solves the issues inherent to web development, not just the issues that React created.


I do not think that is a charitable view of the article or most people's comments. We all knew what was gained. We just bemoan what was lost, much of which has been found to be largely unknown to more recent entrants into the field.

Folks aren't against solving problems. I think the main concern is the amnesia regarding problems that had already be solved and are now be solved again only not as well.


i too have been developing since 1996. and in 1996, nobody was making web-based applications with anywhere near a fraction of the complexity that modern web apps manage.

please build spotify using only HTML and JS language features from 1996.


Nice straw man you've built there. Be a shame if anything happened to it.


Htmx is nothing but new APIs bolted on to a markup language.


Where that markup language is HTML, yes, I agree.

It's a feature, not a bug. That said, I personally prefer the Svelte model. I like leveraging the client browser for effect, not just rendering everything server-side.


What a grumpy comment.

- Two of the best developers I know are completely self-taught.

- I'd argue there have been so many front-end frameworks not for the sake of novelty because the web platform itself was incomplete and stagnated. (And also blew a huge opportunity with the APIs for web components.)

- Now that the platform is evolving and innovating again, more and more things are moving out of the frameworks and back into the platform. Javascript has massively improved.

- Some amazing and complex engineering happens in the frontend space because of the constraints and the need to eek performance out of everywhere you can. You can't just throw more servers at the problem.

- Experiences vary, but I've been on more projects delayed by over-engineering the backend than the frontend.


> And also blew a huge opportunity with the APIs for web components

How? I really don't understand this sentiment.

The web components API is a gajillion times less complex to me than, for example, react.

Coupled with a light weight rendering library like lit-html, a basic component takes seconds.

- Make a class that inherits HTMLElement

- Create a rendering template in connectedCallback using your favorite templating/rendering library.

- Add class properties that call render() when they're changed.

The cognitive load is a fraction of what's needed for frameworks like angular or react.


> The web components API is a gajillion times less complex to me than, for example, react.

And then you go on to list multiple complex things:

- Create a rendering template in connectedCallback using your favorite templating/rendering library.

So you need to bind together a connectedCallback and some rendering library

- Add class properties that call render() when they're changed.

So you have to manually wire class properties to manually call render.

In comparison, React alreayd handles all of that for you.

> The cognitive load is a fraction of what's needed for frameworks like angular or react.

Since you mentioned lit-html, that "lightweight rendering library" has all the "cognitive load" of React, and is getting more complex


> So you need to bind together a connectedCallback and some rendering library

It's no different than jsx, you just get to pick whatever you want. I honestly believe that 90% of the dislike for WC comes from the name "connectedCallback". If they'd named it "onCreate" or something, everyone would be using it. It's named that because it's the lifecycle method for when a component becomes connected to the DOM, so it's technically correct - a component can be created and function without being connected to the DOM. But people really hate that name for some reason.

It's all the same stuff. You have to do all the same things regardless of framework. You declare a template somewhere, you define the props that will cause a render on change, and you keep track of the internal state of the component. With React or angular or vue or whatever, you still have to do all this, you just incur the cost of a massive framework too.

> So you have to manually wire class properties to manually call render.

Yeah, 1 line of code. And in exchange you get to avoid a whole framework, get much better performance and have real control over your component's render cycle. Also, you still have to do this with react, it's just a different syntax.

> Since you mentioned lit-html, that "lightweight rendering library" has all the "cognitive load" of React, and is getting more complex

Huh? Lit-html is simpler than handlebars. Are you confusing it with LitElement?


(( I've split my reply into three parts to avoid a wall of text in a single comment.

I may run into "you're posting too fast, so not all part may appear at the same time" ))

Part 3.

> Huh? Lit-html is simpler than handlebars. Are you confusing it with LitElement?

Of course not.

At the time of writing lit has:

1. A custom DSL for writing HTML

      <some-tag
          attribute=value
         .property=value
         ?boolean_property=value
         @event_listener=value></some-tag>
2. A custom JS DSL in the form of custom directives. Currently there are 12 of them.

They may look like regular functions, but they will throw an error if you use them outside of their scope.

Example:

    // is fine
    html`<p class="${classMap({someClass: true})}">Hello, world</p>`

    // Unhandled Promise Rejection: Error: `classMap()` 
    // can only be used in the `class` attribute 
    // and must be the only part in the attribute.
    html`<p style="${classMap({someClass: true})}">Hello, world</p>`
(Note: that error is incorrect because you can write `class="other parts of the attribute ${classMap(...)}"`)

More stuff is coming to lit, of course, such as contexts, server rendering etc.


(( I've split my reply into three parts to avoid a wall of text in a single comment.

I may run into "you're posting too fast, so not all part may appear at the same time" ))

Part 2.

> You have to do all the same things regardless of framework. You declare a template somewhere, you define the props that will cause a render on change, and you keep track of the internal state of the component.

> ...

> > So you have to manually wire class properties to manually call render. Yeah, 1 line of code.

So, there are two issues with these statements.

Main one is this:

So, for each property you need to track you need to manually call render. For each property in each component you write. Where in React, Vue etc. you... don't have to write that "1 line of code" at all.

And of course, "cause render on change" is trying to completely ignore the realities of re-rendering. If you "just call re-render", yo will run into a whole host of issues.

Example: You have a text box that has constraints on min and max number of characters. When constraints are validated, you want to re-render the input box with a red border. Well, the problem is: if you just re-render it, you will trash existing HTML, and replace it with new HTML, losing input focus.

And that's even before going into the fact that you want to minimize the amount of things you need to re-render. And "just re-rendering" trashes significant chunks of HTML.

That's why other frameworks (including lit) are not "just use template, track internal state and re-render". They track all the places where changes may happen, they keep track of user focus and input, many try and maintain scroll positions when large html changes happen.

---

The other issue is that it's not just properties, of course. It's also attributes.

Web components had a perfect opportunity to remove the distinction and only go with properties, but that opportunity is squandered. And the problem is: you can't reliably distinguish between the two. That is why libs and frameworks either give up and provide different syntax for setting them (like lit's `.property=` and `attribute=`) or rely on runtime heuristics.

And this is evident in the absolutely atrocious API surrounding attributes where you have to painstakingly manually sync attributes with properties in `attributeChangedCallback` with a bunch of `if name === "x" then`. Oh, and it's completely divorced from the `observedAttributes` callback because of course it is.


(( I've split my reply into three parts to avoid a wall of text in a single comment.

I may run into "you're posting too fast, so not all part may appear at the same time" ))

Part 1.

> I honestly believe that 90% of the dislike for WC comes from the name "connectedCallback". If they'd named it "onCreate" or something, everyone would be using it

Of course not. None of the criticism towards Web Components ever mentions "connectedCallback", or how it should be named differently.

Do you know the actual reason so few are using them? Let's skip the atrocious not-really-high-level not-really-low-level imperative API that they offer.

How about:

- 13 years after introduction they still need 20 more specs to try and patch just some of the holes in their original design: https://w3c.github.io/webcomponents-cg/2022.html

- Shadow DOM is infecting every spec so that the actual useful specs like Scoped CSS have to be delayed almost indefinitely to try and figure out how to work with this abomination of a design

To quote the report linked above, "many of these pain points are directly related to Shadow DOM's encapsulation"

- The amount of specs that are required to make them work, barely, and be "good web citizens". And the amount of APIs.

Oh, you want your custom input to a) be able to send its data in a form, and b) be accessible to a label outside of your component? Well, there's a separate API for a) and there's some separate future API for b). And meanwhile your custom button won't be able to submit your form, sorry, it's a 4-year old issue with no solution: https://github.com/WICG/webcomponents/issues/814

And all that despite the fact that there are already a dozen specs covering web components, and dozens more on their way.

- Web Components ar HTMLElement. It means you cannot use them inside SVGs.

This is impossible:

    <svg>
      <x-axis min="2000" max="2019"/>
      <y-axis min="0" max="100"/>
      <scatter-plot points="..."/>
    </svg>
This makes them unsuitable to a huge swath of graphics- and visualisation-related applications.

- A smattering of other issues:

-- They cannot be easily used when progressive enhancement is required: SSR story is still non-existent, you can't easily update the original DOM in a custom element without trashing it.

-- They cannot be easily lazy-loaded because slotted content is eagerly loaded:

    <p>Toggle the section for more info:</p>
    <toggled-section>
      <html-include src="./more-info.html"/>
    </toggled-section>
`html-include` will load in its entirety even if you never toggle the section. And yes, this causes a cascading loading of multiple resources, too.

-- they share a flat global namespace. Of course this will be solved in the next five years by a yet another spec.

--------------

If any userland framework had these many issues, it would be laughed out of the room. And yet here we are with people trying to argue that they are good now actually and all that stops them from being used is "connectedCallback" name.

These are also the reason why most framework authors that initially supported web components (Vue, Svelte, Solid) are now at best completely indifferent towards them.


Not going to go through point by point, because this isn't a great format for longer form discussion.

In general, the points you're raising apply to edge case use of WC.

Most of your gripes are around shadow dom, and I understand that and agree with you - CSS parts and all that stuff are pretty bad. However - I don't use shadow dom. It was intended to be low level API for when you need to author with complete encapsulation.

I've been doing native WC for years and I've never run into a situation where I need shadow dom. Or slots. Or any of that stuff.

The "attributes" vs "props" thing is a html/dom issue, not a WC issue, and again - just about any rendering library will deal with it for you, the same way react or vue or whatever does. It's an utter non-issue in normal development, I write WCs every day and haven't even thought about that in forever.

SSR and lazy loading are anti-features for me. If you really want them with WC the sure, jump into a framework like stencil, but I have zero use for them.

SSR is all about SEO and FCP, and I've never really grokked it's usefulness.

If I need SEO I don't do UI SPA stuff, I just write server side, and I don't need a component framework for that. FCP (first contentful paint) is already a gazillion times faster with WC than any framework I've ever used. The whole point of lazy loading is to defer work until it needs to be done, but you already get that with reactivity - you trigger your component data load on a property setter anyway if it needs to load, and if it's just rendering off properties there's no need for a lazy load.

The TLDR is that you're making this massive straw man argument about bad API with WC, but it's for this tiny edge case of use that's only intended for library authors and such.

The 99% use case will never encounter any of that.

I could build up a big(er) wall of text about the same sort of stuff for all of the frameworks too.

When you want to do complex things - it's complex.

In years of WC work, light weight components using light DOM and a little templating library - I've run into the issues you're talking about exactly zero times.

Also, you may want to double check your understanding of frameworks use and embrace of WCs.


> edge case use ... I've ... for me ... I ... straw man

This is why I hate engaging into any arguments with proponents and apologists of web components.

Any concern and criticism is brushed away as non-existent and insignificant. Even if the actual people who develop this and push this into the browsers are now marking them as not only valid, but a significant problem.

But sure, do keep telling yourslef that theonly reason why more people don't use them is because people don't like the name "connectedCallback"

> you may want to double check your understanding of frameworks use and embrace of WCs.

Please do this yourself. Outside of frameworks and libraries that explicitly advertise themselves as being 100% based on web components (like lit and stencil) almost no one uses them as the foundation. They may consume them, and they may have a way to compile components to them, but almost none actually use them.

And yes, keep telling yourself it's because of "connectedCallback" naming.


> Now that the platform is evolving and innovating again, more and more things are moving out of the frameworks and back into the platform. Javascript has massively improved.

A language so good you need to write another language that compiles into that language to make it tolerable.

> Some amazing and complex engineering happens in the frontend space because of the constraints and the need to eek performance out of everywhere you can. You can't just throw more servers at the problem.

I'm not sure about this opinion. Most websites are slow as all get out and require me to download the world to even get working.

> Experiences vary, but I've been on more projects delayed by over-engineering the backend than the frontend.

As a person on the backend I can tell you your definition of "overengineering" is ignoring the fact we have to deal with frontend cowboys all the time. When SEVs happen it's us on trial almost universally. Just the absolutely bonkers states a frontend can accidentally end up in despite good testing is enough to warrant "overengineering" to try to support it.

We had an opportunity to kill javascript and instead we embraced it. We deserve what we get.


> A language so good you need to write another language that compiles into that language to make it tolerable

If static typing is your thing, I guess. It's not for everyone.

> We had an opportunity to kill javascript and instead we embraced it. We deserve what we get.

Some of us quite enjoy the language.


> A language so good you need to write another language that compiles into that language to make it tolerable.

Some people need it to make it tolerable. That happens on every platform. You have Java and Kotlin/Scala/Groovy ... Microsoft even created F# to its C# ...

> We had an opportunity to kill javascript and instead we embraced it. We deserve what we get.

You mean VBScript? Or what other opportunity you mean?

I often get the sense that JS haters last saw the language in 1999. Modern JavaScript is a very nice scripting language. Succint, elegant, functional.

Its major omission is the lack of static typing, but JSDoc and WebStorm make it tolerable.


That’s something people have said for a while but I’m pretty sure React was the main thing people were moving towards 5 years ago and I think, for the most part, people are still using react. That doesn’t sound like constant churn or people switching frameworks all the time (caveat 1: react has changed from eg classes to functional components and hooks; caveat 2: maybe front end is broken into groups and one picked up react 5 years ago for two years, another picked it up four years ago switching away after two years, and so on, and I’m just combining them all as ‘used react for five years’ in my head).

I feel like the churn has gone down over time. But maybe that is also a decrease in my personal interest in front end as well as posts here (I recall there used to be a lot more frontend related posts here ~10 years ago)


5 years ago I was the lead architect on a v2 rewrite project of about 30% of our app.

We considered React but the landscape was also full of Angular and Vue and a bunch of others I don't remember.

At the end of the day, we went with the latest version of our boring server side rendering library that the rest of the app used. A huge reason was the churn in front-end javascript libraries.

I've never once regretted that decision and the project was a big success.


"we went with the latest version of our boring server side rendering library that the rest of the app used."

Boring tools are the best thing ever. What did you use?


We went from JSF1 something to JSF2 something.

Very boring but there was so much technology change already in this rewrite that we chose to limit the amount of new stuff for everyone to learn especially when we didnt know if it would be applicable to anything in their future career.


”especially when we didnt know if it would be applicable to anything in their future career.”

Wow, you made architectural decisions based partly on optimizing the employees career development? Kudos! I’m not sure how common actually investing intentionally in engineers careers is?


Seems to confirm his point, and matches my experience as well. Front end has largely standardized on React. Vue is a distant 2nd and Angular is really not even considered for new projects.


About six years ago I went backend to avoid the React churn, hoping it would eat itself by now. Unfortunately that didn’t pan out. Apparently it’s the new Struts.


The thing that these young and/or inexperienced developers don't understand is: Frameworks are not your friend. Framework projects are not created with your benefit in mind. Frameworks are created as an opening salvo so that some developers or organization can gain a foothold in the landscape and start collecting money from consulting contracts. The reason there are 1,000 React alternatives is not "people like signals more than hooks", the real root cause is 1,000 people want to steal market share from React so they can get paid as a consultant. "I like signals more than hooks" folks are just useful, predictable pieces of the landscape to be manipulated in this scheme.


Frameworks are your friend; either the one everybody used or the one you invariably end up writing from scratch for yourself for every project.


Indeed, a framework written to be used for a project has a limited amount of time where it's your friend. Until the big 2.0 rewrite comes out and they changed the API completely, and the clock starts counting down to the rapidly approaching 3.0 release where they will rewrite the API, before two weeks later announcing 4.0 alpha 1...


Maybe it's just because I'm old and grumpy and have seen lots of things come and go, but I don't understand how some frontend devs even have this much time to obsess over their tools.

It would be like car guys spending more time arguing about whether Snap-on is better than Craftsman than actually talking about and working on cars.


Snap-on and Craftsman are actually pretty antiquated tools by modern car guy standards. If you want a real wrench you go with a Mac RBRT - it’s the new hotness in combo wrenches but there are decent alternatives out there from Wright and Proto. Here’s a great video showing things you might have missed if you’ve been in Craftsman world for a while[1].

[1] https://youtu.be/hxtgWSpTC0o


I have absolutely no knowledge in mechanical engineering before and I am now really in a youtube-binge about wrench. Not sure it is a good thing that I can get captivated by absolute random topic or a bad thing because how technology just suck up our attention.


Have you met car guys? :)


> but I don't understand how some frontend devs even have this much time to obsess over their tools.

most of us don't. these comments are mostly from people whose idea of "web development" is a form and some static content.


Have you seen r/tools?

I thought the SnapOn koolaid was stale fifteen years ago. Turns out no.


It's disheartening to realize that the frontend space is no better now than when I began my career in 1990. And it's also disheartening that even though computers are like 5000 times faster now, that they feel slower to me as a developer and as an end user.


Nah, you're just focusing on the opportunities to improve rather than counting the victories. Here's my top 3 big steps forward of the last 20 years:

* Webapps don't need to be installed

* Webapps work on all platforms without vendor lock-in

* Webapps aren't trusted and get sandboxed by default

and a bunch of minor victories along the way (you can right click -> inspect every webapp, APIs generally exist and have entered the cultural lexicon, cross-site SSO exists and works).


These are good points.

At the same time, a lot of the UI tooling and APIs feel like we went back 30+ years. Everybody is still reinventing the pop-up menu button (aka “select”). I really thought this was a solved problem in NeXT by the early nineties.


> Webapps don't need to be installed

Was true of what I was doing in 1988 too.

https://en.wikipedia.org/wiki/Andrew_Project


vrml was also invented 30+ years ago but we're not lamenting that webgl is solving an already-solved problem.

https://en.wikipedia.org/wiki/VRML


Telemetry, ads, SAAS, terms of service, data breaches, platform effects.


Wholeheartedly disagree.

Advancements to CSS have made front-end way more reasonably than they were in the 90s. Stuff that took weeks to figure out with tables can now be done so quickly with `display: flex` and the whole grid system. It's beautiful.

If we had `display: flex back` in 1998 I probably wouldn't have stuck with FE rather than dive into the backend.


Web dev (as in: HTML and CSS) improved a lot in the last 20-30 years. But if I had to quickly make a fully functioning interface and had the choice between today's web and 2002's Delphi 7 I'd choose Delphi 7 in a heartbeat. And just look at what non-technial people were able to do with Macromedia Flash in the early 2000s. You need experienced frontend devs to recreate what designers did as a hobby back then.

Of course those solutions don't solve the transition between desktop and mobile layout (since that wasn't a thing back then), but more some modern frameworks solve that well (like whatever MS calls UWP right now) without forcing everyone to reinvent a way to do infinite scrolling without running out of memory


This reads as if written by someone with rose tinted glasses.


+1. would love to see an example of something created in Flash by a single designer that takes a team of frontend devs to create today.

fyi folks, Flash is also based on ECMAScript! just because the mid-90s tooling built by Macromedia triggers your nostalgia doesn't mean it was better!


If he is comparing things to 1990 then that means he's using "frontend" to included non-web UI tech as well, in which case flex vs tables isn't really the main point of comparison.


Nah. Tables were easy. All the craziness came with people using <div> as <table>. That was only recently fixed by flex box.


Agree. I did CSS before flexbox was available, and I have no ideas how I did before. There is tons of very good stuff coming our way in CSS (such as container queries), better ergonomics for Javascript, excellent tooling in the browser, stuff to be optimistic for, not just all this madness about the framework du jour.


I think this is what they meant by rediscovering or reinventing new things over and over. Yes, display:flex is newer than XUL and different in some ways. But 20 years on it seems disappointing that display:flex is perceived as such an advancement by those who have forgotten or never knew the past.


What? A few days ago I gave up trying to write a moderately complex component based on flex-grid. The number of options, and all the quirks of them, was overwhelming, and in the end I couldn't even get the basic behavior I wanted. Maybe i will try again some other. I think display: flex is very useful, display:grid is too complicated with the way they designed it.


It was all backend in 1998.


PHP running as lambda functions^W^WCGI. Those were the times.


What's wrong with this?

   float: left;
Oh wait… that was 2002 at least.

"Tables ought to be enough for everyone."

There we go! Nailed 1998!


Wow, I guess I really needed the sarcasm tag there. It appears some folks didn't get that this wasn't aspirational.


Dont forget clear:both; !


I was writing software when I was 12 in Clipper. The industry became riciculously slower since then.


The industry, sure - but the tools exist today to get things done faster than ever before. It is the people that are the problem, as always!


> It's disheartening to realize that the frontend space is no better now than when I began my career in 1990.

I disagree. Since I started programming some 20 years ago, I relearned web (and especially JS) every 5 years or so. And each time I was pleasantly surprised at how much simpler / elegant / clean things have become.

> that they feel slower to me as a developer and as an end user.

that's true though.

It possible (and even simple!) to make web-apps that are almost just as fast, but no one does that (at least not in the main stream).


Alternative history! I began my career around the same time, and I remember applications taking minutes to start up, Word/Excel crashing and corrupting your file with regularity, and all kinds of horrible anti-patterns. Applications always are as slow as users can tolerate, which roughly end up being about the same over time, but tolerance is typically lower these days.


What are you smoking?

The web has developed immensely since the 90s.

If some UI you use is slow it's certainly not because of the excellent frontend/web technologies we have today.

There are certainly many things to complain about regarding the state of the web but the frontend technologies are not to blame.


But it's been like this for more than a decade now.

Frontend work is unglamorous to a lot of developers but part of the more academic appeal is that it's still very much in its awkward teenage phase. That makes it appealing to tinker with and try to find a "better way." That's the churn.


It's been like that for at least 3 decades - which is how long I've been doing such work. I disagree with your assessment of it being an "awkward teenage phase". The rate of churn is accelerating while nothing really new theory-wise has been added. I agree with the parent post:

> disproportionately composed of young and/or new and/or self-taught developers who "discover" new paradigms constantly


> It's been like that for at least 3 decades

I've been there since the start, too. I disagree that it's been like that for that long, though. JavaScript was an awkward add-on at first, then a barely usable tool (early vanilla), then a stopgap measure to fix browser compatibility problems (jQuery, moo tools, underscore etc) and start to flesh out some libraries.

But the Angular/React phase was the first time people gravitated toward using the frontend as a proper language. Before then it was just a thing you had to deal with.

So 3 decades? Nah. 2 decades of "why do we have to deal with this" and 1 decade of "ok let's make this work somehow"


36 years at least. I'm not talking about WWW. HTML and JS were never meant to be the end-all of human computer interaction, but yet here we are.

I imagine an alternative history where good distributed software got traction.


> 36 years at least. I'm not talking about WWW. HTML and JS were never meant to be the end-all of human computer interaction, but yet here we are.

I have to be honest I don't know what you mean here.

The web and its frontend (and tooling) is what this thread is about. We've thrown out a lot in the mean time. Java applets, Flash/Shockwave, ActiveX, dynamic HTML ... the web has grown a lot and will continue to do so.

But the world of JS as a front-end application language is still fairly new. Until the late 2000s it was just a bolt-on for doing little things around static HTML.


The thread has been extended to cover all distributed front-end paradigms.


But your complaint was about HTML and JS being all there is? I'm not sure what it is you're looking for.


That is my complaint. And yes, I don't know what I'm looking for. All I can say is that the stack that I used 35 years ago was just as good as what I use today. An even more senior developer than myself says it this way. Humans achieve a certain level of complexity and sophistication in any given domain and have an hard time increasing it. I think we've arrived at that point with UX frameworks, and we did decades ago.


> But the Angular/React phase was the first time people gravitated toward using the frontend as a proper language.

Don't forget Backbone which preceded Angular by checks 7 days.


> The rate of churn is accelerating while nothing really new theory-wise has been added.

There's plenty of novel stuff out there, it just takes a long time to filter down to the mainstream. React hooks are probably the best example here: they're a crude approximation of an algebraic effect system from the early 2000s.


This comment smells like gate keeping to me: "developers who work with frontend tech aren't REAL developers".

Personally, I know many developers who are doing great work with frontend technologies. Some with little experience, some with decades of experience, some self taught, and some with formal CS degrees.

Frontend is a great career path for those who enjoy it.


I'm not sure where you read "developers who work with frontend tech aren't REAL developers" but it wasn't the comment you're replying to.


I mean, he did literally liken them to insects though...


...as long as the given front-end is done with a sane language using sane frameworks like Windows / Mac / Linux or iOS / Android.


None of those are frameworks.


They all come with a good set of standard frameworks?

Web ships with barely anything and when it does have something like Date handling people still write replacements for it because it's so bad.


I agree with you and think the eternal september effect is probably the largest factor working against advances in frontend dev but would posit a couple more: 1) front end dev is generally underestimated and under respected in terms of complexity, I have had many devs say “you are basically just building a json viewer” over the years which is somewhat true but a great oversimplification 2) the closer you are to the user the more ephemeral and hard to reuse your components are, and business incentives work more strongly against reuse because the higher ups can actually see the work that is being shared.


> business incentives work more strongly against reuse because the higher ups can actually see the work that is being shared

Can you talk more about this one? I think this is getting at something I've seen but have been unable to articulate thus far.


This is me. But the reason for this being the space is inundated with front-end frameworks - like there's a new one out every week. The nature of the industry is that you have to be up to date with everything. Like I had worked on Angular at one point but recently had to work on an older version and I couldn't figure it out easily. React was decent but now there's NextJs and Svelte etc.


NextJs is still react.


Well put. On the other hand, I pray that the industry doesn’t ossify right now around Facebook’s dominant framework. Sweet Jesus, anyone but Facebook.


It's open source, who cares who the originator is?


Tell that to people who're moving from the open source CentOS project.


tl;dr: I love web development again.

You obviously haven't tried Svelte yet. I would have agreed with you a few years ago though.

The churn as I've seen it has been a direct result of React's ecosystem, not in spite of it. Here's a partial list of React libraries that just provide state management:

    MobX
    Recoil
    Redux
    Akita
    Context
    Hookstate
    Zustand
    Jotai
Just for state management! And all exist solely because React state management is a monumental fustercluck.

Then you get into React API nightmares the article mentioned that have nothing to do with HTML, CSS, and JS but have everything to do with React's API quagmire.

You may scoff at pointing to Svelte as "just a new shiny", but it really is getting back to the web's roots. Htmx as well. I've been doing web development professionally since 1996. I have hated web development since soon after React was introduced. React solved a lot of big problems to be sure, but it introduced its fair share as well as made web development tedious in a way I hadn't experienced before. I wasn't developing for the web anymore; I was developing for React. I constantly felt detached from my actual target. Wrapper after wrapper of familiar vanilla libraries to shoehorn into the React ecosystem rather than living alongside it.

Svelte (and Htmx to a lesser extent) gave me back plain ole HTML & CSS. Svelte also gave back that simple JS that described the problem I was trying to solve instead of endless boilerplate on an API layer on top of the browser API.

Vue got close but didn't go far enough. SolidJS just made a faster React. Svelte and Htmx embraced the web with no holding back, and I love them for it.


so you'd prefer that there was only one state management solution for every webapp? what if i don't need 99% of the features of this monolith library?


Seriously, try Svelte. See how its Stores API works. For bonus points, look at the Context API. Between Stores, Context, and what looks like plain ole JS in the component, state management is a solved problem. With all due respect, calling it a "monolith" out of hand just screams you haven't even looked at solutions and don't know what you're talking about.

SolidJS stores work the same.

In other words, this is basically a solved problem unless you live in the React ecosystem.


What state management does Htmx provide?


Htmx defers almost all logic to server side. That's the tradeoff, and it's a major shift from what we've become accustomed to in the last decade (unless you've been writing PHP or something similar).

You provide listening points to various parts of your app, and when something changes, all points listening to that key also make the corresponding call to the server for refresh. It sounds hokey, but it's very effective, very efficient, and pretty easy to wrap your head around.


Deferring all logic and state management to some mystery and messy server-side black hole? Sounds like a monumental fustercluck.


Not any more than REST is. Server-side rendering doesn't have to be messy. In fact for most modern frameworks, it's become table stakes.


And how many libraries and frameworks and methodologies are there for server-side state management?


State on the server side is often a very different animal from client side. Whereas on the client, everything is either JS and/or a browser API, the server side allows for relational databases, Redis caches, and all sorts of other strategies, some based on session ids while others using whatever fits for that scenario. "It depends" but it's not just a library or framework as you'd imagine coming from frontend development.

Htmx is quite popular among folks who prioritize and enjoy server-side development. Svelte is likely more popular among folks who enjoy browser-based development. There is certainly some overlap between the two camps, but that's my take on it.


Wow. Relational databases, Redis caches, session IDs, different strategies for different scenarios... sounds like a fustercluck, no?


Not if you're a backend engineer. Then again from their point of view, they consider frontend state management to be a hopeless mess. Takes all kinds.


And why does a backend engineer's point of view on frontend state management matter? Why is a variety of options and strategies for different scenarios ok for the backend but not for the frontend?


The frontend has… a browser. It's a much more constrained toolbox. You are forced to use JS and whatever browser APIs made available to you.

The server side is only limited by what can run in a datacenter. Any language. Any service type. Any scaling profile.

Neither is more "correct". Both have pros and cons. As for why the backend engineer's point of view matters: if you are server-side rendering, you will have a better chance of going faster. A browser will always render HTML faster than JS that generates HTML on the fly, and the server side can always be made to generate HTML faster than a browser could. You can always simply throw more hardware on the server side to speed this up whereas you have basically no control over the performance profile of a random user's browser.

Look at Google search results. It's typically not JSON over AJAX; it's rendered HTML dropped into place. Why? Because every millisecond can be quantified into gained/lost revenue.


So why is it bad to choose a frontend state management strategy in a way that maximizes revenue?


> Neither is more "correct". Both have pros and cons.

I think frontend state management is a completely legitimate choice if it fits your use case.


Are you aware that these things still exist in apps no matter what kind of state management they use?


I remember when CSS was brand new. When IE5 had the first DOM. When jQuery took over the world. That's all like 20 years of time.


> ...Server-side rendering isn’t special anymore..

quietly dries tears using pages ripped from ASP.NET For Dummies


Those developers are immature.

JS was always here to stay. Wether you like it or not. Come with solutions instead of leaving it to someone else, or worse complaining.

JS was always super exciting, with a few lines you could build entire applications.


It's not so much about JS somehow being a language like no other, it's more about the web: HTTP, HTML, DOM. And XHR/fetch - JS wasn't exciting before them.


Could you please elaborate on this statement: "The developer community being disproportionately composed of young developers" ?


That's simple enough. Look at StackOverflow's survey (or any other) over 50% of professional devs have less than 10 years of experience.

That's 2013 or the year React came out and a full 5 years after the launch of Chrome/v8 started the next round of the framework wars.

On the frontend, things are even worse. Salaries started to skyrocket 7-8 years ago and the number of people suddenly interested has skyrocket every year for the past 5-6 years.


> Look at StackOverflow's survey

Part of the problem with this methodology is SO is useful among the most junior devs. For example, I haven't been to SO in several years but it was my go-to site in 2010.


The very large State of JS survey skews to even less experience overall with nearly 30% having less than 5 years of experience and a bit over 50% having less than 10 years of experience.

https://2021.stateofjs.com/en-US/demographics/


Yea i also noticed recently that survey is actually really skewed in that directio. And as such shouldn’t really be used as basis for any “state of the developer landscape”


You've misquoted, but I think the intent was clear; (commercial) front-end is more likely to get less experienced developers as the entry requirements are slacker at the lower end.

This lack of experience carries with it the same flaws and risks (and occasional benefits) that inexperience carries everywhere.


I see this as a problem to be solved in the software-education space


It totally could be solved. Make it a licensed profession. Make it like the legal practice where you have to go to school for 3 years and then pass a test to get your license. Only half joking.


agree with testing and licensing (and unionizing) but is there any particular reason people should have to go to school? one of the great things about the software industry is that anyone can teach themselves and make a healthy career out of it - would be a shame to add what might be an unnecessary gatekeeping requirement to one of the last few accessible career-paths with upward class mobility


The sad and ironic part is that additional gatekeeping won't produce better results anyway.


I think the results would be better as all practitioners would be well-versed in theory and practice. And of someone pitched a very novel approach, it would get more scrutiny. Of course we should be open to new approaches - just not for the sake of it being new.


I don't agree because current graduates aren't necessarily well-versed in theory and practice. In fact I've worked with CS graduates that don't understand theory at all and follow the worst conceivable practice. Of course CS education isn't standardized and I'm not talk about Stanford grads here. But I have a hard time believing that simply erecting barriers that require education will improve the situation when a lot of educated people still have no idea what they're doing.


The same question/discussion happens in the legal profession - and they have largely settled on the answer being "yes, you have to go to school"

IMHO, you can't have one (testing and licensing) without the other.


I've worked with plenty of educated developers who couldn't code their way out of a paper bag. One of our local universities has a shockingly bad program that's reproducing their own unique little brand of terrible bullshit. I've spent half my career fixing the messes they leave behind at various companies in the area.


I think left to our own engineers would have resolved to something like this already. The issue as I see it is corporations and business people have taken over the leadership of this trade to rake in money regardless of what it does to the real world.

And why wouldn't they you can create a problem out of thin air, solve the problem poorly selling the solution, and then when your rushed, half assed and bad solution has issues, you can simply sell the fix to that as well.

I doubt we will see much progress in the quality and rigor of software engineering in the near term, it will need to take a shift from making money in the short term at any cost to making a quality product. Instead we see the same thing happening to other industries so I hold little hope in the near term.


It's always the same. Off with the old. Let's use the new. Or new-ish.

I thought we, as in the community, learned a while ago that was a bad path to go down.

That's why there's a resurgence of old-school (yeah, I know...) frameworks like Rails. Or why things like Laravel and the PHP world keep thriving.

Well, React is old now. We know. It's the Rails of the JS world. And it's plenty good enough.

If you know JS/TS and are comfy in that, just use React. Don't feel bad for not using whatever shiny new thing is trendy now. Who cares.

No one ever got fired for choosing react, as some other commenter said.


> I thought we, as in the community, learned a while ago

If I’ve learned anything in my twenty years programming, it’s that the development community never learns anything for more than about twenty minutes. There’s too much turnover without a great mechanism for handing down folklore and war stories.


This.

I’ve been think about this a lot. Like how htmlx is reinventing something called pjax (though better). There’s many other examples. It’s a lot of newer programmers never investigating the “lore”. I don’t think it’s part of CS curriculum, and boot camps certainly don’t teach it. Forget how things they are using works. It’s woefully common for js devs to not understand how variable referencing works. (Which is super important for reactivity)


> No one ever got fired for choosing react

Well, the current top commenter says:

> I lost my last job because of it and all associated technical debt.

But I don't think a tool should be blamed there :)

But as someone that just learned (learns) react, the useThis and useThat stuff is confusing and lots of details to know how to write it so it doesn't do useless re-renders. It takes time to read and practice all of that.


> No one ever got fired for choosing react, as some other commenter said.

That's supposed to be a pejorative, to describe how what management wants is rarely correlated with what's good or useful. 'Ignore shiny stuff' is the rallying cry when the shiny stuff is less performant and harder to use; as TFA illustrates, the thing about React is everything is more performant and easier to use than it. Where is the value in using React instead of Svelte for new development? If it is just that you already know it, what do you think of TFA's assertions about learnability?

The difference between React and Rails is, well, pretty much every mentioned negative attribute of React - Rails neither is terrible for performance, nor is full of hidden pitfalls, nor requires lots of boilerplate for simple actions, nor is incompatible with most Ruby libraries, etc.

I really think 'new stuff bad' rhetoric here is being divorced from every real reason usually backing it. 'React is good enough' is like someone saying 'MongoDB is good enough' - no it isn't, it was a huge step in the wrong direction and everything invented since it is moving towards more streamlined versions of the old ways of doing things. You explicitly reference the resurgence of old-school stuff, without noticing that it the thing it is specifically a rejection of is React.


> The difference between React and Rails is, well, pretty much every mentioned negative attribute of React - Rails neither is terrible for performance, nor is full of hidden pitfalls, nor requires lots of boilerplate for simple actions, nor is incompatible with most Ruby libraries, etc.

You cannot be serious. Every single one of these points is a criticism I've seen leveled at Rails (in many cases on this very website) at some point or another. Performance? People wouldn't shut up about how slow it was compared to traditional server-side languages/runtimes which could do multithreading, or (later on) event-loop-driven runtimes like Node.JS. Hidden pitfalls? I'd like you to meet my friend, Mr. N-Plus-One Query. Boilerplate? I suppose this is a fair point, but on the other hand there were tons of people complaining that there wasn't enough boilerplate- that it was too magical. And incompatibility? Can I point out the libraries that weren't just written specifically to be used within Rails, but actually depended on its heavily-customized initialization and environment preparation?


> People wouldn't shut up about how slow it was compared to traditional server-side languages/runtimes which could do multithreading

? There has never not been multithreading. And yes, people said it was slow, and they were wrong at the time, having confused single-threaded performance with scalability.

> I'd like you to meet my friend, Mr. N-Plus-One Query

This is a general problem in all ORMs, it's got nothing to do with Rails and the closest anyone has ever come to solving it is LINQ, which still isn't very close.

> Can I point out the libraries that weren't just written specifically to be used within Rails, but actually depended on its heavily-customized initialization and environment preparation?

You can, but it doesn't really have anything to do with the point: there are Rails libraries that don't work outside Rails, but Rails is not incompatible with wide swathes of non-Rails libraries. The problem with React is not the quantity of React-only packages, it is that many non-explicitly-React-only packages don't work.


To be fair, react was badly conceived and designed from the start and has aged poorly since.

I’m all for not moving from one hot tech of the day to the next hot tech of the days.

But let’s not stop on react.

> If you know JS/TS and are comfy in that

…there are better options than react.

> No one ever got fired for choosing react, as some other commenter said.

The the extent that’s true, I think it’s only in the sense that choosing react is more like a symptom of the shortcomings that get people fired.

Anyway, it’s the same urge to follow the heard that made react popular in the first place that will lead to its decline. New shiny things are calling. I hope we collectively choose better this time.


Well, I work for a Fortune 100 company and our standard is Vue, so, yes, using React could potentially get me fired ;-)


“React is antiquated…” “If you’re looking for a modern framework…”

I’ve also been hearing the same critique against Go basically since it came out. Meanwhile, the companies I’ve worked at continue to ship with these antiquated technologies and I’ve never once felt that those language or framework choices measurable slowed things down or otherwise hurt the team. Other factors (poor requirements, bad system design, bad management decisions) dominate the causes there. I’ve come around to the lackadaisical option that so long as the tech is compatible with the platform you target, and you can hire people to use it, it doesn’t much matter what is picked.


This blog post is heavy on opinions and short on practicality. I am not using a framework to achieve some platonic ideal of frontend development. I am using a framework to get work done in an ecosystem that makes it easier for me to get my work done and not have the bits rot.

I'm not going to migrate outside of React unless I were to get something out of it. I did not see anything someone would get from switching. I don't understand why people write these kinds of blog posts when they're so non-persuasive.


"But if you trade something off, make sure you get something in return." is the last sentence of Dan Abramov's famous "You Might Not Need Redux" article and the same sentiment is in your post (first sentence of second paragraph). It's good advice.


After having some React full time for over 2 years, the first time I used svelte I was at least 3x more productive than I was in react.

That is what I got out of it.


I like this article, but maybe because he drew the same conclusion as I did: Svelte all the way!

I always wonder if the authors of articles like these have an equivalent (or even adequate) amount of experience with all the many frameworks reviewed in the article. It's really hard to judge what they're good at if you haven't done at least a good-sized project with each one, and it's hard to imagine having occasion to do that. You definitely can't base it on what the framework homepage claims, or its own example projects.

I don't do front end development for money anymore, but when I did I always defended React against its critics. Then, when I stopped having to use it every day, I immediately realized I never wanted to touch it ever again. My defense of it was probably just Stockholm syndrome, looking back.


At some point I'm really going to try to build my next SaaS app with Svelte. I'll write an equally dismissive post as soon as I run into the first roadblock, which I guarantee won't take long. I need big, bad, and fully customizable frontend/backend frameworks for building some giant static websites!

Let's take a look at the frameworks available for this...

Gatsby > 50K stars Next.js > 110K stars (!) Remix > 24K stars (impressive, only 2 years old!)

and looks like Svelte has... ultimately... Sveltekit. Svelte has Sveltkit:

Sveltekit > 15K stars

React is great; not because of React itself but the massive ecosystem and number of frameworks behind it. There isn't a component or hook under the sun you can't find.

I grow weary of such posts, still waiting for an objective truth as to what really differentiates a frontend framework and makes it so much better than all others; still haven't seen it.


Meanwhile, I'm the guy in the corner happily writing native Web Components with (optionally ) lit-html as a renderer.

I get reactivity with class properties and a call to render().

It's so damned easy and straightforward, super fast light weight little components that know how to take care of themselves.

I stick with the light DOM and use a CSS design system that matches the project - bootstrap or whatever.

I have zero build time during development, and a quick "vite build" for deployment - just for easy packaging.

No framework churn.

No complex debugging. What you code is what you debug in chrome dev tools. No source maps.

No complicated state management or insanity like redux.

A new dev can be set up and productive in a day or two, and that includes learning how Web Components work.

I've been sitting in my lonely corner looking at the room full of unbelievably complex front end frameworks and scratching my head.

I just don't get it.


I generally don’t like react, and even when it came out I thought it was overly complicated. It’s also massively overused I think. Sometimes I see the popularity and think I’m taking crazy pills.

I’ve recently been doing a lot of react work. Even relatively simple changes on pages that are just pretty basic forms that probably shouldn’t have ever been a react page in the first place are huge changes. Even ignoring updates to the backend, adding a basic fields to a form with some validation can be 20+ files changed.

This week I updated a rails Erb file with jquery, wow it took 1/10th the time, file changes and energy. Really the golden age of web technology.

React probably has a place if you’re making a single page application at the scale of Facebook, but otherwise I don’t see it.


> Even ignoring updates to the backend, adding a basic fields to a form with some validation can be 20+ files changed.

That sounds a lot more like a problem with the project you're working on, than a React problem.


Performance one is interesting. This was news to me as I had always thought one of the driving factors for people to adopt React was performance.

So I naturally assumed that Angular was slower than React, but turns out it is not the case any more: https://krausest.github.io/js-framework-benchmark/2023/table.... (click on the "Which Frameworks" dropdown to filter on Angular + React)

I use Angular a lot in my day job. The learning curve is steep due to RxJS, but otherwise feels fairly sane as everything is included.


I’m old enough to remember pointing out all the ways that React sucked when it was new. It’s unsurprising and profoundly depressing that it’s losing its grip only after so much damage has been done.


"I disliked the popular thing before it was popular" is not an achievement to take pride in. Heck, most people who picked up React disliked it before using it.

The article states that there are better options now so continuing to use React is not the best choice. This was predicted by most advocates of React fairly early on. The mantra was always: React will be replaced by something better; for the time being that something is still React (i.e. present day React looks very different from the early class-based React).

At the time React started gaining momentum it was simply the best option for what it did. The biggest alternatives were AngularJS (which was known to be a dead end), Angular 2 (which was stuck in Google's cycle of "let's rewrite everything several times because we're not dogfooding this" -- remember that Angular 2 was initially based on `Object.observe`) or the old rusty toolbelt of jQuery, Backbone, Knockout and whatever else was still polluting globals at the time. React eliminated entire categories of bugs at the time and was the first major frontend framework (well, library) to also support server-side rendering.

I think good arguments can be made that e.g. lit-html or htmx is superior to JSX. But at the time those didn't exist and the reason people disliked JSX was that it was different and that it looked like something many had tried before (i.e. VDOMs and XML-ish template DSLs) and that had always ended up sucking. That criticism however came from a place of ignorance (literally "not understanding how it actually works and what it is") and prejudice (i.e. judging by superficial first impressions, not the actual implementation and semantics).

If you think React has uniquely done "so much damage", you either think frontend frameworks in general are inherently bad (which is an entirely valid opinion to have tho I wonder why you think seeking out articles about things you hate just to vent about them is a productive use of anyone's time) or you're being extremely disingenuous with regard to what came before React and what can be considered "React's fault".


I love your comment for the quote "old rusty toolbelt of jQuery, Backbone, Knockout and whatever else was still polluting globals at the time"! In all seriousness though, it might be hard to understand how React felt when it was young for those who missed it or have forgotten. Like with any new technology, those writing about it were involved in its development or early libraries based on React, which improved the signal to noise ratio of the ecosystem considerably. It is not only strictly React that was special, either - with the necessity to 'transpile' React's JSX to ordinary JavaScript came the excuse to use a proper build system, rather than just copying JQuery files into each other, which was the predominant distribution method at the time! Of course, eventually, the build systems themselves were overcomplicated and messy, but at that early stage things like SASS and JSX were very exotic and clever.


> Of course, eventually, the build systems themselves were overcomplicated and messy

True. On the other hand people are now rapidly waking up to the fact that the promised simplicity of having real module systems running in the browser (and ideally federated at that) introduces a ton of complexity (not to mention performance problems) compared to simply having a bundler even when you have to deal with code splitting.

It's also easy to miss how rapidly React influenced the space. Because React was so narrowly defined (i.e. it didn't bring any state management or styling - I remember it being called "just the V in MVC") a ton of other libraries sprung up around it and it even led to a short rise in popularity of otherwise very niche reactive functional programming DSLs and arguably helped sparking interest in reactive programming in general, such as RxJS (which has since seen and ebb and flow of popularity in Angular).


I’ll wait for the “Svelte kind of sucks, and plain old React is fine” article next year before making any decisions (well really I’m waiting for the ‘jquery can do what React and Svelte do believe it or not’ article still).

Where are my AI JS blog post generators at?

Unless … No can’t be … There’s no way these articles have been AI generated this whole time … right? RIGHT?


What was bad about React then is the same thing that’s bad about it today: despite the atomic unit of React being a “component”, the best practice was always to re-write your entire fronted in JavaScript, shipping a blank HTML page and forcing the end user to download a megabyte of JavaScript to make their computer write the HTML, for some reason.

And in order to get the “convenience” upgrade over jQuery+backbone or whatever, you had to abandon all existing standards and best practices, making any JavaScript you were using that was not in the style of React useless.

Web components that encapsulate state and interactivity, usable alongside a regular HTML page, were an emerging direction when React shipped and forced everyone to re-write ‘class=‘ to ‘className=‘. And being forced to re-write every app as an SPA was a dumb idea the day people started doing it, even in light of other available approaches.

You’re right that a lot of people hated React before they ever tried it, and they were right, even with the full knowledge of what it was replacing.


> Web components that encapsulate state and interactivity, usable alongside a regular HTML page, were an emerging direction

They weren't. By 2013 web components were still flailing around completely ignoring everyting that was happening in the world and coming up with an unusable and badly design API while crippling a bunch of other things in the process (like forcing C++-like OOP onto prototype-based Javascript)

> when React shipped and forced everyone to re-write ‘class=‘ to ‘className=‘.

React is basically just Javascript. What do you think className is? https://developer.mozilla.org/en-US/docs/Web/API/Element/cla...

> And being forced to re-write every app as an SPA was a dumb idea the day people started doing it, even in light of other available approaches.

What do you think web components are if not a way for people to dump a bunch of Javascript onto a page (and dozens of Javascript-only specs to accompany them)?


> What do you think web components are if not a way for people to dump a bunch of Javascript onto a page (and dozens of Javascript-only specs to accompany them)?

You can get most of what you need onto a web page with HTML. Some components need to be interactive. For that, you need JavaScript. The question is, do you:

1. Keep the rest of the HTML in place, and add JavaScript to that HTML for the interactivity you need (the web components approach)

Or,

2. Re-write the entire web page as a JavaScript “app”, including the parts that are just fine as static HTML, for the “convenience” of the pieces that need interactivity (the React approach)

Both involve “dumping JavaScript onto a page,” sure, but they are totally different approaches.

For a decade, the entire industry picked “2”, and now the internet is a bloated disaster.


> Keep the rest of the HTML in place, and add JavaScript to that HTML for the interactivity you need (the web components approach)

It's not the web components approach. Almost nothing about web components is about progressive enhancement.

> Re-write the entire web page as a JavaScript “app”, including the parts that are just fine as static HTML

That is literally what web components are. They can't even participate in forms without Javascript


You're describing AngularJS, not React. When React hit the scene there were services for "pre-rendering" your AngularJS app for SEO and crawlers. "Rehydration" for server-side rendering was one of the biggest selling points of React.

Heck, even literal Web Components were stuck in that direction. The big reveal of the Web Components implementation in Polymer involved a demo page that was literally an empty HTML page with a single <DemoApp /> custom element node and a massive JS runtime. And that was after React had become popular enough for Googlers to actively heckle React and other libraries on Twitter: #UseThePlatform.

React of course lapsed in server-side rendering eventually because it was not a priority to Facebook and therefore only an afterthought. Arguably the killing blow was Create React App not giving any thought to it at all. But one of the most popular React frameworks is Next, which is now more than 6 years old and is best known for being good at SSR.

The class vs className thing is a silly argument and enough articles have been writing about this that I don't need to reiterate the full argument here but basically the DOM API calls it className (because it wanted to avoid reserved keywords in property names) and most libraries have special-cased "class" to be an alias for "className" or even go out of their way to prevent you from using the actual property name. React actually does less here, not more. The rendered DOM itself (i.e. the HTML sent over the wire in SSR or what you see in your DOM explorer) is no different whether you use JSX where it's called className or a template language that translates "class" to "className" for you.


> My sense is: we’re beginning to near another leap

My sense is that there won't be another leap in the conventional sense of a new dominant frontend paradigm that will be so "optimal" that it can be all things to all people. jquery was at some point used like for 98% of websites. This historical precedent created the false expectation that the web is a single something. But this is no longer true true. The arrangement of browser/clients - servers is so flexible that very many patterns are desirable and viable even though not yet fully crystallized.

More likely the next "web" will bifurcate (or maybe trifurcate). Its not yet obvious what the different web "subtypes" will look like. There is now a visible revisiting of paths not followed during the breathless SPA years (e.g. minimalistic reactive frontends (htmx, alpine.js) in combination with popular backends (phoenix, laravel, django). There are also new horizons with wasm (e.g. running the entire python data science stack in the browser). And worth remembering that knowledge management challenges that were once thought resolvable through the "semantic web" are basically still unsolved. At some point an LLM will scaffold an SPA/CRUD/sort-of-REST thingy in its entirety and we will need to move on to some truly unsolved problems.

Thus, a lot of this heated debate and people talking past each other is, imho, just a waste of time and it won't be relevant in the big scheme of things.


Honestly my issue with react and the whole ecosystem(including nextjs) is maintenance. I just know that in 3-5 years they will reinvent everything yet again and I'll need to port stuff again. This is unheard of in stacks like Django. I just want things to be stable and work man.


Web dev here working with React for ~4 years now. I really don't enjoy it as much as I used to. It has made me dislike JavaScript in general, and I often find myself wishing things were simpler and more performant. I can't emphasize how relatable this part is:

> We shouldn’t need to do that—especially for a framework that so often claims it’s “just JavaScript.” If it’s just JavaScript, then it should just work with anything that’s actually just JavaScript.

And this:

> I have a confession to make: I’m still not exactly sure what the difference between useMemo and useCallback is—or when you should and shouldn’t use them—even though I literally read multiple articles on that exact topic earlier today. (No joke.) > > I have a second confession: it’s still not intuitive to me what should and shouldn’t go into the useEffect dependency array, or why. I feel like every time I write a useEffect call, I spend like 15 minutes refactoring my code to be in a shape the linter likes, even when I’m 99% certain it’s actually fine and it’s not going to suck my app into an infinite abyss.


I don’t care that React isn’t new or innovative anymore, that’s a good thing in my book. Give me old and boring any day.


I don’t know if you actually read the article or not but just to be clear that was not the argument that was made.

It’s not just “not new” it’s considered to be actively worse than all of its peers in terms of things like performance and complexity, it’s actively a very questionable choice in a greenfield project in 2023.


I did, and the fixation on React’s age struck me. Was it the core premise? No. Was it a central theme? Yes.


I agree with you, there was definitely a fixation. The implication is that React doesn't do things the new and better way just because it's old, rather than a deliberate decision.

Goes back to writing SQL


No, the core theme was technical debt. Technical debt happens to be (typically) a function of time.


I was pretty late to switch from jquery to react- I didn’t switch over until after react hooks were released. The reason is simply that jquery works great and the issues with scalability can be solved with proper design. Of course once react hooks came out it was clearly superior to me than jquery and was well worth the switch.

When I’m developing an application, I could not care less about what tech it’s built on. I’d much rather just pick something old and familiar that’s stable, has a huge ecosystem, and has tons of common issues answered on places like stack overflow.

These flavor of the week types of posts are always worth a read because it’s possible that something else may supersede react eventually. But proper understanding of the render cycle plus use of the react debugging profiler has been enough in the apps I’ve worked on to make them lightning fast.

Oh and typescript is a mistake.


Here is my take on this, very subjective and also very biased as I worked mostly as backend dev or Rails dev. I say this with a focus on the long term maintainability:

In general dont start your web app as a SPA.

Probably (99% of cases) your web app does not need to be fully SPA. If you need live data/reactivity sprinkle part of SSR pages with whatever FE framework you feel is good.

HTML and Vanilla JS are very maintainable over long term. So is being able to share a web URL and see the exact information without doing anything extra to make it work.

Try to resist the urge to use a fancy framework as much as possible. JS + HTML will go a long way.

Push back to designers asking you to do things that needs you to architect a full SPA. Most of the times the users dont want that. Ask what is the actual need that should be solved.

As we are on this subject: please dont start with infinite scrolling. It adds do many case to be handled.


I see the article as myopic in that it is mainly about React-like frameworks that have improved on React as opposed to other ways to develop applications.

My RSS reader YOShInOn is mainly SSR with some HTMX and little dollops of “plain ordinary Javascript”. For instance there is a test file that only takes 80 characters and there is just an event handler that counts the characters in the field and changes the UI accordingly. Granted there is the complexity of “first render” vs “update render” and I’m addressing that with rendering the count and disabled button status in the SSR and the event handler but the event handler could do the same work in the onload handler if necessary.

It’s how to do stuff with plain ordinary Javascript that’s been forgotten.


If someone is trying to get a job, would React be a good option? I'm planning to shift to some role where I program, right now I'm in security, and web browser and JavaScript stuff seems the most interesting to me, I have just started recently on this journey.

I am creating a project using React + Vite which could have very well been created in vanilla JS, but just to get familiar with React and also to show some proof to prospective employers. So just wanted some advice on whether React is the way to go, or is Vue/Svelte where the industry is heading towards? Also any other tips on what you would be looking for when hiring a dev would be very helpful. Thanks.


I'd say it's a good thing to know the approaches of different frameworks, but solid foundations are the most important factor in successful development. Try to decouple your application logic from your view layer to clearly delineate between the React/UI parts and the rest. This would also make it easy to later build a Vanilla version of the frontend without rebuilding the whole code.


If you're just starting with programming in general, then I would highly recommend exploring React, as it is a very intuitive kind of way to learn Functional Programming as a paradigm. Sprinkle those map, reduce and filter functions around, avoid Redux for as long as possible, and you get a pretty good idea of what immutable state does to improve code quality. Haskell and Lisp won't seem so exotic after that, so you'll be able to appreciate the more subtle advantages of FP later.


I hate to say this, but to me, it's quite clear that the author doesn't understand what is React much. And for some reason, it is very common to understand it this way, like it is some kind of a great web framework that defines how we make web apps. I believe it is completely wrong to look at it this way. React is a LIBRARY, to create USER INTERFACES. If you want to apply it to the web - you must use react-dom. You can also write native user interfaces which are not web-related at all. You can do native desktop apps with QT interface, or mobile app using Swift UI kit or Android native libraries.

You can write interfaces on the server, wrap them in HTML documents and send them to the user performing SERVER-SIDE rendering. But not any of this directly entitles React.js as a web framework, and it is utterly incorrect to start comparing it perpetually with what it was compared to.

React was a true revolution in the functional user interface development area. The concept of side-effects, hooks, and reactive renderer comes from the functional paradigm which is not so easy to grasp. This fact alone makes all these articles to come.

The author is true to his "it’s still not intuitive to me what" and "I’m still not exactly sure what the difference between" lines throughout the whole article, but with great confidence he compares React with jQuery and Vue. I would say it is still not intuitive to him what is React in its core, and how different it is from the web frameworks he is trying to compare it to.

React is a functional Javascript library to craft anything related to User Interface. It is incorrect to label it a Web framework exclusively and keep comparing it with others because there are 10 different frameworks based on React, but just a single React there are.

And the React is much more of a bundle of functional concepts than a full-fledged framework for doing anything. You can easily shoot yourself in the foot if you take it wrongly, as it doesn't provide you with clear instructions for making things work. It leaves you on your own with hooks until you understand 6 of them are all you need to create the interface in it's gorgeous simplicity. At some point, you understand that if your hooks are complicated and you cannot grasp your effects - then it is your interface that is complicated and your thoughts themselves went astray to entangle this monster.


When I was younger the most popular music was pop. I loved rock music. Then, rock music was the new hot shit, and people started writing walls of text to justify it. Now nobody cares about rock music, most people around me love "techno" music.

The moral of the story is, what ever cool now changes fast, and it shouldn't matter. Do what you love and don't preach because not like any genre of music, crusades are not cool for like 1000 years now.


Not a good analogy. Good music is timeless. People will be listening to Mozart and The Beatles in 1000 years. Most if not all software frameworks will, for all practical purposes, cease to exist in just a few years and be of no interest except to software historians.


I got into React initially because I could write React components and put them into my HTML where a dynamic component was needed. This was a stark contrast to stuff like Angular or Ember at the time, which would force me to write the whole page in their framework, abandoning basic HTML which worked a lot better for much of the page. Put another way, when I got into React, it was a good tool for writing multi-page applications with some interactivity on each page, when all the other tools were forcing you into single-page applications.

React is still a good tool for writing MPAs, if you can get your team to stick to it. But unfortunately, if you aren't careful, React has become an infectious disease and slowly eats your whole frontend, even where it's not necessary and in fact, counterproductive. Pages which initially had a component or two, slowly are completely rendered in React, and when this happens to enough pages, someone starts wondering why your site isn't an SPA. It's hard to steer teams away from this, because the short-term benefits always seem tantalizing, and few people stay at jobs long enough these days to grok the long-term downsides.

I've started to think having a JS build step (beyond bundling/minification) at all is the original sin here, and lately I've been doing a lot of my work with just vanilla JS and web components. Web components have their downsides which I've criticized elsewhere, but at least they aren't all-consuming. I've also been playing around with a few lightweight frameworks which don't require a build step like alpine.js and lit.js, but haven't committed to one for a production project yet. The biggest downside to this is that there aren't good tools for automated testing without a build step (that I know of! If you have some please mention them).


    "there aren't good tools for automated testing without a build step"
For our vanilla JS we use browser-based tests which we can check in any browser anywhere any time, and which can also be automated and measured with a headless browser from the command line. And we have also used Node and had even more luck with Deno for testing individual functions and libraries which may get used on the frontend! Hope that helps!


> React is still a good tool for writing MPAs, if you can get your team to stick to it. But unfortunately, if you aren't careful, React has become an infectious disease and slowly eats your whole frontend, even where it's not necessary and in fact, counterproductive. Pages which initially had a component or two, slowly are completely rendered in React, and when this happens to enough pages, someone starts wondering why your site isn't an SPA.

This started happening to me this year. And all the other senior devs who know better happen to be gone from this project, so I'm alone having to convince these junior engineers (working on a very large non-JS-backend web application mostly with content pages!) that SPAs are not the ultimate solution to all. It's so frustrating.


> Developer experience (DX) shouldn’t ever supersede user experience (UX).

That's a business decision, and not a given


Why would a business want to prioritize the experience of its developers over its users?


Iteration speeds, I could see myself using a slower framework to ship faster.

See usage of React Native for example, it certainly produces apps worse than native ones, however many businesses still choose to work with it because you can improve the developer experience and ship faster.


Because users do not know that there's some hypothetical "better" experience they could have had and do not care, unless your service/tool/whatever is not functioning correctly. Prioritizing your employees' enjoyment and experience to deliver more, faster, and consistently, is in all likelihood a better decision than prioritizing some subjective improvement to user experience.

Of course there are exceptions. But it's definitely a hot take to say you should never prioritize DX over UX.


> Because users do not know that there's some hypothetical "better" experience they could have had and do not care, unless your service/tool/whatever is not functioning correctly.

If your business competitors prioritise UX over DX, your users will soon know. And then they won't be your users any more.


Many users will prioritize the features they need, shipped promptly, and without bugs, over a nicer UI.


This is one of those "false delima" logical fallacies. The idea that you have to choose between a "nicer UI" and "many features, no bugs, shipped promptly".

All those are important, and given a talented team, there is absolutely no reason why you cannot have good UX, lots of features, few bugs shipped on time.


Yes, and going back to the original point, a company’s posture on this is entirely a business decision and not a “UX MUST BEAT DX” truth


Going back to the original point, "the features they need, shipped promptly, and without bugs" you speak of is actually part of the UX (user experience)!

Maybe you are mixing up the UI design with the UX? In any case, the original point is just highlighting the importance of UX, without giving any solid examples of DX.


For example if a better DX leads to faster development or less bugs. Especially when the difference between the delivered UX will likely be performance related rather than a functional/visual difference. Nearly all technology choices make trade-offs like this.


Developers building stuff faster leads to a better user experience.


Developers building stuff faster leads to either building more stuff or working yourself out of a job. There's absolutely no guarantee that shipping faster leads to better UX.

I've worked in quite a few companies that were always pushing to ship faster and we're okay with the trade offs in missing tests and worse UX. The talk was always that we'd ship fast now so we can step back and clean up later but that's extremely rare in my experience.


So there is someone left to build your business


> If you’re building using other modern tools and frameworks, it’s far more likely that the vanilla JavaScript packages available will work just fine for you—and there are thousands of them

And all of them are available to you if you use React, too.

I stopped reading after a while becauze this post shows complete ignorance that React is not a framework. It's just a tiny general lib focused on rendering things reactively. It doesn't care if it's used in web or not. The core package doesn't even know about DOM unlike eg. Preact that is specifically limited to web.

PS. If you are so knowledgeable about frontend, it's even more glaring that your website hijacks scrolling. Why?


> I’m still not exactly sure what the difference between useMemo and useCallback is

    const useCallback = (fn, deps) => useMemo(() => fn, deps);
That's it. That's all it is. `useCallback` is a shorthand for `useMemo`, when you want to memo a function definition.

Example:

    const handleButtonClick = useCallback((event) => {
      event.preventDefault();
      window.alert(`Hello, ${name}!`)
    }, [name])
is just shorthand for

    const handleButtonClick = useMemo(() => (event) => {
      event.preventDefault();
      window.alert(`Hello, ${name}!`)
    }, [name])


correct, but with useCallback you don't take an additional perf hit for redefining the inner function on every render.

useCallback is for callbacks, useMemo is for memoized data.


Personally I find it weird that React was originally invested enough in a DSL to define a syntax for createElement(), but then didn't follow through when extending the DSL could have made a huge difference for hooks usability.


Here I am wondering why .value on an input[type=number] in 2023 returns a string.


IMO TypeScript, Next.js is massive benefits. Vue, Svelte directive syntax doesn't type-check compile-time. For example,

<ul> <li v-for="todo in todos" :key="todo.id"> {{ todo.text }} </li> </ul>

Many developer miss type a `todo.text` as `todo.test`. React detect error in compile-time. That is enough to reason of selection. And React slower than Vue, Svelte, but Next.js is faster than other framework many situation.


Main thing to distinguish: small team / big team and or small app / huge app.

For small teams frameworks like react & others are (sometimes, not always) overbloated and overkill.

If you want to use finished components without reinventing the wheel, you stay better sometimes with big frameworks like react or vue, ... with all pros and cons.

Sure, it would be nice to use components and tools, that are not framework agnostic, but these are rare or you have to use many, that is a problem for huge teams (fragmentation).


I think one of the main reason to pick React is because, even if it's slower than you'd like, it evolves and adapt, so you can hope you're not going to have to rewrite your entire app with a different library/framework in a year or two.

I've worked on a rewrite of an old AngularJS and it felt like such a waste of time. It didn't matter what the new target of the rewrite was, the fact that we had to was very painful.


Lolz, by the time you investigate React, i already produced tons of production React applications to the customers.

So, who cares about that "Web component is awesome" ?

Just use React and grab the money.

React "simulated the DOM" into minimal surface API for busy devs to use and be productive. That's the whole point.

Seriously, i don't trust the DOM at all. They're not 1 standard, they behave differently on different browsers.

React is 1 standard to me.


Can we bring back knockoutjs then?


Usually mediocrity becomes popular. If you want the best you have to look into niches usually crowded with great above average people. Be it music or software.


So in mid-2023, if not React, what would HN choose?


If you don't already have a backend framework, I see no reason to disagree with TFA's recommendation of Svelte/SvelteKit[0]. It's simple, there's no runtime framework magic to debug, everything works exactly like you assume it does, it's pretty darn fast, and the DSL syntax isn't easily confused for the HTML it's templating (looking at you, Vue).

If you do have a backend framework, then having the backend drive the dynamic updating is a pretty great way to go, so HTMX[1] is the least obtuse way of putting the most power in the hands of the backend. Really makes 'a light sprinkling of JS for interactivity' closer to reality than vanilla JS allows, without adding cognitive overhead.

[0]: https://svelte.dev/ [1]: https://htmx.org/


I'm curious if anyone else is advocating for HTMX as a mechanism to simplify bloated front end code bases


I’ve been using it to great effect for the last year or so. It really is a breath of fresh air. In my case, I’m using a Django backend, but there are lots of successful folks using other backend stacks as well so choose what you know best.

The book is a really quick and easy read. It’s pretty eye opening how productive, and effective, htmx can be with so little magic.

https://hypermedia.systems/


for a small project i would choose vanilla. vanilla is good enough today, tons of features supported on all the browsers, etc etc

but for a large project still react.


ehhhh. I'd think maybe lit-element if you're going to be leaning on Web Components to smooth some of the edges of "vanilla".


Mithril.js, for both work and personal projects. There hasn't been a major release since I started using it ~4 years ago, which is lovely in the otherwise churning sea of frontend development.


Some niche ass framework with little to no eco-system. Or plain javascript by people thinking the web is used to display a single page worth of content.


If I had to choose a frontend framework right now, I'd probably go with Svelte. That was my opinion before I read this article, and this article confirms it.


Solid as a React alternative, and Astro as a Next.js alternative. SolidStart is pretty cool, but I like the flexibility of Astro


If it's an internal app, server rendered HTML and maybe a JS library to render charts. Django or Rails both fit the bill.


Genuine question from someone who's only worked in CSS-in-JS or SCSS preprocessors for the past ten years -- what would you choose for styling?


CSS? In all seriousness though Tailwind or SCSS.


Plain old CSS.


I'm seriously looking into Preact[1] as a library which is philosophically aligned with React, fits in nicely with the rest of the JavaScript ecosystem, but has a very small footprint for what it provides (3KiB).

[1]: https://preactjs.com/


Maybe it's changed with more recent version but that small footprint was a trap for us. We picked it for that, and ran into weird edge cases / bugs in preact projects using third party libs that didn't occur with react.


Thanks for the warning, although in my case I'm not planning to use any third-party libraries except maybe some fundamental ones like Hammer. :)


Lit.dev has been nothing but great for me. Strong recommendation.


I used on a project 6~mo ago and struggled quite a bit to get some basic things to work. Iirc it was related to event handling on nested elements in a component. I believe I felt quite forced to make lots of very tiny components, which made the "try it out" phase quite frustrating.

Do you have any recommended learning resources on building with Lit?


Ehhh. React of course! Well, for me anyway.


PHP with server side rendered templates.


At work, whatever the FE team decides upon, React/Nextjs, Angular and Vue are the only relevant ones.

Privately, I always go with vanilajs.


Not sure, the typical HN user has JS disabled.


i like aurelia because it has a minimal footprint on my code.

i set up routing with the views available and i write a class for each view. there is practically no boilderplate code. (eg what is $scope in angular is simply the class object itself in aurelia)

any class level function and variable is automatically made accessible from the html template. classes and templates are linked by sharing the same name: welcome.html, welcome.js, export class Welcome ...

while in angular you have to declare everything explicitly, aurelia mostly just figures it out by itself.


I've never used React (not really a front-end dev), but I feel similarly about the Spring "framework". It seems to me that people who are tied to it have never really had the opportunity to do proper object-oriented coding and design and are thus stuck in the fundamentally procedural mindset that Spring forces you into.


Do you have any example ? What you said much like NestJS to me.


Good article, but I'm going to hard disagree on two-way data-binding. At scale, you're asking for a very bad time.


>Hooks are undeniably great

I recall seeing far more negative sentiment than positive over the years re. hooks. Maybe it's just me.


they're a mess. what the react developers really wanted is a DSL[0], but they couldn't sell that as well so they hacked hooks into JS.

The whole things about "rules of hooks" should tip people off that it's sketchy. I mean, have you ever actually thought about how:

    function Component() {
        const [state, setState] = useState(1);

        return <>{state}</>
    }
actually works? How does `useState` know what bit of state to grab? (it's a global store identified by the function you're in, and an index. it's why you can't change the order of hooks nor call them conditionally).

Hooks are literally javascript in the sense that they're functions you can call in javascript, but they don't operate under any of the rules people actually think of when they write javascript. If for any `function x() {}`, `if (condition) { x() }` was a fatal error, people would consider that terrible API design and the function shouldn't need to care whether it's called conditionally.

Sure, react hooks 'compose' better than class components, but they also don't compose *at all* with anyones mental model of how JS works. What they needed was different syntax or a DSL in general (what svelte does is a lot more understandable, imo).

[0]: jsx is a DSL but it's merely one bit of syntax sugar. they needed a hell of a lot more.


I still don't understand what the problem is with class components. They made sense. Now I'm suddenly relying on the behind-the-scenes magic of useState and useEffect.

useEffect in particular really messes up my understanding of the flow. Lots of bits of code that may or may not be executed based on the dependency array, and that means my component function is going to be executed several times, each time just to execute another useEffect. It works, but it's not a programming model I like.


Class components don't scale or compose well. You have a fixed number of lifecycle methods, and each new behavior you add to your component has to be split up across those methods and mixed in with everything else. This means that your components are going to get much harder to debug and maintain as they get larger, and it's very difficult to split out common behavior in a form that's easy to mix in to existing components. That's the advantage of hooks: each hook can be defined by a single function that manages its entire lifecycle in isolation, and can be dropped into any component with a single line.

> that means my component function is going to be executed several times

Who cares? That shouldn't be your concern. All you should think is "this effect will get called every time these values change. Am I okay with that?" React will handle running your component function consistently with the right state, you just have to worry about whether your component is rendering the right thing given that state, and running the right effects. React handles correctness. You don't have to remember "oh whenever I update this state, I have to run this other function to make sure everything is in sync" as with class-based components. Because invariably, another engineer will come along, make some changes, and forget to call that function. Now you have a really tricky bug to find that depends on internal state.

This is why hooks have caught on: you can truly write pure declarative components (most of the time) and not worry about execution order or dependencies at all. The tradeoff is that you have to think very...reactively. It's definitely a different mindset, but it means that there's a whole class of bugs you never have to think about because React handles it.


shouldComponentUpdate() also doesn't exist in the function-based components. Instead there's a few different hacks to get the same effect.


useState is basically a local [observable] variable slot in a closure, but defined at runtime in React. That’s why it cannot be conditional. React is an ugly attempt to pretend you’re in a powerful functional language while it’s javascript and you run its core manually and follow the rules for “…reasons”.


Hooks are like cooking with really sharp knives - excellent when treated with care and healthy respect for the dangers, but will/can cut you up really badly in a moment of absent-mindedness.


Yes, I've seen this firsthand. Side effects can put you in a huge mess, i.e. an effect that triggers another effect, that triggers another effect... and it can be hard to follow that logic if you're unfamiliar with the codebase. I do think it causes confusion compared to the 'setState' class-based components because I can follow all of the setState calls very easily.


That's a great analogy and actually gets to my main beef with the whole "I can ship faster with react" argument.

When using a sharp knife it's even more important to stick to the principle that slow is steady and steady is fast. It's the same thing with react, and really any of these frontend frameworks that keep piling on complexity. Sure you can ship features fast and if it's throwaway code the great, but if you ever want to reuse or grow it that quick code is a nightmare of tech debt.


The amount of negative vs positive sentiment you see can be misleading. My sense is that a significant minority just don’t get on with them and make a lot of noise about them because the ecosystem sucks now if you don’t like hooks. While that the majority think hooks are somewhere between useful and great, and don’t really comment much on them.


Indeed, it's selection bias. You're only seeing/hearing those who talk about it, and those who talk the most about it are (probably) from opposing ends of the "positive/negative appreciation of it" scale.


Vue's equivalent (Composition API) handled the hooks concept so much better IMO, by just eliminating 99.95% of the footguns present with Hooks. Obviously Evan had the benefit of hindsight to work with, but still, why people would opt to torture themselves with React when Vue exists will always be an enigma for me


I think it is more negative towards centralized store and using it for every possible project being ridiculous since hype died down recently.


Maybe not hooks in general, but useEffect hooks seem to get hate these days. Even though they were the recommended way just about a year ago?


> Hooks are an excellent pattern [but] every other framework does hooks better

Have to agree here, game-changer when they came out but now every repo I touch has 100 custom hooks. Junior devs don't even understand why they're called "hooks".

Compare the old docs about useEffect() to the new, it's widely abused.


the bottom section talks about "web component frameworks", i.e., frameworks that use javascript's native web components rather than creating their own special component format.

the article says:

> In my opinion, most projects still benefit from using a frontend framework over pure web components—or, at the very least, both together. Maybe that will change in the future, but for now, I think the tradeoffs still tilt away from a pure web component approach in most cases.

but doesn't provide any real argument to justify that opinion.

why would anyone want to subject themselves to framework lock-in when you can have components that are portable across frameworks? what are the arguments against?

genuine question -- i've used Vue and i've used Lit, and didn't see obvious limitations in the latter, but i've also never used either for any large project.


> why would anyone want to subject themselves to framework lock-in when you can have components that are portable across frameworks? what are the arguments against?

https://twitter.com/Rich_Harris/status/1198332398561353728

None of these are solved, or will be adequately solved in a forseeable future.

Some of these will be addressed by ~20 new JS-only specs in the various states of "not started" https://w3c.github.io/webcomponents-cg/2022.html

Literally none of the major (or even emergent) frameworks have these issues, or a chance of running into these issues.


thank you; these are good, specific examples.

#2: maybe i'm misunderstanding, but i think frameworks can implement SSR on top of vanilla components, for instance in Lit: https://lit.dev/docs/ssr/overview/


I've written a more extended response in a different thread here: https://news.ycombinator.com/item?id=37158524


If you need framework-specific solutions to do SSR for web components... they are no better than existing solutions without them.

Lit solution also lists a lot of caveats including things like "only Lit elements using Shadow DOM can be SSR'ed" and "element registry needs to be solve for interop with other custom elements" (that is, there's an issue on the standards level)


The article fails to mention the killer feature which has contributed to React's dominance - React Native.


One thing that became apparent to me after evaluating amount of complexity/work/team needed to maintain React projects compared even to Vue (but the difference is even more striking with more backend backed projects) is that - it is very often way cheaper to not to use React.


What size of project and what pain points made it "expensive" in your opinion?

Because, admittedly I only have a view of react of having used it to enhance a server rendered (PHP/twig) page with rich interactions (Making a UI widget/gizmo that lets the user manipulate the data easily before form submission etc).

On the one "full app" that's an offline React PWA, our only real pain point has been the report section, because the report structure is dynamic (controlled by a config from the server) and recursive which made ensuring the correct components are shown and having performant state management challenging.


I appreciate articles like these. While I do think theres a lot of churn in frontend JS, that's how we test ideas and make progress.

Of all the new ideas, I'm most excited about Electric Clojure. The ability to strongly compose across frontend and backend feels very powerful.


"There was a time, several years ago, when React was pretty much the only game in town when it came to server-rendered content (mainly via Next JS). People were rightly excited for the idea that React could be rendered on a server as HTML"

Hi - year 2000 calling...


React might be the single worst thing to happen to the web. Not because of the library itself, but what it spawned.. the way people write it.. the style of coding that surrounds it. It was a sad time when it rose to popularity. :(


Good article! Sounds like he’s basically arguing for continuing education for developers. Developers like other professionals should be mindful of progress in their field and adopt new tools as improvements arise.


I just don't want to learn another framework unless I know its going to matter.

"Learning a framework" doesn't mean creating a todo app over a week or two. It takes years to really know one. I don't have that time or energy.


I enjoyed writing React functional components a lot. But the leaky abstractions spoiled all the fun. This is why I like Solid. Never think about what gets why when rerendered, if it's necessary or not, using memo or not, ...


Tell me a single other framework where the same high level components work at the same time on both web and natively on the two mobile platforms. React Native is a huge part of why I'm always going with react


One thing I'm coming to realize after decades or being an engineer, architect, and now manager/team lead who is still creating code.

In the thick of substantial engineering projects, when all your initial plans and architecture have not survived contact with the enemy [1], you realize that any robust, maintainable, really successful piece of software only gets that way by going against the zeitgeist of frameworks, patterns, tools, and architectures. Not only must you use boring tech, you must do some thing directly contrary to "best practice".

There are many examples to support my point: CloudFlare's "weird" internal architecture which is heavily DB-based (making heavy use of stored programs and the like) [0], to Google's use of all kinds of internal innovations: Protobuf, MapReduce, Closure compiler, etc., and more I can't think of now. It's a testament to the somewhat sad state of software as an engineering discipline that so much of our real world engineering has to go against state of the art.

For example, just the other day I came to the conclusion that all JS bundlers are "bad", unable to meet my need to reliability, efficiency, and speed. And my needs are not even at the edge. So, I am not exploring crafting complex front-ends without bundlers at all. The shiny things that are constantly being pumped are not subject to, or the result of, a long period of real world use. The examples used to illustrate most are toy examples with virtually no relationship to what the experience of using them in a substantial project would be.

And, yes, I kind of hate how React has taken over everything, although I like JSX, the idea of UI as a function of state, etc. So I had to write my own UI library to get away from React the library, while still being able to write UIs in a react-like way. I hate other heavy UI frameworks even more.

The way forward is to get back to basics. Learn from various libraries and frameworks, but do not import a million dependencies into your project, and do not depend on too many tools. I believe each piece of software must be crafted almost from scratch [2], embedding modern but tested architectural approaches, in an almost monolithic way.

[0] https://news.ycombinator.com/item?id=22883548

[1] The enemy here include complexity, performance issues, shifting requirements, time and cost estimation, and similar things that bedevil substantial software projects.

[2] Not totally from scratch, otherwise you would have to boostrap an OS, compiler, and stuff. But the black boxes you rely should be _very_ robust, and easy to reason about. No one gets confused about, or has to debug, what is happening when they save a file. You trust what the OS is doing , although it can be quite complex behind the scenes.


It's worth thinking about where "best practice" and "state of the art" come from. At worst, it's a business that's trying to shape these things to sell their product.

In a more middle case, it's just people explaining what they did when they faced a particular problem, and how well their solutions worked. There's a cynical version of this too, where people are more focused on their employer-brand or personal-brand than being helpful.

Not to downplay the actually helpful instances of thought leadership! I'm just observing that there isn't always an easy way to tell these things apart, or to boost the helpful ones.


React may have aged, but my codebases havent - all the old stuff is on crufty ang1, 2, vue1 2 - it's all deprecated. Only the react codebases are up to date.


What I love about this article is how little I care

When I’m being excluded from job descriptions because I have react on my resume I’ll revisit this article


React has brought a stability to the front-end scene that everyone was waiting for. Now that we have it, we're complaining again.


I had flashbacks to Backbone, Angular, Ember, Angular 2, and Vue when the author said React was early to the scene


I thought this was another "The things you forgot because of using the frameworks all the time" title.

It wasn't.


it is still hard to pick an obvious alternative though,based on maturity, ecosystem, tutorials, libraries,etc. so far I will have to stick with react for my client side rendering projects(no SSR at all)


I want to add more on the “other staff you should try” list:

- phoenix liveview / ts-liveview / hotwire

- htmx

- clojure

- cycle.js

- dom-proxy

- data-template


Hopefully LLMs will take us back to the basics


Glad to see these ideas being shared more broadly. I've had enough of React. I lost my last job because of it and all associated technical debt. The company I worked for (a startup) turned into a kind of Darwinian Squid Game where those employees who were able to keep adding on top of the mess of tech debt at a fast rate were promoted and those who did not were let go. It became an absolute brainf**. Also, I had lost all motivation because there was no real engineering left to do; all the work was related to debugging React-specific gotchas/issues which I hate doing.

React creates layer upon layer of unnecessary, opaque abstractions which make it harder to debug complex front ends and it encourages poor engineering practices. For example, I've seen a lot of cases of junior developers dump setInterval() calls all over the place into the code inside useEffect and not cleaning up afterwards... Causing memory leaks. But these devs can work so fast using React (to get features out in production quickly) that managers just love them and it's difficult to convey to them that this is in fact a short-term approach and it will come back to bite them in the long term. The app at that startup had such awful memory leaks that my new computer would freeze a few times a day.

I feel like the new generation of devs got used to working with these abstractions and by some measures they seem highly competent, yet it feels like they're missing some critical knowledge; like they don't understand what's happening under the hood. Sad because there's actually a lot less happening under the hood than there is happening above it! You can solve many problems while staying closer to native browser features without all this complexity.


You can say this about any technology though. Whenever you prioritise delivering features and are ambivalent about tech debt then of course the quality of the code base will suffer.

There is nothing inherent to React that makes it significantly worse than the many other Javascript frameworks out there. At least it has the benefit of having ongoing support by a major vendor with a record of long term support for open source projects. That's not something that is all that common in the Javascript ecosystem.


> There is nothing inherent to React that makes it significantly worse than the many other Javascript frameworks out there.

There definitely are plenty of things which are an order of magnitude harder in react than any other framework.

One flow data is an example, having to install deps for everything from state management to css is another.

All the choices compounds and make complicated projects even more complicated, increasing tech debt.

Don't get me wrong: Angular (and for sure other frameworks I can't think of) had the same problem; many other frameworks do not.

These days I'm very happily developing against Solid Start with not a single issue I can't think of and a syntax which is very close to React.


"There is nothing inherent to React that makes it significantly worse than the many other Javascript frameworks out there."

That is exactly the kind of conclusions that come from not understanding what runs under the hood.


I'm certain that this would have happened with any other framework mentioned as well and pointing towards React being the issue is just searching for a scapegoat where there is none


The problem starts in html, css, javascript and the browser as a development platform. React tries to patch over those issues, and creates some new issues.

People claim other frameworks solve the same issues without introducing any significant new problems. I'll remain skeptic until I see a couple of huge full-functionality apps in those frameworks that manage to keep a clean codebase and good performance.

I've seen too many times people "solving" frontend development, most of the time that solution just amounts to documents linked to each other, and avoiding complex forms and interactivity, but if you just do linked documents, frontend development was solved in the 90s, and you don't need javascript at all.


I agree with most of it, but I still had to chuckle at the "don't understand what's happening under the hood" part. The browser and JavaScript are themselves very high level, so it's funny how e.g. not using React would make you understand more what's going on under the hood. It's a pretty deep hood.


A lot of the React fanatics are in denial about this. But, I've seen some absolute messes. Does anyone remember InVision? You probably have forgotten about them because Figma and other design tools ate their lunch, but part of their failure and delay in InVision Studio being released was in part because of React. I know other companies have encountered limitations with React and had to hack around them, most notably Atlassian who had to break their app up into apps (essentially parts of the app were smaller apps) because they wanted to use state management for everything and the memory problems were astronomical.

React got popular because at the time, Angular.js was the framework of choice and we can all agree Angular had some serious problems like the digest cycle and performance issues working with large collections. React in comparison to Angular was a breath of fresh air, but in 2023 there are far better choices now than React.

The thing is, React started out as just a view library and the community are mostly to blame for how terrible it has become. How many state management libraries have there been? How many router packages? Devs think they want a library, they actually want a framework. It's why the most popular uses of React are not vanilla React, they're frameworks like Next.js. Also, when you compare the performance of React to other libraries and frameworks, you realise it's one of the worse performing options. It's slow. The whole entire notion of Virtual DOM was groundbreaking in 2013, but in 2023, reactive binding approaches like those taken in Aurelia and Svelte are far superior and better performing. Virtual DOM is overhead.

Has anyone ever seen a large-scale React project that is just using vanilla React? I've seen a few large-scale React codebases and many of them were a tangled spaghetti mess. It gets to a point where React's lack of opinions and standards for even the most basic of things mean you can see the same thing implemented 100 times in the React community. If you're building something beyond a landing page or basic CRUD app, you need some conventions. There is a reason despite the hate it gets, Angular is still used in enterprise and government settings. It's verbose, but you write components and other facets of your apps a specific way and know that Developer A implementing a feature is going to be understood by Developer B because it's not going to be so self-opinionated. This is something that backend frameworks learned years ago.

Don't get me started on the terrible communication from the React team. A good example is how they have handled React Server Components. They changed the docs to recommend RSC's by default, despite the fact many community packages don't work with them or require additional packages. The way they approached RSC's and rushed them out was terrible. This isn't the first time either.

I have been working with Aurelia 2 (https://docs.aurelia.io) and I love it. It's intuitive, it's fast, the developer experience is great, it comes with all of the needed dependendencies you need like a router, validation, localisation and whatnot. No need to go building a faux-framework of Node packages bloating your app. I've also been working with Web Components, which are in a really good place now too and getting better with each proposal (there are a few good WC proposals in the works right now).

Developers need to start using the platform more. Web Components have been supported by all browsers since 2020 (Chrome has supported them since 2013), so it's a good time to dive in. Using something like Lit gives you a nice development experience. Part of the problem is React developers have been brainwashed into thinking classes are bad because of some terrible design decisions in React (which led to Hooks) and writing Web Components relies on using class syntax (although, you can write them as functions if you really want to).

React is anti-standards, it's anti-developer and it's bad for the platform. The fact that React is ten years old and doesn't support Web Components still, goes to show just how little the React team cares about Web Standards . I know jQuery is a bit of a meme now, but at least jQuery helped shape modern standards. Has anything good come from React for the platform?


I have worked with Aurelia 1, and I strongly recommend against using this framework. Over time, I have collected many gripes, but just off the top of my head:

- Arrays are observed by monkey-patching the push, pop, and other methods. There is no concept of assigning keys to cells [1]. So, if you want lists to be stable, you must manually diff the arrays and mutate the old one.

- In general, the observation system was awful. They have a custom JS subset interpreter for their templates, and they secretly add properties to observed objects. If all else fails, they will start up a 300ms timer that polls for changes.

- The binding system favors mutations over functional updates, but deep-observing objects isn't possible. So, if you want to observe a data structure for changes, you may need to write down each key.

- I encountered multiple bugs in the templating language. I don't remember the exact details, but they were similar to this: If you have a containerless element somewhere inside a conditional element, that's somewhere inside a repeated element, the containerless element isn't rendered.

- No type safety in their templates.

- No conditional slots, no dynamic slots, it's not possible to forward slots, can't detect if a slot is used.

- In my tests, performance was worse than React.

[1]: Unless you dig through GitHub issues and find an external contribution. However, it was broken for some time and doesn't follow the Aurelia conventions.


These are all Aurelia 1 concerns which have been fixed in Aurelia 2.

- There is no dirty-checking in Aurelia 2. The observation system now uses proxies and other sensible fall-back strategies. The computed decorator for getters is also gone in v2, meaning no accidental vectors for dirty-checking.

- Observation system was rebuilt to use many of the same strategies detailed in point one. No dirty checking and proxy-first. Similarly, your next point about mutations, also has been addressed by the new binding system.

- Many of the templating bugs people encountered were spec implementation issues due to how the browser interprets template tags and content inside them. There were a few repeater bugs, but the ones outside of non-spec compliance haven't been a problem in years and do not exist in Aurelia 2.

- You can write type-safe templates now.

- You have have conditional slots now if you use the new au-slot element. A lot of the slot limitations in Aurelia 1 were because Aurelia adhered to the Web Components spec for how slots worked. In v2 there is still slot, but a new au-slot has been introduced to allow you to do dynamic slots, spot replacement, detect if slots are defined or contain content.

It's important to realise Aurelia 1 was released in 2015, so it's not perfect and some design decisions reflected the state of the web and browser limitations at the time. Aurelia beat out React in a lot of benchmarks back in the day. I'm sure Aurelia 1 vs React has slipped, but Aurelia was one of the faster options for a while, especially in re-rendering performance. You should give v2 a look. It improves upon v1 in every single way.


Aurelia 2 has been in alpha for years and is now only in beta.

My point wasn't only that these issues exist. If a framework has this many issues that go unfixed for years, while the user-base dwindles, maybe you shouldn't trust the developers.

In addition, I believe that not only the implementation, but the fundamental design that is flawed. There's a reason why UI development has moved away from the OOP/Mutation/MVVM approach. The problems that hooks were intended to solve are real, and every big Framework since React has provided approaches to solve them... except Aurelia.


how is the transition from aurelia 1 to 2?

my app has actually very little aurelia specific code so i expect this should not be to hard. if only i can find an aurelia 2 equivalent of this version that works without any build system: https://news.ycombinator.com/item?id=36971080


The syntax and overall paradigm of Aurelia 2 is the same. The team avoided where possible a repeat of what Angular did to the community with the transition to Angular 2. Most notable differences are routing and dynamic composition.

There is a build system free version documented here. Is this what you mean? https://docs.aurelia.io/developer-guides/cheat-sheet#script-...

If you need any help porting it over, just let me know.


that looks interesting, but it doesn't seem to work.

https://unpkg.com/aurelia/dist/native-modules/index.js doesn't resolve. i tried https://unpkg.com/aurelia/dist/native-modules/index.mjs which does resolve, but it links to a dozen other files which all don't seem to resolve either. it looks like unpkg.com is rather broken.

with aurelia 1 there was a downloadable archive (which still exists) that had everything bundled that i could just unpack and it was ready to run. it didn't even need a server to host the files if i was running a browser on the same machine.

the original documentation for that is here: http://web.archive.org/web/20160903072827/http://aurelia.io/...

basically there are two things i am looking for:

i want to be able to develop the application without using browser-sync or build steps and it appears the version you linked promises that.

but i also want to be able to host and develop the application completely offline without any need for internet access.

the reason for that is that i am using the application (in production as it were) while i am developing new features or fix bugs that i discover while using it.

running the transpiler in the browser doesn't bother me, it's been fast enough so far.

i would use aurelia-cli if i could figure out how to make it build a development version without browser-sync and without transpiling and compressing the code before it is deployed.


is there any framework that works similar to aurelia but does this better?

i really like how aurelia is practically free of boilerplate code, and doesn't force my code and data into specific structures.


I've been working with Web Components a bit lately and was pleasantly surprised to see Lit had some similarities to Aurelia. Nothing really comes close to Aurelia, which is surprising given it has one of the better developer experiences.


> The fact that React is ten years old and doesn't support Web Components still, goes to show just how little the React team cares about Web Standards .

No one cares about web components, including people who originally where really bullish on them (Vue, Svelte, Solid). React supports web components just as it supports anything that attaches itself to the DOM, and that is more than enough for the vast majority of use cases.

Meanwhile, if Web Components were any good they wouldn't need another 20 specs just to barely patch holes in their design: https://w3c.github.io/webcomponents-cg/2022.html or still have unresolved issues like "custom button cannot submit a form": https://github.com/WICG/webcomponents/issues/814

> but at least jQuery helped shape modern standards. Has anything good come from React for the platform?

It could have, if the people behind web components listened to anyone except themselves.


i think the popularity of react (and node) comes down greed. do more with less. a tumorous outgrowth of the "move fast and break things" attitude of early FB development and cargo culture of the tech boom eras.

you can have one dev write the front end and most of the server side code too. not only that but they have to handle much of the tooling, testing and debugging.

and the learn2code push also was designed to saturate the market with lots of these devs. many of whom lack the background knowledge to understand what they're doing.

i seen this job expand through the years from a smaller set of responsibilities to a much larger one where most of your work is only indirectly (and irritatingly) related to what you're actually trying to do.


> I feel like the new generation of devs got used to working with these abstractions and by some measures they seem highly competent, yet it feels like they're missing some critical knowledge; like they don't understand what's happening under the hood.

Is this remotely relevant, though? I don't think it is. The whole point of working with higher level abstractions is to not have to care about the lower level bits. We all know that things are not as optimized as they could theoretically be, and that's ok. People are paid to deliver value, and microoptimizing stuff just wastes everyone's time.


It's fine to work with higher layers of abstraction, but you should get some value out of it. What I think happened is that React just removed some work from lower layers and created even more work at a higher abstraction layer.

I would say that React gives you more work in terms of cognitive load and also in terms of development time if you look at it on a medium to long time-frame.


I think large systems get so large and complicated that they become very hard to reason about simply and think about. They become difficult to change their architecture or tweak them. So developer velocity takes a hit and the system is so complicated that it's hard to change anything.

LibreOffice, Mozilla Thunderbird are of such scale that it's difficult to change these applications how they work today.


+1

Have you been exploring any other technologies since React?


For my newest project, I'm going for plain HTMLElement (Web Components) but if I find that I can't live without reactive data binding/rendering, I will probably use Lit https://lit.dev/

So far it looks like I won't even need to go there... It turns out it's pretty easy to manage a web-component's dynamic state without reactivity (at least based on how I architect my apps). I find the HTMLElement lifecycle hooks (and attributeChangedCallback) to be sufficient.


What will you recommend as an alternative?


> I have a confession to make: I’m still not exactly sure what the difference between useMemo and useCallback is—or when you should and shouldn’t use them—even though I literally read multiple articles on that exact topic earlier today. (No joke.)

> I have a second confession: it’s still not intuitive to me what should and shouldn’t go into the useEffect dependency array, or why...

Come on, this isn't that complicated, I find it hard to take the criticisms seriously when the author hasn't groked React properly.


I'd be frustrated with React too if I worked in team where these things are not well understood.

You don't need to read "multiple articles" about these things, they're explained clearly in the docs

- https://react.dev/reference/react/useMemo#memoizing-a-functi...

- https://react.dev/reference/react/useCallback#how-is-usecall...

- https://react.dev/reference/react/useEffect#specifying-react...

To answer OP's questions, useCallback is

  function useCallback(fn, dependencies) {
    return useMemo(() => fn, dependencies);
  }
As for useEffect, everything that might change between renders, eg props used in the effect, must go in the dependency array.


The linter plugin for hook dependencies is pretty great, I very very rarely need to specify a dependency array different from the one the linter suggests.


Claims that hooks are the baseline and then proceed to explain how they don't understand the dependency array in useEffect huh?

It's fine admitting that hooks are a bit too complex. (don't get stockholm syndromed)


Right lol I don't even disagree with the author's larger point, but why is this such a common thing to outright admit if you're writing specifically to the topic?

>I’m still not exactly sure what the difference between useMemo and useCallback is


> There was a time, several years ago, when React was pretty much the only game in town when it came to server-rendered content

This is actual nonsense. Creation of a fully-formed HTML document server-side is performed by countless platform combinations.


It is a hilariously naive statement. Everyone’s PHP CGI bin on their basic free web hosting did/does SSR. Every Rails and Django app does SSR. SSR has been norm since forever.


PHP CGI, Rails, and Django can server-render a client app that gets rehydrated on the client? Because that's what the blog post is talking about.

Let's be a bit more charitable when we pull quotes out of context.


What does rehydrated actually mean? Honest question.

In PHP the server computes the full HTML and sends it to the client browser. What would need to be added here to have “client side hydration” for example?


Let's start in the other direction.

You have a client-side web application. You want the initial-state HTML to come over the wire on the first response rather than wait for the client application to load, make a request, and then render the result.

So you use a tool like those listed in TFA (like Next.js) to run your front-end app logic on the server to generate the HTML and send it to your client where your front-end app mounts to that HTML and takes over (cutely named rehydration).

This is relatively cutting edge stuff which is why it's weird to assume OP is an idiot who never knew about PHP or CGI when he wrote an article that is obviously talking about client-side applications and rendering them on the server.


They mean not having to write any client-side JS. So, having a mechanism to use the backend language for both the content that gets displayed when the page/component first loads AND any interactivity thereafter. It’s easy to populate a <select> with values with (traditional) SSR, but then you’d often have to write some JS to make additional requests when the user makes a selection, for example.

Seems weird to me to use “SSR” as a term for both SSR + hydration, but I’m not in the web dev lingo bubble so what do I know? The author doesn’t use the term “hydration” until the blurb at the end talking about Quik


The whole blog post is about React and client-side development, so the context should be clear. If it weren't clear, the other SSR-capable frameworks they list in the SSR section are client-side frameworks with the same SSR feature.

SSR when talking about React is very clear jargon.


Server-side rendering doesn't actually mean server-side rendering though. It's a term of art for a paradigm where applications are written in a single code base, and certain elements are rendered on the server and cached and other, more dynamic ones are rendered by the client.

The older platforms for this had you essentially write two separate backends - the one which renders HTML, and the other which returns a JSON or XML API for your hand-written JavaScript (or CoffeeScript or JQuery etc.) embedded in your HTML.


Not a front-end dev, but I think (correct me if I'm wrong) the usual way of SSR were things like returning a plain HTML web page in Spring/ASP.NET/whatever and that the main invention of Next as far as SSR goes is that you can write your server's HTML docoment in JSX.

So I would say the author's point (if I was asked about it) would be that these other new front-end frameworks support similar things, instead of sending plain HTML over the wire.

Am I wrong?


We had that discussion here in the past, I’ll just repeat my point of view: When someone says “SSR” today, especially with a Javascript context, they are specifically referring to Javascript SPAs (pre-)rendered server-side.

So, considering this, is it still nonsense? (I honestly don’t know.)


React is horrible and shows how little javascript developers understand about engineering. It sits right there with Laravel. They may be popular, but popularity sometimes indicates mediocrity as by nature it needs to satisfy the average.


It's a matter of perspective I guess, I made a living out of it :)

And also, mediocrity is part of our life on this planet, and also, a matter of perspective.


So did I. That's why I know its horrible. The amount of money clients spend on people to simply cleanup the messy code this framework helps create is ridiculous. I love the invoices, but the framework is horrible.


What do you use instead? Symfony? Honest question since im evaluating them both right now.


Gave up in PHP long time ago. Laravel is useable as it is, all tools are enshtified.


If I'd come here in when React was the new hotness and criticised it, I'm pretty sure I would have been shouted down.

In the meantime this one site I worked on, which used Java for server side rendering¹ with a bit of JQuery and custom scripts is still going strong.

1: It's ridiculous to hear JS people say how awesome server side rending is when basically every other language used for the web was server side, sometimes decades before it.




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

Search: