Hacker News new | past | comments | ask | show | jobs | submit login
Why I don't miss React: a story about using the platform (jackfranklin.co.uk)
334 points by tomduncalf on May 3, 2022 | hide | past | favorite | 267 comments



> But the web platform isn't perfect, and I suspect most React developers have come across a situation where you’d love to be able to just tweak how your component is being rendered.

Honestly, I haven't. The only potential caveat I can think of is when you have some non-reactive legacy code you want to embed inside a React component... but even then React's escape hatches are more than sufficient.

If you're really worrying about when your component renders or re-renders it's probably because there are other issues with your app.


The escape hatches were one of the first things I used to explain why I initially liked react, called them exactly that too.

"They're smart enough to know they're not smart enough to build perfect abstractions, so they do a great job but leave escape hatches just in case"


This is why I felt out with Elm. It is harder to escape the hatches with it.


You can use the ports system and interoperate with js in Elm. I used it in the past and it is quite a clean abstraction.


It's frustrating that it forces you to jump into handling async code, though, in all cases. This wasn't always the case, and for good reason: sometimes async code is just vastly more complicated for no actual benefit if you can tolerate the FFI causing a crash at any calling point.

The interest in Elm took a major hit after the compiler banned use of JS.


That is what I mean! You need static top-level declarations of every out-of-elm iteration you want to do.

React on the other hand can wrap a JQuery calendar in a React component and from a programming point of view, using that component you would be none the wiser.

Also ports force everything to be async - and I am not talking just promises - I mean a new render per call response! So calculating 1+1 on a port requires generate a new render, and intercepting the result in a Redux-style handler, bubbling that into a component.

While you won't need to do 1+1 via ports, you might need to use a synchronous web-api feature that has not been ported to elm, or even use a math package to multiply some matrices.


you dont escape hatches; you escape THROUGH the hatches


So not \h\a\t\c\h\e\s ?


The only case I have is I love to use D3 for vis. But the thing is it's trivial to embed D3 into a react component and either let react handle rendering via svg or honestly just let D3 take over the DOM in that component. I do this all the time and it works very well.


I wrote my own React components using D3 to do the underlying math but setting up my own DOM rendering. It's ok, my thoughts

Pros:

* I have generic "zoom/pan" implemented. I did this by making a generic ChartContainer with 5 zones - top, right, bottom, left, content - and you specify just the size of the non-content zones (if displaying them at all) and otherwise it behaves responsively (i.e. CSS style on the container is respected in the internal math). When you scroll the left/content/right vertically, or the top/content/bottom horizontally, it virtually scrolls the other components for you. It also of course handles the math, each area of the 5 is passed a DOMRect describing how big of SVG it can render

* I have smart edge routing component on a graph; if you are doing the math yourself on how to position the SVG elements, you can easily describe that graph, so smart edge routing is free

* my library has themes via CSS vars, and the components written in this way are obviously automatically themed

Cons:

* it's a bit verbose for sure, takes some small time and focus. After the initial investment in ChartContainer though, they work freaking awesome

* D3 graphs often come with sweet animations and such, I don't have any capability to emulate this today, I hate to do performance-heavy things like manually doing math every frame in a hooks-based way, and I don't want MobX in my component library

* you sort of lose access to the D3 ecosystem, nothing is free

To be honest, I think I have made a top-tier Gantt with the smart edge routing and zoom, my Graph looks sharp too, and for overhead views it's super nice to be able to zoom and pan and show rulers on the side (imagine showing factory layout, or a board layout, etc). Otherwise, if you are doing more traditional pretty eye-catching stuff, it's not quite meant for that approach


I also went this route and used d3 for the math but my own hand-made SVGs for the rendering so that the DOM is all in "react land".

You may want to check out this library: https://airbnb.io/visx/ They converted a ton of d3 features into proper React components


I’m a huge fan of visx after discovering it a few years ago. I recently needed to create a custom line chart and looked into numerous React-based libraries but none fit exactly what I wanted, so I went back to visx again. It requires more planning, but the results you can get (just like with d3) are incredible.


Nice link, thanks! I built my own axes / legends / mouseovers but this other stuff looks awesome, really nice to be able to compose their parameters too if I offer something like a line chart etc. I will definitely try to integrate some of this


Awesome library. I used it back when it was named Vx with react-spring and d3. You can’t beat this combo.


Does d3 have a typescript wrapper?


As in a wrapper with an API more geared towards statically typed usage? Or just type definitions for the existing D3 APIs? The former is really uncommon (or at least not a particularly commonly idiom), but the latter is typically a quick search for @types/${packageName}. If that’s what you’re after, I was curious and saved you a search, because it would be quite surprising to me if something as popular as D3 was missing type defs: https://www.npmjs.com/package/@types/d3


React doesn’t offer any render optimizations by default, so not worrying about it sounds like blissful ignorance - you’re just ignoring a ton of unnecessary renders because they don’t visibly affect performance (on your development device). After a certain level of complexity the issues will start to show.


React offers tons of optimizations for not re-rendering. useEffect, useMemo, useCallback.


React 18 even will have batching built into all state.


"by default". You still have to use those manually.

One of the promises of switching from class-based components to function-based was supposed to be an automatically applied version of shouldComponentUpdate, which AFAIK was never fulfilled.


Not true. Even if you memoize all the values and props used, your component will still execute, generate vdom and go through reconciliation. You must use React.memo in addition to memorizing everything in order to completely prevent a no-op re-render.


What's there to optimize? If you don't use state, it doesn't rerender. If you click a button to add another element for example, it does exactly that. If you have a reactive variable in your HTML and update it it rerenders that part only. What's there to optimize further?


Depending on the complexity of your computations and state, what you just described can basically become unusable. For example, an app I work on implements a spec which:

- Models state as an arbitrary DAG

- With arbitrarily deep dependency chains

- Which may trigger dependent nodes based on only subsets of their state

- Based on computations of arbitrary XPath expressions, sometimes containing non-native extensions; these can be expensive whether implemented as a hybrid wrapper around native XPath or fully in userland

- Which in turn may trigger recomputation of their own dependent nodes

A naive implementation of this according to the algorithm you described will cause real world usage to block sometimes for several seconds until the app becomes responsive again.

Being able to have greater control over when to commit state and when to render intermediate state are crucial to usability for this app. Being able to defer the entire computation for state without a path to an associated view is even better. Being able to batch state -> render updates based on priority even better still. All of this can be accomplished with React’s APIs, but it certainly wouldn’t be the default behavior. And it’s all from a real world use case where SolidJS—which has a similar DX to React but significantly better performance, and which I’ve been prototyping for gradual adoption—also needs more optimization than its dependency tracking alone can achieve.

Even trivial demo apps with well designed pre-hydration state (note: already optimized beyond the default) and otherwise find performance at runtime can suffer significant lag between LCP and TTI by running far too much code for stuff that’s nowhere near needed for immediate interaction.

Granted in most cases this tradeoff is reasonably acceptable. In many cases it’s not. Prematurely optimizing it isn’t a great idea, but there’s a wealth of room for optimizing when it’s valuable to do so.


> Being able to batch state -> render updates based on priority even better still.

Mobx [1] is pretty good for this, it batches updates that happen, making rendering more efficient.

Also regarding rendering, react will update a component it it's state changes. It might update its children components, but if you pass them in as props, they won't be updated, as they're rendered in the parent component's context.

This allows you to create complex applications with thousands of interactive components, and have quite good performance, as minimal rendering is performed.

[1] https://mobx.js.org/react-integration.html


Yep. Solid is too! Even so all of these abstractions need help when the computation itself is expensive and knowing whether to perform it is too. The ones best designed for that provide really clear APIs for how to take control where they’d otherwise handle it.


Would love to know what the app does. From the mentions of xpath all I can think is "visual xml editor"?


It’s an implementation of ODK[1] extensions to the XForms specification[2]. The specific implementation is Enketo[3], which I was brought on to ODK to help maintain. Not exactly the spec I’d go with greenfield, but it’s been successfully in use for a decade with great impact.

1: https://getodk.org/

2: https://getodk.github.io/xforms-spec/

3: https://enketo.org/


ideas:

could be using data returned in XML format because there is no JSON endpoint for that particular data source.

XPath is also nice for dealing with just about any complex markup tree, for example if you needed to extract data from serialized DOMs that were sent to your application somehow.

How about SVG tools using XPath?


Thanks, great ideas and I'd never considered XPath for SVG. I need to delve into that one further.


>what you just described can basically become unusable

Oh, so like every JS interface ever. :D


I mean, not really? My naive implementation in Solid required a few tweaks understanding the model and performs updates perceptually instantaneously on a perf sensitive input I use as a smoke test, without any of the tricks I expected to need, just its built in reactive primitives. The existing implementation performs the same computations on that data in about half a second, which feels like an eternity without special care to unblock the UI. JS is really fast. You just have to know how to use it, and when not to.


Every programming language and application has the chance to become unusable, thus every JavaScript application has the opportunity to become unusable, obviously most do not because otherwise nothing would be usable on the Internet which, snark aside, things are usable even if they might annoy me.

>You just have to know how to use it, and when not to.

So, you have never had a JS application delivered over the web become unusable despite your attempts to only use it how and when you need to?

Okay, well, congratulations either or in order or you've not been forced to use it for something you didn't want to or have just never been building something big with the technology and made a mistake?

I mean my stuff generally doesn't become unusable, but generally is not always.


> So, you have never had a JS application delivered over the web become unusable despite your attempts to only use it how and when you need to?

