Think some of that (the dialog and friends) is the wrong way around: we wouldn’t have gotten all those nice DOM native components if libraries and frameworks hadn’t popularised them and driven adoption into the standards.
I am not sure I agree “the state of front end development” is due to “functional purism” either. React just provided a good abstraction that worked well for many people. It’s a meritocracy. If the abstraction that worked best (however we measure that) had been something more OOP then that would have been adopted.
Not sure I agree with the tone of the article, but I do find that Javascript developers have a weird relationship with "functional programming". I see so much convoluted code with arr.reduce() or many chained arr.map().filter().filter().map(), that would just be so much simpler and easier to read if it was a classic for-loop. I suggest this to people and they scoff at the thought of using a for-loop in Javascript.
> Consider the humble modal dialog. The web has <dialog>, a native element with built-in functionality. [...] Now observe what gets taught in tutorials, bootcamps, and popular React courses: build a modal with <div> elements
The dialog element is new! Only broadly supported since 2022. I find it hard to fault existing material not using it. Things like dialog, or a better select, are notable because they were lacking for so long.
I believe functional is the better (and best) paradigm we have right now. But the problem of why FE development still feels overcomplicated is because of a different reason.
There's a mismatch between how components are organized and how data flows through the front end application.
HTML is hierarchical. You have elements wrapping each other
A
└─ B
├─ C
│ ├─ C1
│ ├─ C2
│ │ ├─ C2a
│ │ └─ C2b
│ └─ C3
└─ D
├─ D1
├─ D2
│ ├─ D2a
│ └─ D2b
└─ D3
The issue here is that you can have something like D3 changing the state of an element like C3. So data must be artificially grafted on the above hierarchy to make it work.
D3 wants to send data to C3? Well then that means B must be the owner of the data. So data that feels like it must live on D3 well now you got to make it live on B which has nothing to do really with D3.
This has one primary problem.
It destroys modularity and much of the benefits of functional programming making it sort of useless in react. If you did prop drilling most things that have a path from B to C3 and B to D3 now are no longer modular and can ONLY be used in context of data related to D3. If you didn't use prop drilling and used some contextual way to pass the data the problem is still there because now components on that path have access to contextual data that's irrelevant. I mean for a time it may be safe... but some developer may break it and have a component access that context and suddenly modularity is broken... that component can now never be moved outside of the context.
Really... how data flows through your program is actually a separate graph structure, and how HTML elements are organized in your program is another separate graph structure we try to graft into the first one and that creates a mess.
I think the best way to do this, hasn't been done yet. But really side effects like clicks and button presses should NOT live on components. Components don't know about these things. That keeps the hierarchy and modularity of these html elements pure. A framework that's well designed needs to enforce this separation. I even think this can be done in a way that is STILL functional, but not react.
HTML and jquery were sort of going in this direction, but the problem was HTML lacked modularization because you couldn't group tags into a component. You also have timing issues and complexity with state that jquery didn't handle.
Overall I think the old style was actually better. It was a better overall direction that had tons of problems and I think those problems could have been solved if we continued in that direction. AND i feel we could have continued this direction with some sort of functional framework.
Imagine something similar to jquery but this jquery can only directly reference components on your component hierarchy and pass data directly to components (aka manipulate them). Context and state will also live on this jquery like framework and it will be handled in a similar way to how react handles it. While components themselves can wrap other components, and parameters that go into components can ONLY have default values. The components can never dynamically "call" other components with data and actually have anything truly dynamic going on.... only the jquery like framework can do this.
I don't disagree with the idea that people can be a little kooky about FP, but the idea that webapps are perfectly fine without modern front end approaches is a bit exaggerated. Managing UI state is much easier in the client - sure, if you don't have a stateful UI to begin with don't go build some JS SPA. But I've have been there done that with teams and companies that dislike JS then try to fake UI state back and forth from server to client, and it really sucks, overcomplicates stuff that should be simple.
This article started out interesting and then there were a series of baffling claims that... didn't quite make sense to me and feels like they are just trying to set up a straw man.
1. The author complains that React devs don't understand addEventListener when it is used and required reasonably often as far as I have seen?
Also, "Again: the web had this. The browser’s event system is fast, flexible, and well-understood. But it wasn’t controlled enough for the FP ideal of a closed system."
The stated purpose of the synthetic event system was to normalize differences in browser behavior back when React was created. It's not as necessary these days because browsers have gotten better, but saying it's about "FP Idealism" seems off.
2. The author complains about re-inventing the <dialog> element. This is valid, and new code should obviously use it. That said, it only became available across all major browsers in March of 2022, and still isn't supported by some minor browsers.
All of the popular component libraries were made before that, and thus ought to keep their JS implementation for backwards compat.
As far as tutorials, when I search "React dialog tutorial" the first result regrettably does show how to build your own, but the next two focus on using the built in element.
3. Then the author turns to customized select, and complains that JS frameworks don't support them. This would be valid but the very MDN article they link literally starts with:
> This article explains how to create fully-customized <select> elements using *experimental browser features*
No offense intended to the author, but this is the most bizarre list of points.
I also realise how weird it must be writing a personal blog article and then have random internet-folk dissecting it. Hope this doesn't dissuade any future articles.
I am a FE developer and I believe that we collectively have a loser's mentality when dealing with CSS.
In my mind, SCSS + CSS modules + maybe a processor tool is an rock solid and modern set of tech that produces excellent results and most importantly moves styling off the main thread. It makes sense to use it, but we don't. FE interviews even for senior+ roles are JS/React/system design questions. Nothing about CSS and I get it. Why interview for something you don't use internally?
I recently read something that stuck with me, which was about micro front ends but I think applies in more cases than this: "it doesn't solve a technical problem but an organizational one".
There was an excellent reddit discussion on the pros and cons of tailwind and it boiled down to "it's really hard to enforce CSS guidelines for teams of multiple people". Tech leads didn't want to monitor how 10 or 20 or 50+ different FE developers wrote CSS and opted for tailwind so that everyone wrote the same, even if that meant multiple inline classes pasted on each element. I find this reluctance to enforcing guidelines weird, considering at $WORK we have multiple confluence pages and internal documents about React and Javascript guidelines and I have seen similar documents in previous work places. Would it be really different to apply the same mental paradigm for CSS?
Of course, all this is under the hindsight knowledge that HTML and CSS have evolved in recent years to be truly powerful and versatile. I get the technical decision to go all in on JSS and React 5 years ago. I don't now.
Are there seriously devs that think FE code quality actually matters? It’s become so standardized and cookie cutter setting up this frameworks to actually work in development and production environments is ten times more difficult then recreating Facebook or Twitter. Who would build there career on this at this point?
Great article. I got off the webdev train just as Redux was coming out and never looked back. When my team lead decided to unilaterally replatform the app we maintained from Rails to NodeJS my professional life went from heaven to hell. Gone were the days of finishing our tasks for the week in two days and playing ping pong every day. Insult was added to injury when that team lead left halfway through.
The web had a golden age where it was understandable. The browsers' inconsistencies were mostly ironed out and you had references for what worked where. Flexbox was magic and you had shims to get it working where it wasn't yet supported. Web development was actually fun. When you solved problems, you were actually learning something, not just throwing stuff at the wall.
These web platforms gradually threw all that out. If you're a new engineer, realize that platform knowledge isn't real knowledge. Knowing React really well isn't a thing you can build a lasting career on. Your job is your job, but your education is your responsibility. If you don't want to be locked into an ecosystem, make sure you are constantly learning fundamentals.
These are things to be critical of after post-React in the explosion of complexity, but I don’t think this is FP’s fault. I did a lot of FP front-end in the actual FP languages—not languages cosplying FP with JS or TS—& these communities (Elm, PureScript, followed js_of_ocaml, Reason, & the things Haskell was trying at the time) were not jumping on these same bandwagons of complexity but hoping to wrangle in some of it, usually focused on how the view should be a declarative representation of the state while pushing side-effects to the edges. There wasn’t talks of making CSS too complex, hydration, et. al. That JS/TS crowd however…
Composition in React Hooks is closer to multiple inheritance in C++ (because it combines state and behavior from multiple components) than functional programming.
This is a very incorrect conclusion. Nothing about jquery prevented functional purity. If that's what you wanted, use it as such. Jquery just made browser differences much less of an issue and wrapped it in a nice way. The modern react stack is exactly what all the fp snobs raged against and they weren't wrong about it. Its been said before, there was jsf before react. Both are bad ideas. React has terrible performance is extremely heavyweight and ridiculous for what its used for. There's a reason there's a revolt nearly daily.
To me the major failing here was people over investing in faang thought leadership. Still haven't ever used react angular etc in a major project and gone wow this is great. JQuery got a lot closer. There were many other ideas coming forward around the time those frameworks came up, it was a fertileperiod for frontend. Sounds like we should cycle back.
If anything, jQuery allowed things to be more FP-oriented. I don't remember who said it, but "jQuery selectors are lenses for the DOM" is one of the better observations about jQuery I've read. A lot of jQuery is unnecessary in modern JS, but we still don't have those sweet selector semantics, and you're still expected to loop over everything by hand. And as a continuing middle finger to the DX, NodeLists don't even support the HOFs of the Array interface and have to be converted to arrays by hand.
Other commenters are criticizing details, but I really appreciate the OP trying to see the entire landscape. I agree with other commenters that ownership over code is a primary driver (at least for CSS style vs. javascript interaction).
Leaving aside details, it seems clear the javascript frameworks were ahead of the platform and had the perverse incentive of staying that way, which also took the pressure off browser developers (already slowed by inter/standards politics), resulting in a long historical period of dissonance.
By comparison, Java bytecode gave Scala and Kotlin instant access to the enterprise, and the JDK team responded with faster cycles and steady but measured incorporation of features, because they realized they needed something to get enterprise off Java 1.8 and into licensable VM's. Progress is slower in the enterprise, but the dissonance seems minimal.
> CSS cascades globally by design. Styles defined in one place affect elements everywhere, creating emergent patterns through specificity and inheritance.
I can’t be the only person who finds that this makes complex sites a nightmare to design? (Raise your hand if you’ve had to use `!important`)
Towards the end of the posting, it turns out this is a plug for HTMX.[1]
So, is HTMX any good? Do people use it?
The primary mechanism of HTMX seems to be that you click on something, which causes the server to return HTML which is then shoved into the current HTML at the selected point. Is that a good primitive?
I get the impression from the article the author may have meant declarative instead of functional programming. FP can be fully imperative. I often see developers interchange these terms improperly because there is some implicit narrow context that’s out of scope to the broader nature of the terms.
21 comments
[ 3.5 ms ] story [ 42.4 ms ] threadI am not sure I agree “the state of front end development” is due to “functional purism” either. React just provided a good abstraction that worked well for many people. It’s a meritocracy. If the abstraction that worked best (however we measure that) had been something more OOP then that would have been adopted.
> Consider the humble modal dialog. The web has <dialog>, a native element with built-in functionality. [...] Now observe what gets taught in tutorials, bootcamps, and popular React courses: build a modal with <div> elements
The dialog element is new! Only broadly supported since 2022. I find it hard to fault existing material not using it. Things like dialog, or a better select, are notable because they were lacking for so long.
There's a mismatch between how components are organized and how data flows through the front end application.
HTML is hierarchical. You have elements wrapping each other
The issue here is that you can have something like D3 changing the state of an element like C3. So data must be artificially grafted on the above hierarchy to make it work.D3 wants to send data to C3? Well then that means B must be the owner of the data. So data that feels like it must live on D3 well now you got to make it live on B which has nothing to do really with D3.
This has one primary problem.
It destroys modularity and much of the benefits of functional programming making it sort of useless in react. If you did prop drilling most things that have a path from B to C3 and B to D3 now are no longer modular and can ONLY be used in context of data related to D3. If you didn't use prop drilling and used some contextual way to pass the data the problem is still there because now components on that path have access to contextual data that's irrelevant. I mean for a time it may be safe... but some developer may break it and have a component access that context and suddenly modularity is broken... that component can now never be moved outside of the context.
Really... how data flows through your program is actually a separate graph structure, and how HTML elements are organized in your program is another separate graph structure we try to graft into the first one and that creates a mess.
I think the best way to do this, hasn't been done yet. But really side effects like clicks and button presses should NOT live on components. Components don't know about these things. That keeps the hierarchy and modularity of these html elements pure. A framework that's well designed needs to enforce this separation. I even think this can be done in a way that is STILL functional, but not react.
HTML and jquery were sort of going in this direction, but the problem was HTML lacked modularization because you couldn't group tags into a component. You also have timing issues and complexity with state that jquery didn't handle.
Overall I think the old style was actually better. It was a better overall direction that had tons of problems and I think those problems could have been solved if we continued in that direction. AND i feel we could have continued this direction with some sort of functional framework.
Imagine something similar to jquery but this jquery can only directly reference components on your component hierarchy and pass data directly to components (aka manipulate them). Context and state will also live on this jquery like framework and it will be handled in a similar way to how react handles it. While components themselves can wrap other components, and parameters that go into components can ONLY have default values. The components can never dynamically "call" other components with data and actually have anything truly dynamic going on.... only the jquery like framework can do this.
1. The author complains that React devs don't understand addEventListener when it is used and required reasonably often as far as I have seen?
Also, "Again: the web had this. The browser’s event system is fast, flexible, and well-understood. But it wasn’t controlled enough for the FP ideal of a closed system."
The stated purpose of the synthetic event system was to normalize differences in browser behavior back when React was created. It's not as necessary these days because browsers have gotten better, but saying it's about "FP Idealism" seems off.
2. The author complains about re-inventing the <dialog> element. This is valid, and new code should obviously use it. That said, it only became available across all major browsers in March of 2022, and still isn't supported by some minor browsers.
All of the popular component libraries were made before that, and thus ought to keep their JS implementation for backwards compat.
As far as tutorials, when I search "React dialog tutorial" the first result regrettably does show how to build your own, but the next two focus on using the built in element.
3. Then the author turns to customized select, and complains that JS frameworks don't support them. This would be valid but the very MDN article they link literally starts with:
> This article explains how to create fully-customized <select> elements using *experimental browser features*
(emphasis mine)
The developers look for ergonomics in maintaining the code base, that can scale to larger team and websites.
This requires a lot of customers JS framework code to offer, but in a sense, it's because the platform doesn't natively support it no.
Would there be ways to evolve the web platform to better align with the React style for example?
I also realise how weird it must be writing a personal blog article and then have random internet-folk dissecting it. Hope this doesn't dissuade any future articles.
In my mind, SCSS + CSS modules + maybe a processor tool is an rock solid and modern set of tech that produces excellent results and most importantly moves styling off the main thread. It makes sense to use it, but we don't. FE interviews even for senior+ roles are JS/React/system design questions. Nothing about CSS and I get it. Why interview for something you don't use internally?
I recently read something that stuck with me, which was about micro front ends but I think applies in more cases than this: "it doesn't solve a technical problem but an organizational one".
There was an excellent reddit discussion on the pros and cons of tailwind and it boiled down to "it's really hard to enforce CSS guidelines for teams of multiple people". Tech leads didn't want to monitor how 10 or 20 or 50+ different FE developers wrote CSS and opted for tailwind so that everyone wrote the same, even if that meant multiple inline classes pasted on each element. I find this reluctance to enforcing guidelines weird, considering at $WORK we have multiple confluence pages and internal documents about React and Javascript guidelines and I have seen similar documents in previous work places. Would it be really different to apply the same mental paradigm for CSS?
Of course, all this is under the hindsight knowledge that HTML and CSS have evolved in recent years to be truly powerful and versatile. I get the technical decision to go all in on JSS and React 5 years ago. I don't now.
The web had a golden age where it was understandable. The browsers' inconsistencies were mostly ironed out and you had references for what worked where. Flexbox was magic and you had shims to get it working where it wasn't yet supported. Web development was actually fun. When you solved problems, you were actually learning something, not just throwing stuff at the wall.
These web platforms gradually threw all that out. If you're a new engineer, realize that platform knowledge isn't real knowledge. Knowing React really well isn't a thing you can build a lasting career on. Your job is your job, but your education is your responsibility. If you don't want to be locked into an ecosystem, make sure you are constantly learning fundamentals.
React is the farthest thing from functional, see here: https://mckoder.medium.com/why-react-is-not-functional-b1ed1...
Composition in React Hooks is closer to multiple inheritance in C++ (because it combines state and behavior from multiple components) than functional programming.
To me the major failing here was people over investing in faang thought leadership. Still haven't ever used react angular etc in a major project and gone wow this is great. JQuery got a lot closer. There were many other ideas coming forward around the time those frameworks came up, it was a fertileperiod for frontend. Sounds like we should cycle back.
Leaving aside details, it seems clear the javascript frameworks were ahead of the platform and had the perverse incentive of staying that way, which also took the pressure off browser developers (already slowed by inter/standards politics), resulting in a long historical period of dissonance.
By comparison, Java bytecode gave Scala and Kotlin instant access to the enterprise, and the JDK team responded with faster cycles and steady but measured incorporation of features, because they realized they needed something to get enterprise off Java 1.8 and into licensable VM's. Progress is slower in the enterprise, but the dissonance seems minimal.
> CSS cascades globally by design. Styles defined in one place affect elements everywhere, creating emergent patterns through specificity and inheritance.
I can’t be the only person who finds that this makes complex sites a nightmare to design? (Raise your hand if you’ve had to use `!important`)
So, is HTMX any good? Do people use it?
The primary mechanism of HTMX seems to be that you click on something, which causes the server to return HTML which is then shoved into the current HTML at the selected point. Is that a good primitive?
[1] https://htmx.org/