hckrnws
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*
(emphasis mine)
> That said, it only because available across all major browsers in March of 2022, and still isn't supported by some minor browsers.
`<dialog>` only got full compatibility with Firefox about two months ago with Firefox 141. Safari still doesn't support `closedby`.
Given that, I still regard `<dialog>` as experimental, and that'll remain the case as long as the "Baseline Widely available" label comes with an asterisk.
I can see from a new developer point of view, their frustration. Why aren’t things standard? Why not use builtin tags? Why this or that?
Valid questions we should all be asking. Sometimes, just because “that’s the way it was” doesn’t mean that’s the way it should be. Often times I find myself deleting code that is now more readily available as either part of the platform I’m on or part of the framework I’m using.
Your points are valid too, that they don’t know about the history that got us here and why it is the way it is but nevertheless we should all be asking ourselves daily, “do we still need this?” and trim the fat.
That's not what the article was about though. It wasn't only a complaint about not using built in niceties of the platform. It was an assertion that the reason we aren't is because of some kind of functional bro boogeyman.
It only became obvious at the end that the whole (WAY too long) article was just a giant troll to promote the author's personal pet technology (HTMLX). But it was a highly disingenuous one, because (as the poster above noted) it was giant straw man, not a legit critique.
I felt cheated just by having read the article: I'm all for a long and winding article that has something to say, but this one was telling a bad joke for WAY, WAY too many paragraphs.
The article does not go into the disadvantages of server-side rendering (or more specifically, fetching html from server). I am sure the author is well aware of the choice between client- and server-side rendering but skipped it and seems to present technology like htmlx as “solutions" to all the problems the article mentioned which is quite a stretch.
> Combined with React Hooks (which replaced stateful classes with functional composition), the ecosystem shifted decisively toward FP.
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.
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.
Personally I use filter and map (and others like .some, .every .flat and flatmap etc) all the time but I avoid reduce.
filter and map immediately tell me what the purpose of the loops are - filter things and transform things. A for loop does not do this.
To someone familiar with functional programming these are very normal and easier to read and grep than just a loop. In other words filter and map give additional context as to the intent of the loop, a bare for loop does not.
Not to mention this is not abnormal in languages outside of JS, even non-functional ones.
That said Ive seen too many convoluted uses of reduce that I just avoid it out of principle.
I like map() and filter() in Python, but unfortunately they’re 2nd class citizens compared to list comprehensions, which continue to get optimizations to further increase their speed.
I like comprehensions as well - and their syntax is quite readable - but I’d like for the two to be more at parity.
One of the main reasons that map() and filter() don’t get optimizations in Python is because they’re lazy.
It’s a lot easier to optimize comprehensions because you can make a lot more guarantees about what doesn’t happen between iterations: the outer stack doesn’t move, the outer scope can be treated as static for purposes of GC-ing its locals, various interpreter-internal checks for “am I in a new place/should I become aware of a new scope’s state?” can be skipped, the inner generator can use a simplified implementation since it never needs to work with manual send(), and so on.
Map/filter can’t take advantage of any of those assumptions; they have to support being passed around to different arbitrary places each time next() is called on them, and have to support infinite sequences (so do comprehensions technically, but the interpreter can assume infinite comprehensions will terminate in fairly short order via OOM lol).
That said, there are likely optimizations that could be applied for the common cases of “x = list(map(…))” and “for x in filter(…):” (in nongenerator functions) which allow optimizers to make more assumptions about the outer context staying static.
Yeah, the "problem" with reduce is that it can do anything, and so doesn't offer much over a traditional for loop with mutable local variables to accumulate into. Of course, if you can replace a reduce() with a filter and/or map or whatever (which more clearly states intent), by all means do so!
If you really need arbitrary computation, I'm not sure there's any real readability benefit to reduce() over local mutation (emphasis on local!). Sure, there's immutability and possibly some benefit to that if you want to prove your code is correct, but that's usually pretty marginal.
I think the reason for JS devs having "a weird relationship with 'FP'" is, that JS itself, in its nature, is not a particularly well suited language for FP. It has essential elements, that by their nature are global mutable state. For example timers and their ids.
Also weak typing plays into this. Some operations not immediately raising an error when the wrong type of thing is provided, is a recipe for bad experience when having point free style or semi point free style. If given the choice, at least one thing would be good to have, strong typing or static typing.
It's hard to talk in the abstract because obviously people can abuse any type of code feature, but I generally find chaining array methods, and equivalents like c# linq, much easier to read and understand than their looping equivalents.
The fact that you single out .reduce() here is really telling to me. .reduce() definitely has a learning curve to it, but once you're used to it the resulting code is generally much simpler and the immutability of it is much less error-prone. I personally expect JS devs to be on the far side of that learning curve, but there's always a debate about what it's reasonable to expect.
The wonderful thing about .reduce() is that it can compute literally anything. The problem with .reduce() is that it can compute literally anything. As for the rest of the morphism menagerie, I like being able to break up functions and pass intermediate results around. It's literally cut and paste with map/filter, with a loop it's rewriting. Yay composability.
That said, it's easy to get carried away, and some devs certainly do. I used to be one of those devs, but these days I sometimes just suck it up and use a local variable or two in a loop when the intent is perfectly clear and it's not leaking side effects outside of a narrow scope. But I'll be damned if I let anyone tell me to make imperative loops my only style or even my primary one.
> The fact that you single out .reduce() here is really telling to me. .reduce() definitely has a learning curve to it, but once you're used to it the resulting code is generally much simpler and the immutability of it is much less error-prone. I personally expect JS devs to be on the far side of that learning curve, but there's always a debate about what it's reasonable to expect.
Not only that, but the words that GP uses to single out .reduce() start with:
> I see so much convoluted code with arr.reduce() or many chained arr.map().filter().filter().map()
Which I do not doubt, but the point is diminished when one understands that a mapping of a filtering of a filtering of a mapping is itself a convoluted reduction. Just say that you prefer to read for-statements.
I’m fond of chained array methods, especially if the callbacks I pass are named functions - it can make for code that I find way more legible than for loops. But even with anonymous callbacks I’d rather do that ~90% of the time than use a for loop anyway.
> that would just be so much simpler and easier to read if it was a classic for-loop.
Only if that's how you were taught. For devs brought up in the FP manner, the for loop is as hard to grok as you find the chained stuff.
The Blub Paradox in action.
I have never, ever seen this. And I’ve worked next to some very FP-forward types and academic CS/abstract math background types who have vastly deeper knowledge of their fields than I ever will of mine.
Plenty of them don’t like imperative loops, sure. But I’ve never seen someone assert that a simple loop is not intelligible to them while chaining functions are.
On the other hand, from my experience, large development teams cannot write CSS at scale. "Writing clean CSS code" doesn't seem to be a skill that most (frontend) developers seem to value, so abstractions like CSS Modules (which is barely an abstraction - it's just compile-time BEM) and CSS-in-JS came up to manage complexity of both a large codebase and large team.
On the other hand, scaling CSS is fundamentally hard especially in a large team where it's more of an organizational problem.
It takes eternal vigilance to maintain it. Refactoring it is a huge feat. And when you want to modify or add a single component, it doesn't make sense to re-cred in the whole CSS apparatus, and it's not necessarily trivial to figure out where to make the CSS change, so CSS files tend to become append-only.
It's like how learning how to "write clean code" doesn't really change much about how hard it is to change large software systems over time in a large team.
These difficulties with CSS are how you know an org can't "design system".
You will see similar issues with their Word and PowerPoint, setting properties on elements instead of styles.
Yeah, most orgs use Figma as the source of truth, so if your designers don’t “design system”, it finds its way into the codebase.
Even if they do follow a design system, it tends to evolve over time, and it can be a bumpy road to reach a mature one.
> 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.
It's interesting; when I'm writing JS in an actual .js file, I do tend to use for loops. But when I'm writing JS at the (CLI or browser-dev-console) REPL, I'll always reach for arr.map().filter().filter().map().
When you're at a REPL, with its single-line/statement, expression-oriented evaluation, it's always easier / more intuitive to "build up" an expression by taking the last expression from history, adding one more transformation, and then evaluating the result again to see what it looks like now. And you don't really want side-effects, because you want to be able to keep testing the same original line vis-a-vis those modifications without "corrupting" any of the variables it's referencing. So REPL coding leads naturally to building up expressions as sequences pure-FP transforms.
Whereas, when you're iteratively modifying and running a script, with everything getting re-evaluated from the start each time, it's not only more intuitive to assign intermediate results to variables, but also "free" to have side-effect-y code that updates those variables. It's that context where for loops become more natural.
I bet that a lot of the chained-expression JS code you see out there was originally built up at a REPL, and then pasted into a file, without then "rephrasing" it to be more readable/maintainable in the context of a code file.
...though there's also just FP programmers who write JS (or more often TS) as if it were a pure-FP language — either literally making every variable const / using Object.freeze / using Readonly<T>, or just writing all their code as if they had done that — where for loops become almost irrelevant, because they're only really for plain iteration (they're not list comprehensions), and plain iteration has few uses if you're not going to do anything that produces side-effects.
Comment was deleted :(
Series (by Richard C. Waters) are a pipelining compiler for map/reduce.
I think it’s a far cry on the original author’s side to call the use of map().filter().map() an obsession with FP. Underscore.js simply provided super-useful functions over arrays and objects, which IMO makes for more legible code. Often times you can re-use filters with named functions. If you have multiple conditions for iteration exit, it’s clearer to chain filters than it is to have nested ifs or early exits in a for loop — it refactors better.
The real obsession with FP is the pervasive use of immutable state. But in apps, state must be effectively mutated, but now with a copy of the original immutable object. The FP obsession believes that this better than directly mutating the state each and every time.
Using these functions is not the problem. It's using them passed the point of being reasonable where I see the incorrectly placed obsession.
The benefit of FP has nothing to do with it being easier to read. FP is HARDER to read. The benefit of FP is modularity. Take your example:
arr.map().filter().filter().map()
Every step on that is a modular operation. const x = arr.map()
const y = x.filter()
const z = y.filter()
const d = z.map()
now I can easily do this: const x = (arr) => arr.map()
const y = (arr) => arr.filter()
const z = (arr) => arr.filter()
const d = (arr) => arr.map()
o = d(z(y(x(arr))))
This is the main reason why functional programming is elegant. It makes every corner of your program modular and solves the fundamental program of program organization and modularity.with a for loop it is easier to read initially but if that filter chain grows the functional approach will begin to be better.
Take an example of a for loop doing the same thing:
const acc = []
for (const x in arr) {
y = map1(x)
if(filter(y) {
continue
}
z = y
if(filter(z)) {
continue
}
d = map2(z)
acc.push(d)
}
Yes more readable but imagine if the logic gets even more complex. Then at scale functional will become more readable AND more modular. Modularity, however, is the main problem here. You cannot split or modularize that for loop.But I agree with you. Initially and not at scale, functional programming loses readability. Functional programming is harder to read because people think procedurally over functionally. We like numbered instructions or a todo list, not a series of composed function calls and thus from a general view point functional programming is harder to read than procedural programming. But this has never been the benefit of functional.
Functional programming is supposed to solve the modularity problem with how you organize programs to be reusable. Functional programming objectively does this while it is only subjectively considered less readable by the majority of people.
I don't actually have all that much of a problem with chaining fp-style functions, but I note that I see a fair bit of anonymous functions and excessive chaining where none of the benefits you point out are realised.
My actual problem is with bad reduce functions that try to shoehorn multiple things into one function and often break the core concept of functional programming by mutating the input arguments. It's that code that would just be better written as a normal loop.
> It's that code that would just be better written as a normal loop.
Have to disagree with your conclusion here. It's that code that should be rewritten, so it doesn't mutate the input arguments at all.
When I'm doing FP, rather than making a long chain, I assign at each step, then call the next one. As you've shown above. Sometimes I even comment on why the code is doing stuff.
Making it read as a list of steps, helps me understand what it's doing a little easier than that long chain.
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.
It seems to me, that many FE devs don't even know CSS these days. Rather just tack on some "ready" made component found on NPM or some component library. When it actually comes to using CSS to fix something about part of a page or part of a component, I often see non-responsive ways of doing that, badly tested across browsers, breaking at some width of the viewport, etc.
In my view CSS is essential. Not knowing CSS at least somewhat well is a huge obstacle in producing high quality frontend work. It's like being a carpenter, but simply not knowing one important aspect of wood, or not being able to use a specific tool to work with wood, lets say a tool to smooth surfaces. CSS is part of the medium you work with as a FE engineer. It is unfathomable to me, how a FE engineer can not know this stuff well. If some FE engineer is reading this, and feels some impostor syndrome: Yes, if you don't know your medium and tools as least in the basics, then you should feel like an impostor.
I see broken responsiveness very often. Of course in almost all websites, that rely on JS to display what is essentially a bunch of static texts.
If I was interviewing for a FE position, and really had to go through the circus of asking interviewees code questions, I would definitely include a minimum of CSS knowledge there. Basic things like how they would scope their CSS to specific elements or classes of elements and how they would prevent their styling to bleed into other stuff. Or how they would set up a theme with just CSS. Not questions expecting them to write CSS on a whiteboard, of course. Just testing their basic understanding.
I share this sentiment.
CSS modules are really enough - there's no need to overthink it any further.
I'm currently in a project where my first task, spanning several months, was to clean up after the previous guy. The main issues in styling were misguided attempts at sharing styles implemented via breaking encapsulation.
> I find this reluctance to enforcing guidelines weird
It's worse than that. All the hype in design has been about creating a global design language, and enforcing it over all your teams for more than a decade now. All the hype has been on centralizing the design team, moving it away from the developers for some years. All the hype has been on tools that claim to enable reusing and distributing that work...
And yet everything is done in a way that developers have to do everything themselves and don't get to coordinate with each other.
(Honestly, I'm settling on the opinion that non-developing application design is a scam all around.)
What I'm curious is why the platforms don't adapt to how the developers have found works best?
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?
> What I'm curious is why the platforms don't adapt to how the developers have found works best?
Here's my take:
- The web was visualized as a way to publish academic documents in a hyperlinked document system. Librarians and academics live in this world. We hear the word "semantic" from them a lot.
- The visual web was visualized as a way to publish documents that had a precise look. Graphic designers live in this world. They don't care about semantics. They do care about pixel perfect layouts and cool effects.
- The web app was visualized as a way to deliver software to users with lazy, "click link to install"-like behavior. What this crowd cares about is providing server functionality to users, and other concerns like semantics or pixel perfect are often secondary.
- The single page web app is also visualized as as a way to deliver software to users with lazy, "click link to install"-like behavior. They differ from the web app group in that they try to have more server functionality right in the client. Again semantics and pixel perfect are secondary. App complexity is a big problem that this group contends with, and this is what the article discusses.
Given these different ways of visualizing the web (and I'm sure I've left a few out), it's no wonder that we're stuck with the mess that is today's web development. The right solution is a sensible runtime for app development, that doesn't force you to render UI through the DOM and doesn't make it hard for you to get access to basic things like the local file system. We've known this forever (anyone remember Flash?).
WASM feels like it might finally allow app developers to do all of the software things that native platform developers get to do easily, and with the added bonus of strong sandboxing. It's early days yet, I think the "Ruby on Rails"-moment has not yet arrived there yet, i.e. a very popular, easy way for devs to create whatever app-de-jour everyone's excited about.
There are often a couple of barriers to this.
Firstly, you can’t break what is already there, so any evolution of the general platform often has to make wider guarantees than a single framework.
Adopting ideas from any single framework too quickly may put you in a worse position. A framework can evolve and choose when to break compatibility, a language or platform standard has a tougher job in that regard.
Some things that front end frameworks have settled on are now being looked at for standardisation, but I’m personally still wary about changing something like the ecmascript for. It would be an easier call if there were a standard library which simply needed an implementation, but we aren’t quite there yet.
WebComponents?
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…
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.
A lot of these are implementation details and not necessary for the abstraction to work. Preact doesn't use a synthetic event system for example
Is that true even when you want to use Preact without class based components?
Something about web development really does seem to break a person's ability to design/architect a proper event-driven, data-oriented UI.
I suspect there's a class of problems, front end development is one, ORM is another; where the problem itself is constrained in such a way that only shitty solutions exist.
ORM keeps sucking because RDBMSes simply don't operate on objects. You can either impose ill conceived object models on the database, or try and fail to capture the database's affordances in objects.
I don't have a theory on what's gone wrong with front-end development to cause its chronic disease, but it may simply be that HTML is a document markup language, and makes a questionable base for a user interface.
The name for those is "wicked problem". They usually appear when your problem statement is itself incoherent.
The entire thing about users interacting with data through computers is one of them. There are several inconsistent goals, like consistency is at odds with flexibility, and accessibility is at odds with security.
We have those tools that push the incoherence around, but they are always prone to collide somewhere.
> HTML is a document markup language
No it is a hypertext [1] markup language and it doesn't suck if you actually use it as such.
The problem is that we decided that <a> and <form> tags should be the only hypercontrols, only triggered by clicking on them. However, libraries like HTMX and Unpoly enhance HTML so that every element can act as a hypercontrol, responding to all kinds of events. This allows you to implement interactive features such as autocompletion, form validation and infinite scrolling without writing a single line of JavaScript.
> ORM keeps sucking because RDBMSes simply don't operate on objects
Have you read [2]? Modern SQL can return nested JSON. No ORM needed.
[1] https://htmx.org/essays/how-did-rest-come-to-mean-the-opposi...
[2] https://www.scattered-thoughts.net/writing/sql-needed-struct...
UI would be easy if its data wasn't just a cache.
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.
Bonsai is a frontend framework that models data as an explicit graph, separate from any “component hierarchy” or DOM structure. State can live anywhere in the application graph, whether or not it’s associated with DOM nodes, and you eliminate all of the “move this state to the parent to share it” ceremony by just having “components” return their views and “outputs” at the same time (if they want).
It’s pretty great and hard to imagine going back to a React-like component hierarchy.
Oh nice, it's ML style, like elm.
IMO/IME these problems have more to do with program organization rather than with any individual architecture.
To avoid it, funny enough, you have to take cues from functional programming, and you need strong, composable, primitives with succint interfaces (the opposite of shadcn). Even for visually combining and placing components, you need stateless layout components [1] that don't depend on anything and just render children a certain way. This way it's possible to have a very flat component hierarchy. The entire state-logic at the top-level doesn't hurt much anymore. Also, just props+events are enough, no need for Context, Redux or other tricks.
But if you go the "Clean Code" route and the main reason to have components is so so they're not too big, then you get deep hierarchies, prop-drilling becomes a big problem, and you need Context or state libraries specifically for inter-component communication.
This is a problem that I've seen come up time and time again not only in Frontend but also in desktop apps and in video games. And backends often have the luxury of having the entire state in the database, so it doesn't happen as often.
Of course the side effect of this is that you will end up with bigger components, and you need better abstractions, but IMO this is a small price to pay for having code that is easier to work with and doesn't need special ways for handling the data. Also this method tends to work better in bigger apps and people complain it's wasteful in smaller apps, so there's that too.
[1] In the design world this is often called Templates. https://atomicdesign.bradfrost.com/chapter-2/#templates It's interesting how this didn't catch among frontend devs. I remember "layouts" being a big part of WPF for example.
hard disagree.
With prop drilling how do you get the setter methods into C3? You have to prop drill all the way down.
Let's say I add a new component under C3 that has a side effect in some sister hierarchy under B. Then now suddenly in between and B and C3 and the other component I have to modify EVERYTHING to take that new change into account and these components now all have an extra prop that they don't intrinsically need but they keep in order to account for C3.
Because data is so intrinsically linked with components Every component between B and C3 now needs to be modified to prop drill when previously it wasn't needed.
that's because you are using react where every html element that does something dynamic is its own component.
when i use aurelia, then the whole page is one component and dynamic functionality in elements is achieved through bindings and functions that all share the data in the component. you can include other components, but you only do that where needed, and then passing data becomes a lot easier.
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 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.
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.
It's funny because React has both class-based components and more functional components.
more like ruined it
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?
Crafted by Rajat
Source Code