Of course I have, that’s not the point I was making. My point was that JS and the VMs it runs on are very fast, if you know how to use the language and when not to use it. That couldn’t possibly apply to apps you didn’t build. If I’d said C or whatever is fast if you know how to use it, I don’t think I’d get this comment about some horribly inefficient downloaded printer driver.


I take your point, and can appreciate how more familiarly will lead to greater ability to address these sorts of things, but I do feel like your last two paragraphs / “caveats” could represent a massive edge case.


>If you're really worrying about when your component renders or re-renders it's probably because there are other issues with your app.

that's why I prefer Solid instead of React. For client side stuff, Solid is sooo much better than React.


This has got to be gaslighting at the highest level: oh you're doing something wrong because that's not how you're supposed to do it in React. Not since Java's Spring have I encountered such weird zealotry for a relatively mediocre (but widely popular) framework.


Too many folks' livelihoods depend on it at this point. The other side of the same coin is the gaslighting that you can't build anything sufficiently complex without react. If you did build it without react, it obviously wasn't sufficiently complex.


I'm fairly certain you're trolling but as a good rule of thumb if you find yourself fighting your framework you picked the wrong one.


I'd suggest thinking about dismantling your framework if you've been happy with it for a bit. If you've been rewriting or authoring large chunks and disabling features it might be informative to spend a slow day looking at what you've found useful.


> Not since Java's Spring have I encountered such weird zealotry for a relatively mediocre (but widely popular) framework.

You've now described the Web Components crusade which, among other things, engages in actual gaslighting.


If all you need is a couple of basic forms and some basic interaction, you can do it all with vanilla JS but let's not kid ourselves. This will not allow you to build very rich apps without implementing a significant chunk of the frameworks you dislike so much. In fact, I would even say that if this is not a core part of your product, you are simply wasting time and resources. There is a huge amount of man-hours poured into making these frameworks work correctly under any condition.


> If all you need is a couple of basic forms and some basic interaction, you can do it all with vanilla JS but let's not kid ourselves

This is a classic red-herring argument from developers who have not built anything complex with vanilla js. You can build rich interactions with or without a framework, you’re just making different trade-offs (conventions, learning curve, flexibility, tooling).

There is a much larger amount of man-hours put into browser APIs, and web components is one of them. I don’t see anything wrong or that warrants a “you’re wasting your time” warning in his argument. And note, he’s talking about the chrome dev tools everyone including the react team use daily, not “basic forms”.


Using web components makes your forms instantly inaccessible without JS. Browser APIs evolved over time and albeit most are pretty good nowadays, a lot of stuff is still bad in HTML world and frameworks like these solve that painpoint. The framework still allows usage of FormData and whatnot, there's even a new framework ontop of React now that aims for form handling without any JS at all in the browser so there are good reasons to adapt them.

And the fun part is that when you are going with the browser APIs like a responsible developers, do aim for backwards compatibility and browser support and all that jazz you will at some point also be annoyed to write a lot of imperative code to add a modal, add this field dynamically, handle class toggles and make another button somewhere change something else in the UI that it's inevitable that you write a poor-mans version of React that now no one knows how to maintain and onboard people.

React didn't come from PHDs in some university, it came from the real needs and desires of developers to just think in "I want my UI to look like this, get it done" and not in "Aight, I add a class here now, but update the value here, this button also needs to be disabled now and then make the request and if it fails then add this element for the error in this spot and enable the button again but if it works yeah just throw all of these away and replace it with a success message"


I’m not sure I can even make out what argument you’re trying to make, but let’s go.

Nowhere in the article the author claims web components is a great choice for everything. He works on DevTools, which is not a website, and 100% js already. Seems like a perfectly ok choice.

> be annoyed to write a lot of imperative code to add a modal

I’ve recently added a modal system to a react app using react-aria-modal, and no kidding, it took over 1000 lines of code* to get it working, following their guide to the letter. Later, out of frustration, I reimplemented the same feature using Svelte (which lets you get much closer to plain JS and HTML), with the same features and aria support, in a couple of hours and 10x less code.

> it's inevitable that you write a poor-mans version of React… it came from the real needs and desires of developers

React uses a very specific architecture of VDOM, stateful components, hooks etc. There are plenty of alternatives, including well developed “poor-man’s versions” like Preact, hyperapp or SolidJS.

It seems you’re under the impression React is some kind of universal solution to all frontend apps, developed by “the people”. It’s just a framework, developed at facebook, born from the evolution of their existing server component system. It works, feels nice for small apps, I use it along with a million other people, but it’s not a panacea, and it’s sad that a lot of people simply dismiss everything else before they’ve had a chance to actually understand the trade-offs.

* id say it’s imperative code too - calling hooks in the correct order, passing data from one to another, telling react what the dependencies are, updating and transforming values


You call the argument a red herring, then name all the reasons people use a framework over vanilla js: conventions, learning curve, flexibility, tooling.

Sure, the browser apis are great and always getting better, but I don't see how that's a reason not to use the framework.


Conventions, learning curve, flexibility, tooling or just because that's what is there already and you have no decision either way :D


You’re arguing chrome dev tools were built with vanilla JS and didn’t require their own bespoke framework? That doesn’t track for me


> There is a huge amount of man-hours poured into making these frameworks work correctly under any condition.

The path is littered with the ghosts of frameworks past. Don't let the current efforts or trends convince you that we're done with this process. React will be a ghost one day.


I can advertise for a "React developer" and find people familiar with react rendering. I will never be able to do that with in-house render solution. This will apply to whatever replaces react as well.

Unless I'm selling a render solution, I don't want to be maintaining a render solution. Maintaining glue code might suck, but writing everything from scratch limits the scale of the work that a person can accomplish. I liken it to polishing gears rather than driving the car.


I think that's the biggest thing to me. It's easy to say 'we can do just fine without $BAG_OF_TOOLS, there's no real need for it, it's simpler and faster and we get off the ground with it', but then once you have enough people that a bag of tools is needed, you create an in-house bag and soon you have a 'simple' system for managing state that is nevertheless much less exciting to the new cohort of $BAG_OF_TOOLS bootcamp graduates, etc. And people pointing to the framework graveyard ignore that you need to hire people now, not 10 years from now. If 10 years from now React is as obscure as an in-house framework, meh?


That's like saying I should use a steam engine today because the electric motor will be superseded someday.


That's not the dynamic.

It's people that think electric motors are always the right solution to every problem and it's only a matter of rube Goldberging it up to shoehorn electric motors in to places that that's better without them.

It's against arrogant dogmatic rose colored glasses fanboyism being mistaken for software engineering

And this isn't straw-manning, the internet is full of these evangelists that exist as effectively marketing arms, as if they're bicycling around wearing nametags on behalf of the Church of Current Day Frameworks.

All it does is create messy piles of tangled garbage that wastes people's times and gets thrown away to be rewritten when the next flashy thing comes around. It's hot fashion for programming

It's gross and needs to stop. Seriously. Let's build the future, help fix the world's problems and quit fucking around.

This fetishism for shiny things have left us impotent executioners of meaningful change and thus we are amidst the tech stagnation


The way it played out with jQuery is that there was a transition period; gradually more and more classes of app didn't need to be built with jQuery and it was easier to build them without it.

The implication was that we're in a transition like that presently.


The steam engines will continue to run on coal after the natural gas to the power plant is shut off and the power stops working for the electric trains


If an electric engine makes your vehicle noticeably slower and heavier, there's a reason to keep using a steam engine.


Or maybe it’s more like saying ICEs will be a ghost one day? EVs were once the path not taken…


I said no such thing.


You implied it. What you should have alluded to is that it is necessary to use technologies today that won’t necessarily be in use in the future, merely as a stepping stone to get us to the next destination, where we will use a new but still temporary technology.


As Scott Adams says, "Analogies are for fighting." If you try to counter a statement with an analogy you almost always simply get a fight.


Quoting absolutes expressed by highly opinionated people is also for fighting. Not saying you shouldn’t, but maybe there’s some nuance missing. Not even saying the particular analogy was devoid of conflict, it has plenty of room for disagreement. But it didn’t feel to me like it was inviting any which wasn’t already present.


I would classify Scott Adam's statement as a trueism -- true for most people, under most circumstances, for most times. Unfortunately, couching a trueism in its most precise linguistic form with associated probabilities and error margins is a path to simply being ignored. Once a thread switches to rhetoric, dialectic responses are like pissing in the wind, forgive the analogy :-)


Well I’ll give you this: quoting Scott Adams then correctly using and understanding the word dialectic is definitely not on my HN comment threads bingo card.


Surely it's the countering bit that shows you want to get in to a fight more than the analogy. Analogies are just a way of illustrating a point.


I do wish that people would engage in dialectic conversation when they encounter an analogy, rather than rhetoric. Unfortunately, I find Scott Adam's words ring true.


Never thought about that, where do you get this from? But it kinda rings true for me in life.


I heard it from Scott Adams, the creator of Dilbert. In addition to writing that comic he is a very interesting thinker. He is also a trained hypnotist.


I think op was suggesting someday we’d be on hoverboard or something


We're all gonna be debugging wordpress apps in the metaverse while our self-driving cars whisk us down the freeway.


The longer something has existed on top, the longer it will continue to. React still hasn't peaked yet. Its tail to obsolescence will outlast anything you build in it today.


Which is certainly more about popularity and subsequently littering the world with soon to be legacy apps. React and Wordpress, pick those up and you'll have work for your whole career I suspect. Also a legacy knowledgebase on how to achieve just about anything with both of those tools.


That’s a pretty funny stance. The library has a gigantic developer share and is supported by a tech giant. A world where React isn’t used and remembered is one where the web isn’t based on the same primitive. The idea of a thin layer on top of JS offering composition is not complex, and the execution by react is still trend setting. Remember when they introduced hooks and now tons of libraries have the same thing? That’s not because React is behind the times and possible to supplant as a small team


Applies the same to jQuery or Bootstrap?


Just a friendly reminder that React is approaching a decade in life. There are no other competing frameworks that look to be taking it’s place.

Not saying it will never go away, just that, maybe the front-end world has finally, significantly slowed down in churn. Things could always be better (Svelte is nice) but overall, React does what I need and I rarely curse at its design.


How was the situation of jQuery 2014? Seems to me pretty similar. So in 2030, react will still be widely used but largely obsolete.


Not at all.

From jQuery’s release to 2014 there were multiple phases of front-end frameworks.

Backbone, Knockout, AngularJS, Ember. All of these had their time in the light during that phase. Most companies were already switched over to one of these frameworks. React was the new kid on the block at this time.

You Don’t Need jQuery was out well before 2014.

It’s also a bit difficult to compare jQuery since it’s a library that can linger in a codebase indefinitely. It’s not a framework.

Also jQuery release date was 2006, so the equivalent year 9 would be 2015. By which point React migrations were in full swing. I wrote my first on the job React + Flux application in 2014 and then joined a new larger company in 2015 where we were making plans for a React migration.


> The library has a gigantic developer share..

So did jQuery, and that google framework used to create Gmail, what was it called?

Oh yeah, nobody cares anymore because they're irrelevant in 2022.


And jQuery is still used in lots of places without any problems AFAIK.

Even if the React development team would stop the framework will for sure be around for a couple more years and receive at least security patches.


I've worked on webapps that are part jquery, part classic angular, part react, and part angularjs.

My opinion of each of those parts has been primarily down to the developers, not the underlying choice of framework.

Things that work in production last.


jQuery has faded into the background, no longer interesting.

React has too many sharp edges, it'll only be here until something shinier supercedes it.


> jQuery has faded into the background, no longer interesting.

It’s a mature, stable technology, still in wide use - and not really a competitor with react. That you claim it’s “no longer interesting” says more about your own preferences and ironically makes it sound that you are personally interested in the newest shiny fads - so I’m confused, what is your objection to react then?

Angular isn’t exactly dead - and is a more apt comparison.


I’m currently job searching and actually came across several mentions of jquery in job descriptions. It’s still alive!

Edit: 3,700,000 downloads per week on npm alone. That’s not a complete or perfect representation of usage, but that’s a significant number


What else do you need jQuery for? The most important parts are already included in the browser.


Honestly I bet a significant portion of the code I have maintained (and even some I’ve written) was reinventing a wheel someone didn’t know existed. Not even out of a desire to solve a problem, but simply not realizing it was done already.

I suspect people still reach for jquery for similar reasons. They know it makes complicated stuff work, it’s reliable, they don’t need to think about the specifics of the problems it solves… As a result, they’re less likely to discover that it’s no longer necessary in the first place. They’ll just keep using it.


The same will happen to react. React will become a victim of its success, because the more it is used the more likely its concepts will be integrated directly into the browser or ECMAScript


Maybe this is less obvious if you’re deep in the React ecosystem and nothing else but I’d argue that React is already in early stages of a death spiral for a few reasons.

These mostly come down to

1. It’s no longer the fastest, in fact it’s barely competitive speed wise with many things that have come after it.

2. It’s architectured in such a way that it is fundamentally misaligned with the rest of many web standards (I.e the DOM) which made a lot of sense when it was released but is now a major liability.

3. It now has to ship around a lot of code that now lives natively inside the browser and is now rather bloated as a result compared to newer iterations such as Lit as mentioned in the article.

Personally, I think it’s fatal in the sense that they have painted themselves into a very specific corner with no obvious engineering solution to get them back on the standards path. Its problems as a result aren’t really fixable without major architectural changes that would fundamentally change the project. On top of that they are only going to get actively worse over time as more things get moved into the browser and they are still stuck shipping a bunch of JS code to do the same thing. In short they are on a bad long term path with no clear off ramp.

I wouldn’t start a major project in React in 2022 for something I wanted to be around in 5 years from now as a result.


Never said I wasn't partial to shiny.


jQuery was and continues to be just about as successful as it is possible for a project to be. The reason it’s no longer as widely used is because it essentially became part of the platform. Most of what jQuery does is now possible with platform APIs, and those APIs exist mostly thanks to jQuery proving their utility.

A similar thing happened to CoffeeScript: no one uses it anymore because nearly all of its good ideas made their way into JavaScript itself.


What sharp edges? (This is an honest, curious question.)

I don't find many sharp edges in day-to-day React work. I say this having once been a very strong proponent of framework-less frontends, before trying Vue, then Svelte, and then settling on React.


Does React itself have edges, or do your issues derive from other parts of the ecosystem (Redux, styled-components, MobX, whatever)?


React has edges. Hooks are an anti-pattern with all kinds of footguns. Suspense is also a crazy anti-pattern by literally throwing and catching errors as a means for communicating between parts of the framework.

And this isn't an issue of me not understanding React or hooks, I would consider myself to be as expertly acquainted with hooks as it's possible to be.

Now, do I still use React for everything? Yes. Do I prefer hooks to class components? Also, yes.


> Suspense is also a crazy anti-pattern by literally throwing and catching errors as a means for communicating between parts of the framework.

Okay I can criticize React and its weird solutions until the cows come home, but this is a pretty weird one because it’s entirely an implementation detail. No one working with Suspense ever needs to know that’s how it works unless they’re building a library to be compatible with its behavior. Otherwise it’s just trivia.


Wouldn't the debugger break on exception? So any exceptions used in "nonexceptional" situations have a potential to "pollute" the debugging experience?

Admittedly, I haven't tried debugging React 18 yet, so I don't know if that actually happens in practice.


Only if you set it to break on handled exceptions/Promise rejections. This isn’t new behavior in React 18, it’s been the mechanism used for Suspense since it was introduced. If you have used Suspense and haven’t had unexpected debugger pauses, that’s what you should expect going forward.


I work primarily with React, and I'm curious - why do you consider hooks to be an anti-pattern? (This isn't a criticism, genuine curiosity)


In practice, because they don't work the way most people think they work, and because it's really easy to screw up using them.

Hooks are called every render, which is a relatively transparent process that happens all of the time. All hooks have to be called every render, otherwise you're breaking the rules of hooks. The reason why is because the only way hooks know which hook they even are, is the order in which you call them.

For example, if I have

    const a = useRef(true);
    const b = useRef(false);
The only way react knows that the first value it should return the next time it renders is what I'm expecting to be value `a` is because that useRef is called first every render. These are all kinds of rules and assumptions about hooks that make them not behave at all like normal functions. I don't think people understand that, for useRef, for example, those two lines of code are run every render, passing in the initial starting values, which then react disregards after the initial render, and maintains a mapping of ref and state and memo etc values all by the order the hooks are called in. I see people use hooks in callbacks all of the time and just fundamentally not understand that they're doing it wrong.

Then there are all of the closure problems with useEffect and useCallback that I see people really struggle with.

And useState...lordie. The fact that it defers setting the state value, whereas useRef will immediately have its value updated. Deferring useState has caused so many bugs.


I don't like them because they hide program state in innocuous-seeming function calls. Want to call useContext in a helper? It'll work, until it doesn't. Want to display a loading spinner? You'd better not have any useState calls below it. Want to see what hooks a function will use? You have to run it or go through each line of every piece of code it calls, they're not in any way declarative.

The programming paradigms I like best are declarative and make invalid or undefined behaviour impossible to represent. Hooks do the opposite: they're procedural, make it very easy to write a program that compiles with subtle errors, and don't have compile time checks to stop bad code.


> jQuery

I still see it on resumes today.

> that google framework

Seriously, Google stuff is infamous for being smothered by Google itself, what's your point

> nobody cares anymore

Literally the only non-Google example you could think of is still popular. But jQuery wasn't a graceful idea with a strong implementation, it was a wrapper to alleviate the pain of browser APIs. React is a wrapper to alleviate the pain of JS. Thus my original claim: "[a] world where React isn’t used and remembered is one where the web isn’t based on the same primitives". I don't see that happening soon.


I'm not a frontend expert, please forgive me.


Web components might change those primatives. It is still pretty early days, but I would be surpriaed if react isn't replaced either by something built on web components, or maybe even native web components.


> It is still pretty early days

Web components were proposed 11 years ago. Widely available for at least six. When will it stop being "early days"?

Now all the air in browser development has been sucked out of the room by them. Instead of actually moving the web forward browsers are busy patching holes and problems created by web components because they are horrendously badly designed.

And they still have an issue list as long as the equator. Any framework in such a state in "early days" would be laughed out of the room.


> widely available for at least six

Custom Elements weren't available until 2018. So unless you are referring to the chrome-only experimental v0 version, I don't think you can say it has been widely available for more than 4. And there will likely be substantial improvements to it before it starts dominating web development.


> I don't think you can say it has been widely available for more than 4

Yes, my timeline was off.

> And there will likely be substantial improvements to it before it starts dominating web development.

I'm definitely veering away from my original statement, but here goes :)

There won't be any substantial improvements in web components. It's painfully obvious how many shortcomings they have, and how many holes have to be patched before they can become actually useful. I mean, they had to come up with a whole new Javascript API just to make them participate in forms.

And now their existence taints and poisons most other improvements to the platform. For example, Scoped CSS (which on its own would solve a huge chunk of what web components offer) now have to be twisted to accommodate web components, and will likely be a worse spec as a result.

Chrome "developer advocates" will incessantly berate and gaslight other projects and frameworks, and will claim that web components are a success because companies with billions of dollars in revenue and thousands of developers use them to create a yet another avatar or breadcrumbs component. That... that is neither success nor a path towards any substantial improvement.

"It's almost as if congealing 2010-era best practices in the platform before we'd finished exploring this territory was a mistake" [1] And the future is likely to be component-less [2]

If the tens of millions of dollars that Google alone has poured into Web Components had gone into something meaningful like https://open-ui.org we'd have a significantly better and a substantially more future-proof web. Alas.

[1] https://twitter.com/Rich_Harris/status/1513668040784814084

[2] https://dev.to/this-is-learning/components-are-pure-overhead...


> without implementing a significant chunk of the frameworks

In my experience, it hasn't seemed all that significant. These frameworks are absurdly general and cover a range of use cases and deployment methods that most people don't use. I just need the kitchen sink, not everything else.

So far, just using custom elements and a small wrapper around the <template> element, I've not been struggling to create the features I need or would otherwise miss.


Yeah, my experience is that people frequently overestimate the cost of building something for your needs and underestimate the integration cost of buying something.

Also, the trend of hiring <framework> developers is a plague: if you know JavaScript and the DOM well, learning the basics of react is a couple afternoons of work and you can figure out the pitfalls via code review and learning on the job.


That’s right, except I think it would take most people longer than an afternoon. There’s stuff that’s quite unique (and powerful) like useEffect and JSX takes a bit to get used to.

But generally I wouldn’t be worried about onboarding a web dev who doesn’t know the lib, it’s not rocket science. One of the appealing things is how very straight forward and clear it is.


> This will not allow you to build very rich apps without implementing a significant chunk of the frameworks you dislike so much

I am currently working on an app at work that wants SPA functionality, but they won't let me use any of the frameworks. Tons of vanilla JS and Jquery. I am sure what I have written is probably considered a crime against humanity in some place.

Does it work? Yes. Is it an elegant and maintainable codebase? Not by my definition.


I feel you. I remember the old days of trying to build SPAs in jQuery and they were dark ones.


I actually have quite happy memories of working with Backbone and jQuery - there were obviously all manner of problems, but everything was quite easy to understand and a lot less magical. Apparently this was in 2012 - how time flies! - so I imagine rose-tinted spectacles must be in full effect here!


That raises an interesting question: what would be the declarative framework easiest to minimally reimplement?

I’m thinking you could have a single file, jQuery-based, hand rolled version of some framework and get many of the benefits while still technically complying with the “no frameworks” rule. In the same way that you could reimplement Redux easily if you for some reason weren’t allowed to use it.

I suspect diffing performance would be the bottleneck but I wonder if you could come up with some weird half solution that worked for your particular use case.


I would love something like this, but I do not think I am at the level to be able to build something like this, at least not in a reason amount of time.

I've not used Redux for anything before, but I will look into for sure. I've heard the name thrown around a few times on here, and I could probably use something like that. Just nothing that would require a staunch learning curve to use.



Look at the Mithril or Preact codebases and make a basic version of your own.


I will look into these. Thank you for sharing.

I doubt I will be able to roll my own version of whatever these project due mainly because of time constraints and because I am the only developer working on it. Since we have adopted all the Agile stuff, Sprints are basically deadlines and not very...Agile.


I've been down this path.

I've built my own framework once out of frustration, thinking typescript will make it easy... after a while I realized that I was just rebuilding chunks of existing frameworks and most likely not in the best way. Webtech is really messy to begin with, typescript didn't really save me. So I stopped. Sure it was nice to know how to build your own viewstack, navigation and state management and how to some newer html5 features, but it really was not the way to go. Vue js seems to be closest match to the way my mind works and built a very crippled version of it minus all the good tooling and plugins. I was also influenced by Knockout and Wpf/C#, so it had some similarities of what I used to do in those. I honestly do not like the way react works or the way it wants me to work, it feels extremely messy too (syntax and project structure)! I get the same feeling from react that I got from own crappy framework!

So anyone reading this, I encourage you to build your own frameworks, but think very carefully if you need it in production and can support it in the long term. Try to keep emotion/ego out of the decision.


Maybe I'm misunderstanding your point, but React really doesn't dictate project structure at all.


I think react sits really well with some people, and with others it doesn't. For me I find I have to fight against the platform to separate presentation from behaviour. And let's not kid ourselves, a lot of react code bases do the classic winforms mistake of having an essentially code behind architecture.


And why was that a mistake?


IME marrying business logic so closely to presentation makes it very hard to change one without the other. Especially relevant for web apps, where you may want to re-use business logic for mobile apps, which becomes very difficult when they're tied to a react component.

Also makes it harder to test. There's a great paper called "Naked Objects" which I'd recommend for anyone doing GUIs, but powerful idea I got from it is make your presentation code so immediately obvious from your business objects that you can practically generate it automatically.


Pawson's Naked Objects thesis is absolutely brilliant.

It proposes a complete approach of which not all of the parts will be useful for any given project, but it is -very- much worth reading even so.


Hey, someone else on the internet who knows about it!

And yeah agreed, but I think we could all use some scantily clad objects at the very least.


Because it was implemented via inheritance. Which is why the argument is BS, nobody does react like this. They specifically tell you not to do it, and I think there's a bunch of stuff in there to stop it from working.


> of the frameworks you dislike so much

This is totally uncalled for. He's not attacking you. He's explaining a tradeoff, very reasonably.

> I would even say that if this is not a core part of your product, you are simply wasting time and resources.

I find especially interesting that this phrase can be used to defend both sides of the argument. If you are building a highly rich application, chances are that using a framework for that is the right choice, agreed.

But.

Not all the apps being build out there need to be Very Rich Apps. There's indeed a lot of space for only-slightly-rich-but-mostly-static apps, despite the recent HN article.

And for those, introducing a framework is ... precisely, a waste of time and resources.


> This is totally uncalled for. He's not attacking you. He's explaining a tradeoff, very reasonably.

What? I don’t see how “dislike” would describe anything other than some kind of preference. I don’t see how it’s an attack.


Their comment is perfectly reasonable and measured. I don't think anything in it is 'uncalled for'. Your own comment is a confusingly ironically ill-tempered response.


The phrase “The frameworks that you dislike so much” is not an argument. It’s a characterisation. It implies that the OP is blinded by his own personal preferences, and that his arguments have no weight because of that.

Imagine if I had started my answer with “Since you love frameworks so much, then…”. That would have been a similar mischaracterisation on my part (equally uncalled for, since I don’t know the other person enough to make such judgement)


Jack builds Chrome DevTools, that's a really rich app and seems to work pretty well


> Was this slightly more work than using a library from npm?

> I'd definitely recommend using a library for this, and we settled on lit-html (link to library from npm)

This article is mostly about switching from React to Lit. You can use modern web APIs (like FormData) with React, FormData's not a replacement for state management.

You can use Web Components with React, the way Fluent UI does (https://docs.microsoft.com/en-us/fluent-ui/web-components/in...).

In this single case they replaced a couple validation functions with attributes. Good to move that direction but if that's all you use React for then yeah, you might not miss it much.


Anyone know what is going on with lit-? Their TypeScript starter is painfully bloated and outdated and never seems to keep pace. I actually ended up looking at microsoft/fast for my use case but that seems to be stale in some way.

I kind of feel that given the "simplicity" of a single class wrapping custom elements, everything is pretty boring.

Note: I cannot do better.


I feel like google does web component frameworks like it does messaging apps. Each new one is the silver bullet. I wouldn't build on any google web framework personally, even if it claims to be oh so simple and lightweight.


Mirrors my experience exactly. Used polymer, angular, react and lit element. I’ve been able to rely on react for almost a decade. The others have just been mistakes


You don't understand the context since Polymer and Lit Element do not solve the same problem space as Angular and React aim to solve.


This is very small thinking. The context is to produce value for a user on a web platform. I’m well aware of the APIs and limitations for each of these.


I use Lit and have a tiny bit of MS/FAST in one project. You're right. Neither site gets updated. I think both have terrible doc, really. I didn't learn anything from the Lit starter or the intro doc. Only the interactive tutorial was of any use.

I think FAST is dead because MS doesn't want to play keep-up with it. In fact, all of the component libraries that Lit advertises on their home page (https://lit.dev) seem be Thanksgiving leftovers put out on a buffet. No one is seriously updating a set of web components for public use.

But... perhaps that is because Lit isn't really great for making components for others? It doesn't get you out of the work of documenting them, for example, which is already done with canned component libraries. It certainly puts all the fixes back on you.

In my experience, Lit is terrific for green sheet projects and ones where you can keep everything in-house. But there is no "Lit community" or resources for people getting into it who want a jump start. And no great tutorial doc.

Unsurprisingly, you don't see Lit discussed too much anywhere!


Can't speak for the Lit framework, but never had any issues with lit-html or it's typescript defs, it's been rock solid.


I'm in the same boat.

I don't use lit-element, it's too heavy for me.

lit-html, on the other hand, is wonderful and rock solid.

I typically do light dom components, rendered with lit-html. Simple classes that extend HTMLElement.

When I want reactive style, I add setters that call render(). When I want imperative, I add class functions.

All my components generally take care of themselves and are mostly encapsulated, they'll generally have a init() method that loads the data they need, and calls a setter which kicks off the render cycle.

Alternately, data will be passed from a parent component via a property, and that'll also kick off the render cycle.

In many cases I do a combination of the two in order to support deep linking.

I'll mix and match design systems sometimes, depending on the payload weight. Ionic, shoelace, etc...

The Vaadin router ties everything together beautifully.

I also have a small state utility called ApplicationState[1] that I use for the edge case of cross-component communication and triggering. It provides a graph-based approach to notifications/state change.

I've been using this approach for several years with success, with deeply complex and large applications and small lightweight tiny footprint apps.

[1] https://claytongulick.github.io/applicationstate/


npm init @open-wc is a really nice starting point for Lit also mentioned here https://lit.dev/docs/tools/starter-kits/


> This article is mostly about switching from React to Lit.

I'll freely admit I'm a backend guy and don't know much about JavaScript frameworks, but the author emphasizes they didn't use Lit, just lit-html, and for the same reasons they didn't use React.

Is lit-html really such a huge portion of Lit that you disagree with their own assessment of what they've done?


They combine lit-html with a "basic scheduler" that they've written themselves. I'm guessing that's intended as a replacement for React, but it could easily be seen as a replacement for Lit, which offers "reactive properties" too.

I think how they gloss over the "we'll just write a library to handle component rendering, lifecycle and state" portion as a "basic scheduler" is a bit disingenuous. The author even mentions they are essentially recreating some features of React, but felt it was worth the tradeoff.


There is no doubt that, when using Lit, you're going to re-write portions of some existing framework. That's the big selling point: You're going to write them your way, and only the ones you need. Instead of inheriting and learning React (or Angular, or Vue), you decide what syntax and behavior your components will have -- all the way down to "bare metal" of when and if they render and with what contents or results. None of this is specified by Lit so you will be re-writing those pre-fab aspects of any canned framework.

You'll also be writing any kind of routing or other validation tools that you need. Which is actually glorious! You get to make one that's small and easy to keep in your own head, yet flexible enough to be extended and expanded in any way that you can imagine.

There isn't a React component that would have helped me build this game[0], other than very basic stuff like buttons. But with Lit, I could write components all they way down to SVG graphical elements and create all kinds of new behaviors that React doesn't understand.

[0] https://hexxedgame.com (100% Lit/TS)


> create all kinds of new behaviors that React doesn't understand

Care to expand? (I'm working on SVG-as-React-component stuff.)


Sure! What I mean is that, since the web components are bare metal, they can be very specific to my game. I have SVG components that return graphics, change colors, move themselves around, etc. based on properties and state in the app. Because they aren't based on canned components, I don't have to worry about shoehorning what I want into a React component that's really made for something like text or a dropdown, etc.


The section about trusting dependencies, the scenario where they go away, version churn etc doesn't resonate with me in regards to react.

I don't know any project in JS-land that is more serious about semver, backwards compatibility and reliable upgrades than react. If facebook dropped the project tomorrow, Vercel alone could probably continue to maintain it well.


Not only that, but so many strong engineering orgs build on React that I can't imagine it degrading very soon. Even if the top contributors left, Facebook imploded, and Airbnb disappeared, I'm quite certain there would be a crowdsourced effort to rescue and maintain the framework.


There’s even preact which is similar to react but a different org.


Both React and Lit's approach (that requires schedulers and user uncontrolled updates) are completely unnecessary for most if not all of the applications currently using React and I bet nobody even knows why they exist.

Facebook made React like this because of these requirements: they wanted their chat application that requires various real time small updates to multiple parts of the page to run quickly where a wipe and rerender approach is too slow, while being declarative because their constantly rotating staff had trouble writing it imperatively.

To meet this requirement you need:

a constantly revolving staff that are of varying degrees of competence and can't write non-buggy imperative code in the few situations you can't just wipe and re-render

a situation in your application where wipe and re-render is too slow, AND the situation is too complex to hand-write the individual updates manually

The other decision React made that was wrong was the need for JSX. They decided on JSX because they made a mistake many people make when just using the pure JavaScript API for creating components - they tried to make it nested like html using a fluent/chained call approach. As it turns out, trying to keep the nested HTML structure is not necessary for readability.

My library is github.com/thebinarysearchtree/artwork

After using it, it makes React look like SOAP vs JSON. It has less code, runs as fast as you can get, and everything is in your control because it is just web components with some functions to handle the repetitive parts.


Would love to see some comparison between yours and React, Svelte, Riot, Angular and Vue (or others)


For comparison, just read this: https://mithril.js.org/framework-comparison.html

Personally I prefer mithril or Soild over all other front-end framework. They light and fast. And Mithril author had in depth knowelge of the other frameworks.


This actually looks really nice


The author makes some fair points but I also think part of it is learning. It sounds like they had finished learning React and the ecosystem and all that was left was finding React bugs, and occasionally identifying ways to work around React's way of doing things. While they are still at a stage of learning Web APIs which means exciting discoveries.


Yeah agreed. The arc of learning seems to be…

This is interesting -> this is the best thing in the world -> here’s how this could be better

The “use the platform” people have been making this case for web components for at least 5 years now. The reality is WC will take off when and if they are a better alternative and even then they’ll need to be paired with some sort of framework. They may even make their way into React one day.

The only thing that bugs me about these takes is React is using the platform. It works great in all major browsers, it’s not some extension like Flash. It’s the platform.


React very much feels like its own platform to me - having its own browser tools to debug it is a dead giveaway.


I think it feels that way because it’s a bit of a paradigm shift in terms of the way we think about building user interfaces, but the reality is its just javascript running in a browser. I’ve been writing react over 10 years and used to devtools just a handful of times. They’re by no means necessary. I used to use an extension for jQuery to quickly find css selectors. Nobody was saying we weren’t using the platform then. It’s just a strange form of posturing from web component enthusiasts who are frustrated they aren’t taking off. And these enthusiasts are 99% Google employees who work on web components.


Yes react is an odd one to me. I prefer to program in a somewhat functional matter - separating pure code from things that mutate state, or render things to the screen. React pushes me away from that, instead encouraging me to mix state, rendering and templates all in the same part of the code, though they do provide a functional facade.


> "...and used to devtools just a handful of times."

How do you debug?


React dev tools, specifically. Of course I (and GP, assumedly) uses the browser dev tools. I don't find the React dev tools very useful.


Even on large web apps I almost never reach for the react or redux specific dev tools. Just the normal debugger is more than sufficient.


Then react + mobx also requires you to use mobx's browser tools to debug it.

Note: I say this as somebody who really rather loves react+mobx - but you're not wrong about the trade-off.


It seems that the author switched from Facebook's React to [his employer] Google's [Lit](lit.dev), and subsequently wrote a blog post in praise of the hand that feeds.

> Replacing lit-html would be an undertaking but much less so than replacing React: it’s used in our codebase purely for having our components (re)-render HTML.

That's high praise. I might take a second look at Lit and style it facilitates.


I'm moving towards vanilla JavaScript for my platform, and one of the things that I've discovered is that if you have a reactive data source then you don't need a lot of framework. Granted, I'm taking advantage that the core platform is much more stable than a decade ago.


What is a reactive data source?


To me a reactive data source would be something like Asana, Trello, Teamwork or on an ecommerce site it could be the cart widget. Basically any type of data that needs to react without requiring a page reload or any data source that needs to sync with another users inputs in real time.


RxJS aka the reason so many websites take 100MB of memory nowadays

Don't use it


It fairness you can do reactive data without RxJS. For example by using the vanilla web socket API. Agree that RxJS is best avoided though.


You can react to state changes with an astonishingly small amount of code with JS [0]

[0]: https://github.com/curlywurlycraig/vdom-util/blob/master/src...


Link doesn't work for me. 404s


Apologies, should be good now.


I got into RxJS cause I had to deal with an Angular project a few months ago, what's wrong with it?


A data source that you subscribe to and get a stream of updates. I'm building https://www.adama-platform.com/


I imagine a webhook source could be a reactive data source or any stream based API


Article makes a variety of already well understood points, but only briefly touches on the most interesting one (from my perspective): durability.

If the thing you're integrating is an evolving, improving moving target, and it's coming out of a team of only a handful of people, double any visible costs associated with your application for the sucker who must build it in 2 years time to add some new feature. It is possible to build a strong and easy to communicate case for avoiding frameworks using long term maintenance costs as the basis.

jQuery was actually pretty good at this, it only had one big flag day that I can remember. In that sense, jQuery was much closer to what you get for free working directly against the platform interfaces. Deprecation cycles are much, much longer, and burden of proof much higher for new features in the browser than pretty much any third party framework.

Somewhere here on the thread there was slander directed at Closure Library / Compiler. In this context, that is so totally tone-deaf, Closure Compiler/Library projects from 2010 still build with little to no changes today (based on local experience). I can't say the same for any alternative I have used in the past decade.


> but only briefly touches on the most interesting one (from my perspective): durability

React is over 10 years old and is backwards compatible probably all the way back to its 0.x versions.

Web Components have already deprecated and removed v0 of Custom Elements, and deprecated HTML Imports. On framework/library side: Polymer 1 wasn't compatible with Polymer 2 IIRC, and then Polymer was scrapped and discontinued in favor of lit.

React is a surprisingly safe bet for durability.


Really enjoyed this article. Web components seem promising, I played around with them a bit but I found it difficult dealing with global styling (ie, how do I make my component have the same colour scheme as everything else?).

Probably worth looking into again.

I also concur with the author about lit-html. It does one thing and does it really well, easy to understand, and no transpiling needed. Can't recommend it enough for generating dynamic html client side.


I've come to the conclusion that web components (with or without shadow roots) are not the best "elementary particle" to build a webapp out of. Most of the time you want simple divs and sometimes you want custom-tag. The important thing is to have a setup where you can quickly promote a component into a web component proper. I think solid.js has a nice solution this, where you just call a function that wraps the component into a web compoent and registers a tag for it.

One issue I have with lit is that it just forces you to turn everything into a web component instead of a carefully deliberated choice.


What's the threshold for you, where something needs to be a web component?

Honestly I just like the idea of making my own HTML tags and being able to do more with markup.


I'm thinking of things that satisfy these three criteria

1. Need to be configurable

2. Are meant to be used many times through an application

3. Are not easily built using regular html

For point one, take a loot at input[type="text"] html5 elements for instance. Placeholders, validation, size, stylability, errors.

Similarly, the video tag. Volume, play pause, size, quality, playback speed, compatible formats, much more.

For point two and three, you could for instance make a Login component, to encapsulate your authentication form into a component, but this is easily achieved using regular html forms. Also, you're most likely only going to use it once or twice.

So what are good examples?

A sparkline component, this is a type of an inline graph.

A markdown or html editor component.

Custom interaction or input components. Consider for instance where you're working on an audio mixing application. A rotatableKnob element is an elementary input here.


Only web components if you don't control the rest of the page, like someone embedding your component on their page, but I would still give them the control to name the component. That is a lot of work just so you can write my-tag instead of .className in your css file. I think the react way of styling each component inline is the way to go.


If you’re using a shadow root, look into CSS Custom Properties which poke through it and the HTML part attribute as well as its corresponding CSS :part() selector.


Reading the MDN documentation for parts, how are they different from classes?


They are both DOMTokenLists so parts look a lot like classes. The difference is parts are used in a shadow root to expose internal elements for styling. I’ve written a bit about CSS parts here: https://www.abeautifulsite.net/posts/when-to-create-css-part...


Tried Lit and StencilJS.

They are both forcing the usage of custom events to dispatch functions and share data between components. It's horribly unergonomic. Using the DOM with event bubbling and capturing feels really bad.

Orchestrating rendering is a mess.

The Shadow DOM and templates don't really solve any issues that aren't already solved with things like CSS modules for style scoping and even using element cloning is faster than templating.

The only thing they have going for it is that they're a nice way to share 3rd party components as an alternative to iframes or JS library API which targets a DOM node with a parameter.

And you can use any small framework like Preact, Svelte or SolidJS and wrap it with a web component.


So what do you do? Hand-craft Web Components?


I avoid using them, except when having to expose a component to a third party, if they _really_ want the ergonomics of using WCs.

Then I'd use something like https://github.com/preactjs/preact-custom-element, https://stenciljs.com/docs/custom-elements or https://github.com/solidjs/solid/tree/main/packages/solid-el....

As far as I see, there is nothing that WCs provide which isn't already solved, in a better way, both for devs and users.

And making a framework that use custom elements and shadow DOM for component-based logic and encapsulation seems like a purely philosophical approach to adhere to some vision of "platform purity".


In Lit, yes. It's hand-crafted web components with support for one-way data binding by parameter passing. Any other updates are by event notifications, as the commenter said.


Ah thanks for clarifying, it sounded like you wouldn't recommend either Lit or Stencil.


Sorry if I wasn't clear. I'm a huge fan of Lit! It gives you the freedom to make your own framework -- the parts you need. I respect the OP's comment and our difference of opinion, which is why I didn't reply negatively to it.


The rendering part resonate with me. I've tried in some side projects SolidJS framework and I really enjoy that the rendering of each component occurs once! Easier to not fall into some traps that React has.


> Easier to not fall into some traps that React has.

Honestly once you get used to it, it becomes second nature... For me at least.

One piece of advice I would give is to not try to ram the hooks use-case into things. It becomes especially annoying when you're dealing with asynchronous values, where you need to deal with 'null' and friends. Sometimes some imperative code in useEffect is simpler to read and easier to maintain; it's fine to step out of the paradigm for some things.


This reminds me of those posts like "Flask is better than Django". Sure, if you want to reinvent 90% of what's given to you for free with the bigger framework.


It’s bizarre to see the author waxing poetic about the small size of lit-html when it’s actually no smaller than Preact.


FWIW preact is 4kb minzipped (+ 700 bytes for htm package templating) while lit-html is 3.3kb minzipped.

Author also talks a lot about the issues with losing control of the component model when using preact


I admit I don't really understand the web components/cusotm elements "story". (I'm not even totally sure the right terminology, or what OP is talking about specifically).

Are these now useable on any contemporary browser? Or do you use some kind of polyfill? Anyone have a good from-zero tutorial for the approach OP is talking about?


Yes, they are usable without polyfills in any modern browser. The general idea is that you can register new element types whose behavior is defined in JavaScript classes. They interact with the rest of the DOM in the same way other HTML elements do: by emitting and handling events.

They can also maintain a “shadow DOM” with its own HTML subtree and CSS scope, so that you can make complex elements whose internal state is encapsulated from the rest of the DOM.


Hi. Sorry I couldn't parse that without a specific example. In which typical use cases should I create new element types?


This might be a good introduction from the Lit team themselves to see what this looks like in practice https://youtu.be/QBa1_QQnRcs


Whenever you'd usually create a new component in React.


I wish I didn’t say this but I just hate using React now. What was once simple is becoming more and more complex and I wish I had just stuck to a more batteries included framework like Angular/Vue/Svelte but the time has passed now. I’m just glad I don’t have to work on Frontend anymore.


I mean it seems you don't really like Frontend — not specifically React


I use plain JS, couple of libs and web components for business front ends. Works like a charm. Never needed React. It was created by FB to solve FB problems. Being small company this React approach to me it is just plain overhead.


In my projects I use cycle.js/snabbdom and I'm already following many suggestion of the article (es. form data). My next goal would be to discard snabbdom (and virtualdom) and use custom elements. For that I'm evaluating a library like https://github.com/WebReflection/uhtml and all it's ecosystem of utility


Everything on the web "uses the platform". There's no other way to get content into the browser.

Web Components are just a part of that platform, and very badly designed at that. A lot of the platform around them now exists only to patch holes in them (like form participation) and to solve the problems they introduced.

And since they are now a part of the platform, they poison everything like upcoming CSS scoping which instead of being a straightforward thing now has to account for all the web component insanity.

Edit. There also so many thing wrong in the article that argh.

"We don't need React and dependencies"... and then talks about lit-html which is a small framework with custom syntax and constraints on how you can use tagged literals.

"Easily replaceable dependencies"... and again talks about lit-html which is a fully incompatible replacement for Polymer. I wonder how folks that used polymer (Youtube) feel about "easy replacements".

"Can't control rendering with React" and talks about Web Components which literally give you no control over when a component can be rendered, don't have lazy loading, cannot subclass SVG or embed partial SVG etc.

And so on and so on...


> talks about lit-html which is a fully incompatible replacement for Polymer.

lit-html is completely different from web components and not meant to replace Polymer. lit-html is a library that just handles rendering and lit-element, which is meant to replace polymer uses lit-html as its renderer to make web coponents.


Semantics. If you go to Polymer website, it says this: "The Polymer library is in maintenance mode. For new development, we recommend Lit", and it links to what literally everyone I've seen calls lit-html (because that's how it started).

React is also just a library that handles rendering. But sure, "it's different".


Come on over rovers: https://github.com/cheatcode/joystick.

I promise you'll love it if you're switching from React (pure HTML, CSS, and JavaScript w/ minimal abstraction). And it's full-stack so no more stitching together frankenstacks. Good ol' isomorphic JS for devs who value their time/productivity.


Hard to say it's a good sell coming from React when the component API has been twice-replaced by better options in the React world. This looks awfully tedious to use.


Tedious? It's as straightforward as you can get (by design). React has devolved into an utter mess of ambiguous patterns and unnecessary abstractions that make the work far more difficult than it needs to be.


Few things that annoy me about react are mostly minor personal missed details like stale state in websockets, sometimes asynchronous state updates/wrong order; things you expect to work in a certain way but don't. Then it's like "you should use a [use]Reducer for that". Generally I like react/my go to. Just sometimes it does things not intuitive to me.


I think React is great. In Some instances of useEffect can seem inscrutable. I believe svelte is a great counter to a lot of the ceremony in React and I see it as the most compelling “framework” available. I sorta miss JSX with it but it’s not that important after a while. I find all the tech and rhetoric that comes from Google Dev Rel people (excluding a few gems) to be either pretty damn good but evangelized distastefully or just straight up incoherent. I find everything thing with web components and shadow dom and all that abhorrent. Yeah it’s the “platform” but the APIs are super complex, convoluted and filled with caveats all to not use a framework. I also believe the narrative that big JS bundles are ruining the web is a diversion. Google, and more specifically, monetization and advertising is ruining the web directly. Large JS bundles are secondary. Advertising and ad revenue ruined the web before the much aligned SPA.


The problem with Web Components is it's slower than React or other vDOM implementations. Also everything is a string. To re-render, you have to manipulate the innerHTML--usually replacing the string every update. To pass a prop to a component in a modular way, you have to pass a string attribute (e.g. something like <my-component my-attribute="[1,2,3]"/>). Even though v8 is extremely fast at string operations, it's just not a good practice and doesn't scale.

W3C standardized Web Components before React existed and took off, unfortunately. I expect the next standard to just be React itself (or a barebones version that the library can build on top of), patent licenses permitting. I'm pretty sure as a C++ precompile, it would be unstoppable and end the debate for good.


Every real world use of Web Components that I’ve seen uses <template> elements and/or imperative DOM methods to implement rerendering. These are blazing fast and exactly what React uses. It’s possible to build a slow app using Web Components, but that’s true of every library, including React.


Same here; I suspect they've mixed up defining the component (where some examples do use innerHTML) and using the component (which don't).


> Web Components is it's slower than React or other vDOM implementations

> To re-render, you have to manipulate the innerHTML--usually replacing the string every update

"Usually" is relative, I guess, but nothing's stopping you from using the imperative DOM APIs to update the component's contents; I daresay this would be the typical thing to do. These APIs will be just as performant as anything else out there. What you're really giving up, then, is the reactive programming model. Web Components are just a way of modularizing things; they have nothing to say about how you update the DOM (for better and worse).

You are right (I think) that there's no good way around converting attributes to and from strings, though the performance overhead there should be minuscule in most cases. The bigger problems with that are a) some data (like functions) can't be serialized at all, and b) it leaves a lot of room for passing invalid values


You can use DOM node properties instead of attributes, when working with custom elements from JS. No seraialization/deserialization to/from string there.


If you're using a framework like lit-html as the author recommends, it will replace the string every update. Most people will prefer that way since it's more ergonomic and similar to React. You could do imperative DOM updates, but that'd be like going back in time to jQuery.


This is false. It does not replace the entire string, but uses a template literal to identify which changes need to be made before selectively updating the DOM.

This video is a few years old, but the core concepts remain the same.

https://m.youtube.com/watch?v=Io6JjgckHbg


Wow, that's a pretty compelling video. I guess they all are, but I like the use of modern web standards.


This simply isn't true. Tagged template literals are not string concatenation. Also any "thin layer" of tooling on top of vanilla web components (like Lit) is entirely capable of passing complex objects as props. String-only "props" are only the case for literal HTML attributes in your source HTML—and even then you can embed JSON in an attribute and get a real parsed object within the component.


> Tagged template literals are not string concatenation

They are not concatenation by themselves. But for them to be useful, you will end up doing a lot of it because there's nothing else to do with strings than parse (often with regexps [1]) and concatenate [2] the strings. And then you dump the concatenated string into the DOM using `.innerHtml` [3]

There's no magic.

[1] https://github.com/lit/lit/blob/main/packages/lit-html/src/l...

[2] https://github.com/lit/lit/blob/main/packages/lit-html/src/l... and https://github.com/lit/lit/blob/main/packages/lit-html/src/l... and so on.

[3] https://github.com/lit/lit/blob/main/packages/lit-html/src/l...


I use Lit every day and I have no idea what you're talking about.

Any property can be a full JS object. When the property is changed, it is re-rendered in your component. I have never touched innerHtml and my Lit apps pass and render all kinds of stuff into html`` tagged templates.

It's really pure magic because you can freely mix regular old HTML and regular attributes with dynamic data and data binding. There's more than one way to write anything which gives you great flexibility. I adore tagged templates, and they work for CSS and SVG, too.


> I use Lit every day and I have no idea what you're talking about.

I'm talking about how lit is implemented internally and that's why I provided links to relevant parts of lit's code.

People having no idea how things work is the bane of our industry. And that's why we have objectively false statements like "regular old HTML and regular attributes with dynamic data and data binding".

Lit is almost as far from "regular old HTML" as React's JSX is: lit is a HTML-like DSL that even has constraints on how you use tagged literals themselves.

E.g. `<${tagName}></${tagName}>` is a valid tagged literal and it's invalid in lit.[1]

> they work for CSS and SVG, too.

If lit lets you mix SVG with custom elements, they don't really use custom elements. See discussion https://twitter.com/Rich_Harris/status/1198339672361119745?s...

[1] https://lit.dev/docs/templates/expressions/#invalid-location...


I do understand that string concatenation and DOM rewrites are happening under the hood. How could they not be? But the point of using an abstraction like Lit is that I don't have to worry about that part.

Are you suggesting that Lit is updating .innerHtml when it doesn't need to? And are you sure about that? Because that should be entirely under my control by setting properties or state of the component, not by Lit redrawing them willy-nilly.


> Are you suggesting that Lit is updating .innerHtml when it doesn't need to?

Literally nowhere did I say that. I was responding to a specific thing.


So what exactly is the complaint? You said that tagged templates require needless updates to .innerHtml and that "string concatenation" is the only thing they can do. Now we are agreeing that that's not true? :-)

How is it "objectively false" that Lit mixes regular HTML with data binding? That is exactly how it works. I have several Lit apps and they use regular HTML as well as custom components and both have access to Lit properties and state that are dynamic.

Are we talking at cross-purposes or are we trying to say the same thing two different ways? I use this tech every day and I feel like you're saying something about it that's not true -- or maybe I'm not understanding your view.


> You said that tagged templates require needless updates

I never said needless

> that "string concatenation" is the only thing they can do

It's not what "they" need to do. It's what you, or the library using them needs to do.

> Now we are agreeing that that's not true

If you invent something that I never said, then yes, we can both agree it's not true.

> How is it "objectively false" that Lit mixes regular HTML with data binding?

Once again that is not what I said. The objectively false statement is that it's "regular HTML". Lit is a HTML-like DSL because none of this is "regular HTML" because those attributes are invalid in regular HTML:

   html`<div ?hidden=${!show}></div>`

   html`<input .value=${value}>`

   html`<button @click=${this._clickHandler}>Go</button>`
And, on top of that it even adds constraints to tagged literals themselves:

   // Valid JS, and valid tagged literals. Invalid Lit

   <${tagName}></${tagName}>

> Are we talking at cross-purposes or are we trying to say the same thing two different ways

No. You're inventing things that I never said or implied and arguing against those inventions.


I still don't understand the objection. Your example of invalid Lit is something I would never write. Lit is perfectly helpful without it. What makes you say the .value and @click attributes are invalid? In some older HTML spec, you mean? They certainly work correctly in modern browsers.

You can definitely mix data binding with regular HTML. It might be "invalid" according to a spec that makes no difference. The point of all of this is to write apps that work and can be debugged.

What is the rallying cry against Lit, exactly?


> I still don't understand the objection.

Please re-read what I wrote in my very first comment

> What makes you say the .value and @click attributes are invalid?

Just checked the spec, you're right they are valid. Hm, I was sure they weren't. Won't dig through the history to see if this changed :)

However, "Authors must not use elements, attributes, or attribute values that are not permitted by this specification or other applicable specifications, as doing so makes it significantly harder for the language to be extended in the future.", https://html.spec.whatwg.org/multipage/dom.html#elements

So I'd say they are still not okay on existing HTML elements

> It might be "invalid" according to a spec that makes no difference.

That is a very bad stance to take. "Invalid to the spec, but who cares".

> What is the rallying cry against Lit, exactly?

There's no rallying cry against lit. Stop. Inventing. Words. And. Meanings. I. Never. Said. Or. Implied.

There's a single very literal comment I made with links to support that statement.

I'm out of this discussion. I have other things to do with my life than keep saying "I never said what you think I said" over, and over, and over again.


Right, all I'm saying is this is nothing intrinsic to the Web Components standard like the parent comment suggested. It's just one particular way you might use them.


> To pass a prop to a component in a modular way, you have to pass a string attribute

Is this actually how people pass props with Web Components? I've only used web components for a few years but I've always created a new instance of the class and I pass props using the constructor like:

`${new ExampleComponent(props)}`

Then in the constructor it's just this.state = {...this.state, ...props}


I’m not sure what you’re referring to here honestly but React is substantially behind web components in terms of every performance metric I can think of.

Boot up, runtime, micro benchmarks and at scale.


There's pointers here to interesting new things which I'll have to learn more about.

One of the core values for React for me is simply code structure - organising things into a hierarchy of elements seems to make sense - I found that hard to replicate when I once tried to build a vanilla js application.


I've really enjoyed using HTMX + Flask rendering HTML. It seems very ergonomic.


Few of the comments seem to focus on Lit, the "anti-framework," which is a very valid alternative.

In Lit, there are *no* pre-built components. No boxes or buttons or controls or routing. None. You make what you need.

Sounds daunting but, as the author points out, it frees you from cruft. You make only what you need. YOU design the API and syntax. And you add/remove whatever you want, whenever.

It would be hard for me to go back to canned components after Lit! Try the interactive tutorial:

https://lit.dev/tutorial/


> In our case, we still felt this decision was justified because we don't have to recreate a scheduler with all the complexity of React's; we can build a small, self-contained implementation that only implements what we need.

I wish there were more details about this. Implementing a small scheduler seems like a monumental task and I'd love to learn more about how to implement a base-case.


Not OP, but if you're building a small scheduler for batching changes, it should be pretty straightforward:

- `jobs` is an array of functions

- enqueue adds a job to `jobs` and starts running jobs if not running

- job running can be triggered by animation frames or setTimeout


Whenever I see a few internal apps made with React/Vue, they would miss super basic features such as highlight-able text or canonical permalinks.

It got me thinking, why these frameworks make simple things difficult?

Note that I am a backend/infra engineer (but I am able to build complex web app using jQuery back in the old days.) so I may be missing something here.


It's so strange to me how not using a framework is so often displayed as the "simple" solution. Not using a framework basically means using global, mutable state. This is maybe ok if all you need is one or two dropdowns. But anything further it isnt the way.


Aren't web components more of an addition to frameworks like Bootstrap than a React replacement?


Correct. The best use case for Web Components is to ship a bloat-free, reusable widget that doesn't care whether a consumer uses it with React, Vue, vanilla JS, Angular, etc.


I don't think so. I want to wrap webgl games with a custom component, and they share basic UI (which are also custom component dependencies). But none of this has anything to do with the larger web application (Angular) which manages much much more.

So stuck with iframes which although I can hide to some extent, are terrible.


But React does much much less than Angular.


I am not meaning it like that sorry that I did not explain well. There is a place for frameworks, and there is a place for "wrapping" non framework projects as a consumable. I am stuck here. I just meant that any framework or not is optional. React, Angular, Vue, Svelte or my funny.html should be able to use my "bundle" with options because the "bundle" doesn't care. That is where Custom Elements shine. It's just that from my perspective, Angular is the interface to the project.


Same here. I've been slowly getting rid of old React components on both SaaSHub & LibHunt. It's much easier to go forward and maintain your code when there's less JS complexity. For the curious ones - these are both Ruby on Rails based projects.


I have known about web components for some time but this article and the linked mdn guide have whet my appetite to maybe give it a try. Perhaps for my next bespoke small web app I can try my hand at web components rendered server side.


Server side rendering ftw


I have been waiting Server Side rendering to come back. I can't get my head around why build a normal brochure website using frontend frameworks.


All comments is about developer experience. What about user experience? I find many framework adding a lot of data, loading times, etc. for little gain for the user.


lit-html is great although at $DAYJOB we ran into some issues with missing linting on them.

We now use a JSX renderer that emits plain HTML strings.

You get all the ergonomics, the IDE assistance of checking for typos in your attributes, ensuring your closing tags line up, and webpack can flatten it back to plain HTML at compile-time for no run-time __jsx / React.createElement() calls.


Not sure if you're aware of it, or saying it's missing features, but lit-analyzer adds compile-time linting and type checking while lit-plugin provides IDE integration of the tool


Why lit-html over something like pug?


My ad for web components: btw I used to use react


> Firstly, because some people on the internet like to get angry over opinions that may not match their own, I want to make clear what this blog post is not:

> It is not a call for everyone to immediately drop React and move to web components.

> It is not a blog post declaring React “dead”, or the wrong choice for every project.

> It is not a blog post declaring web components the best solution to all projects.

You might want to consider how well the phrase, "Haters gonna hate," applies to your comment.


I was only joking that the title of the piece seemed slightly misleading/baiting! (but I also was not familiar with the term "using the platform")


React works well for simple, non-interactive components. Complex, interactive components are going to have state. Stateful components don't work so well in React. If you want to update props in a stateful component, the recommendation is to replace the component entirely by changing its key. At the point all of the benefits of React (preservation of selection, caret position, scroll position etc.) vanish. You might as well use vanilla js instead of React.

What does using Vanilla JS look like? Here's an example: https://github.com/wisercoder/eureka It uses two tiny 500-line libs. It uses TSX files, just like React. It has components, just like React. It doesn't have incremental screen update, but neither does React, if your components are interactive and stateful.


This is either a fundamental misunderstanding of React, or you're actually talking about a different library.

> React works well for simple, non-interactive components. Complex, interactive components are going to have state. Stateful components don't work so well in React

React components are designed with state in mind. When state changes, components passed that state in the form of props are re-rendered. Don't take my word for it though, from the first paragraph on the reactjs.org website; "React makes it painless to create interactive UIs. Design simple views for each state in your application, and React will efficiently update and render just the right components when your data changes."

> At the point all of the benefits of React (preservation of selection, caret position, scroll position etc.) vanish.

I have never heard these spouted as the benefits of React. The main fundamental philosophy of React is that only components that have state changing "react" to changes - in other words, the benefits of React are: no unnecessary re-rendering (hence the virtual DOM).

> If you want to update props in a stateful component, the recommendation is to replace the component entirely by changing its key

This part just threw me, if you are doing it this way - you are doing it wrong.


> When state changes, components passed that state in the form of props are re-rendered.

https://reactjs.org/blog/2018/06/07/you-probably-dont-need-d...

> I have never heard these spouted as the benefits of React.

You will find this if you read enough of React developers' blogs. JavaScript and DOM these days are fast enough that most pages can completely re-render the page and replace the whole DOM in one shot and you won't be able to tell the difference. The downside of doing that is that you lose focus, selection, scroll position, etc. So preserving those things is the benefit of React.


> Stateful components don't work so well in React. If you want to update props in a stateful component, the recommendation is to replace the component entirely by changing its key.

Do you have any concrete examples for this? I'm not sure I agree: I've made plenty of stateful components in React and they are just fine. If anything, they're a lot cleaner than what I could do in plain JavaScript, thanks to the framework.

Further, could you expand on what you mean re: recommending changing the key? I have never heard the React team suggesting to do this, although maybe I missed something in the documentation :-)


Wait isn't state the whole point of react? What level of interactivity are you talking about? State and props, that's it's thing: you can always update them.

I've only need the "change key to flush components" trick very few times, and most of those where rush fixes for bugs that had a better "doing it right" fix at a different level.


This is categorically false. If you want to update props in a stateful component it is exactly the same - just pass new props.

If you instead are talking about syncing props with state, there are ways to do this as well without changing the key, but this is considered an anti-pattern in the first place.

This sounds more like bashing react without even knowing it very well in the first place.


> This is categorically false. If you want to update props in a stateful component it is exactly the same - just pass new props.

https://reactjs.org/blog/2018/06/07/you-probably-dont-need-d...


This whole article is about an edge case where components have an internal "draft" state and an external "final" state, where both represent the exact same thing, and you want internal state to change when props change. This, in itself, would be an anti-pattern in any kind of programming, reactive or not.

What the author is trying to convey is that using getDerivedStateFromProps is not the best idea, and there are two simpler ways of doing it. The first solution (only keeping the state in one place) is the better one.

About the solution you're repeating all over the thread, anyone using React will notice that the "key" change solution you're talking about only works for trivial cases: it doesn't work in practice if you have more internal state in the component. It does work perfectly fine if you only have one single piece of internal data.

This is of course a past worry. All this is much simpler to solve by using Hooks.

But the important lesson here is maybe that one shouldn't judge whole Frameworks by advanced articles about edge cases written 4 years ago that require more experience with the framework than you have.


Nothing has changed in the last 4 years. Any time you have props and state, updating props is best done by replacing the component by changing the key. If you think hooks has fixed this, you are welcome to point to an article or code that demonstrates that.

All of this complexity is completely unwarranted, which is the point of the article at the subject of this thread. You can do it with simple vanilla js and it is easier. Javascript developers tend to buy into frameworks too easily without realizing the framework is making some things more complicated than without any framework.


> Any time you have props and state, updating props is best done by replacing the component by changing the key

No, it isn't. This is a ludicrous statement.

Replacing the key will RESET the internal state of children objects. Meaning you can't use this workaround for any component that has any kind of internal state does not come from props.

See for yourself: https://codesandbox.io/s/compassionate-williamson-qezsw5?fil...

On the other hand, it is completely trivial to update props that don't affect internal state. This article is only about updating props that affect internal state of components that don't have any other internal state.

> All of this complexity is completely unwarranted

No. All of this complexity you're complaining about exists for one very specific edge case, and this edge case exists in non-reactive frameworks too. You're just extrapolating the complexity of one single edge case to the whole framework.


If you pass new props, it swaps out the whole instance of the element in the document. Probably.


What's more, if you want it to only do this when passed new props and not at other times, you have to use things like React.memo:

"If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result."

https://reactjs.org/docs/react-api.html#reactmemo


But it doesn't do this is my whole point. React will not blow away the entire DOM in the document even if props change.

It will correctly keep your scroll position, caret position, etc. if you use React the way it's intended to be used, which is very easy to do and learn. Of course if you use the `key` prop to blow away the entire DOM with every change all these benefits are lost, but thats not react's fault, its your own.


> Stateful components don't work so well in React.

They work fine, though managing state outside of components via a state management library is common.

> If you want to update props in a stateful component, the recommendation is to replace the component entirely by changing its key.

Where do you find this recommendation? I’ve never seen anything like it, and keys are usually only used for repeating sets of elements, and you would generally only use a different key if something is not the same logical entity as the thing that previously had the key.

There might be some cases where you want to force a new rather than updated component by the kind of key manipulation you describe, but it's not the general case of prop updates for stateful components.

> It doesn't have incremental screen update, but neither does React, if your components are interactive and stateful.

React does have incremental updates for interactive, stateful components. You can deliberately negate it the way you’ve described, but you should not, generally.


> Where do you find this recommendation?

https://reactjs.org/blog/2018/06/07/you-probably-dont-need-d...

> keys are usually only used for repeating sets of elements

Not true at all!


From the blog you posted:

> In most cases, this is the best way to handle *state that needs to be reset*

You are talking about updating state, react author is talking about resetting. That's a big difference.




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

Search: