Stateless components are a good idea, but their implementation as functions and hooks leaves any JS programmer not familiar with React scratching their head. Throwing Promises for Suspense is basically Algebraic Effects. Redux and a million other libraries tried to solve data management, none of them doing it in a classical K/V store. Now every app I touch I have to find its special version of reducers and selectors.
I like front end programming and Javascript overall. Components are a nice abstraction, and life cycle hooks make sense in real life contexts. But React reeks of developers who think they are too smart for their day job and want to redefine UI programming just to render a button with an event handler.
Given requirements that meant, to progress, they were going to need to either:
1) Tell devs that sometimes they would simply have to use classes/objects for some components, because certain performance enhancements or state-management would only be available there, or;
2) Partially re-implement objects with really bizarre declaration syntax, in a language that already has objects—shit, its functions are objects, and maybe it's changed but I read the hooks code when it was added and it was just some FIFO property/method queues, rather than tables, tied to a damn object representing your component in React's core state-machine;
They chose #2.
[EDIT] yes I'm aware that one reason they prominently gave for hooks was that inheritance hierarchies could cause problems in React codebases, but that seems woefully insufficient as a motivation for writing a crippled version of objects/classes that lack the features they had problems with, rather than just telling people "maybe stop hitting yourself?" and continuing to use what the language already provided, which everyone already understood.
All UIs need state. Yes state is bad in most cases and makes programming harder. No abstracting it into 4 different files doesn't make it any clearer.
There was an issue with composition in React. HOC didn't scale very well, and Inheritance is almost always Bad (TM). That said, I do think hooks were an esoteric choice versus a more explicit service registration/DI pattern.
Except it is not really functional. See:
https://mckoder.medium.com/why-react-is-not-functional-b1ed1...
The whole thing has been functional programming from the start, if you know what algebraic effects are then the functional underpinning should be obvious to you as well as anyone with the slightest brush with FP. Hell, the original React prototype was in Standard ML, later ported to OCaml and then JavaScript.
> Throwing Promises for Suspense is basically Algebraic Effects
The fact that you disregard Suspense as a head-scratching algebraic effect, instead of using simple "Promises" goes to show how much the JavaScript ecosystem seems to be about fooling people into doing functional programming without triggering their gut reaction of "FP is spooky unproven thing, but Node enterprise ready!".
Imagine for a second that a Promise's .then is called .bind, put it in a thunk if you want to be extra precise and tell me what it is. Hint: It starts with "M" and it's just a monoid in the category of endofunctors.
That's a lot of hot air. There is nothing functional about React. Algebraic effects represent impure behavior in a functional programming language, such as input and output, exceptions, nondeterminism etc. all treated in a generic way. Impure behavior, including algebraic effects, is best avoided in functional programming.
Sorry to post the link again, but please read this: https://mckoder.medium.com/why-react-is-not-functional-b1ed1...
I read the article FWIW, it didn't particularly convince me. I think even writing things in the style of functional programming, if that's what we want to call it, still makes it easier to reason about the code. Confining side effects to hooks also means there's only one place we have to reason about having non pure consequences.
let add (x: int) (y: int) : int =
print_string (Format.sprintf "x: %d, y: %d" x y);
x + y
This is a function. It's not pure. There is nothing that's stopping me from using it exactly the same way as a pure add implementation. OCaml is still a functional programming language. As said on Wikipedia: "Functional programming is sometimes treated as synonymous with purely functional programming, a subset of functional programming which treats all functions as deterministic mathematical functions, or pure functions.". Functional programming is not only purely functional programming.If you don't have a pure core then you are not using FP.
No, they don't really. Haskell programmers tend to program like that because monads are annoying to use everywhere in your application. But this is really just the hexagonal pattern in different clothes. DDD programmers care a lot about business logic, so the core is business logic. People that like pure functional programming care a lot about pure functions, so the core is pure functions. Some people even mix both (a good example of that is Doman Modeling Made Functional, the talk or the book). I guess people that care a lot about performance would put performance at the center, at the cost of purity and/or abstraction. Basically this whole pattern is a way to ask yourself "What are my values? What's my priority when I develop software?", and to make sure that it's at the litteral center of your application.
So again, you are mixing functional programming, "functional programmers" (which I don't think means anything), and people that value pure functional programming a lot.
Which brings us back to react. Is React functional? What does it means, to be functional? I can at least try see what people mean when they say "React is functional". There are probably multiple things: 1) React is more functional than its predecessors. 2) React share values with functional programming. These are a bit fuzzy, but we can try to answer them.
1) React is more functional than its predecessors: It's surely more functional than traditional vanilla JS, jQuery and Angular. I know that before React Backbone was popular, but I don't know anything about it, so maybe Backbone is even more functional than React, which would undermine this point. I may also have forgot some important development along the way (Ember ? Meteor? CoffeeScript? I wasn't into programming at that time so it's hard to judge the popularity/influence of everything). From what I know, I'd say it's a yes. At least in the most popular frameworks (Angular, React, Vue), React is the most functional.
2) React share values with functional programming. On the frontpage of React, we can see "Declarative: 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. Declarative views make your code more predictable and easier to debug.". That sounds a lot like what you can hear for some functional programming advocates. "Make the code declarative, be more productive, and the compiler will take care of the performance", in a way. Then there is "Component-Based: Build encapsulated components that manage their own state, then compose them to make complex UIs. Since component logic is written in JavaScript instead of templates, you can easily pass rich data through your app and keep state out of the DOM.". Making a complex UI by composing simple parts again sounds like composing functions in functional programming. "Encapsulated components that manage their own state" feels more like OO though. I can also add that the React community uses Redux a lot, which was inspired by Elm, which itself is clearly functional programming. I've heard that hooks are a way to get closer to functional programming, but I can't confirm this, as I haven't used them. As a conclusion, I'd say that yes, React share values with functional programming, though it doesn't strive for purity (in both senses of the word).
So, again, is React functional? Yes, I'd say it is. What does it mean to be functional? I think a good example here would be OCaml. OCaml is a functional programming language. OCaml also allows you to do imperative programming, or object-oriented programming. However, in the wild, most of the OCaml code you find is functional. How functional? That depends. For some people it will mean functions and data structures. For some it will be this with modules. For others, that will be monads. So in general, maybe a bit less functional than Haskell, but more functional than Python or Java. That's the same with React. When we say "React is functional", we mean "probably a bit less functional than Elm, but more functional than Angular and Vue".
You're using "functional" in a very specific way, which is usually covered by "pure" or "purely functional", which is unproductive to these kind of conversations.
What is the benefit of being functional?
If there is no benefit then this whole discussion is moot. If there is a benefit to FP that isn't easily achievable using other styles, then does React achieve that benefit by doing FP style?
Or is React leaning on the cachet of FP for marketing purposes?
For React, the idea is building the UI as a function of the state. The benefit is to make the code easier to understand, debug, test, etc. I don't think I have to discuss with your the benefits of pure functions.
> If there is a benefit to FP that isn't easily achievable using other styles, then does React achieve that benefit by doing FP style?
I think it does, partially. Though it isn't going as far as something like Elm.
> Or is React leaning on the cachet of FP for marketing purposes?
I would almost say the opposite, React succeeded at first because it didn't push too much the functional stuff. Elm went farther, and doesn't have the market share of React, because insisting too much on FP, especially at that time, would only scare away developers. If you start to go the FP path, at some point you realize that using JavaScript can't work, and you have to switch to something new. People have experience and huge codebases, so they don't want to switch. You can see the same with TypeScript. TypeScript succeeded because it embraced JavaScript, especially its flaws. That means that as standalone language, TypeScript isn't as good as it could be. But as an incremental improvement in the JavaScript ecosystem, it's good, very good.
To see what happens when you use FP for marketing purpose, you can take a look at ReScript, the current reincarnation of ReasonML.
> For React, the idea is building the UI as a function of the state
Well, if you have state you're already not functional.
Look, React does not have to be functional to be useful! Let's not misappropriate the FP label and apply it to a tech that is clearly not functional, misleading a whole generation of developers.
React is great, hooks are OK, but FP it is not!!
That's just wrong. State will exist, wether you like it or not, and you'll have to deal with it.
Again, you're using FP to say pure FP. Is Standard ML not functional according to you?
Yes, state will exist... in a thin outer layer. Pure core with a thin impure outer layer. If state is distributed throughout the entire program then it is not FP.
Reason has always felt weird and half-baked. It had all that nice syntactic sugar for the benefit of javascript developers — but in the middle of it, there was some OCaml ugliness, like different math operators for integers and floats, or special treatment of recursive functions. Plus a half-baked async story, or lack of unicode support. It was all very weird.
But in other areas: I understand Swift was a great marketing success, and it is heavily influenced by FP, right (I haven't used it personally, so don't know). And so was Kotlin?
From my limited exprience in Swift, it does have functional parts, although I don't know if that's the main focus of the language, or just a nice thing to have.
Kotlin seems a bit more functional than Java, although Java has been catching up recently (sealed classes, pattern matching, record).
This is unhelpful. I don’t know if I’ve ever encountered this attitude before, I’m enthusiastic about FP and I frequently direct people toward FP principles wherever I possibly can. Dissuading application of those principles in part because they’re not applied in (your view of) full is sending people in the wrong direction.
And you might not care, but I do: it’s also gatekeeping. Making people feel like what they’ve learned to make their code more functional, less side-effecting, and generally easier to reason about… making them feel like that’s not important progress they can value unless they share your knowledge and understanding of Category Theory or whatever is going to drive people away from what you want. And it’s going to drive marginalized people away most, probably from programming in general. That stinks.
The level of purity you’re demanding isn’t even claimed by most functional languages. And the ones which do use Monads as a sleight of hand to make the claim, but that’s plainly a useful fiction.
> This is unhelpful.
You have to care about purity. The benefits of FP hinges on this. Saying you don't care about purity is the same as saying you don't care about FP.
That doesn't mean that anything less than "perfect purity" is worthless. You have to always aim for purity, even if you don't always achieve it, because without it there is no FP.
This is more helpful. I’m not going to add my own unhelpful reaction to the rest of what you said, I think I already added more value above than I’m inclined to now.
If that's your definition, functional programs basically don't exist in the real world. Wikipedia (and I) don't agree with that [1], it specifically separates out pure FP [2].
[1] https://en.wikipedia.org/wiki/Functional_programming [2] https://en.wikipedia.org/wiki/Purely_functional_programming
The whole concept of React is to model the UI as a function of the state. React was first made in Standard ML (you don't really get more functional than this). Jordan Walke, the creator, went on to work on ReasonML, an hybrid between the OCaml and JavaScript ecosystems, to try to leverage the functional parts of OCaml.
> Impure behavior, including algebraic effects, is best avoided in functional programming.
This is wrong though. Functional programming doesn't shy away from impurity. Algebraic effects are a way to handle impurity, which is unavoidable.
Disagree. Functional programmers often speak of implementing programs with a pure core and a thin layer on the outside that handles effects. If you don't have a pure core then you are not using FP.
In FP as an umbrella, purity is not a hard requirement for the entire paradigm, only a predominantly pipeline oriented style based around expressions is (in contrast to, say, C, where one generally passes a pointer to the same state around to procedures that pick and choose what to modify in that state bag, as a series of statements). Common Lisp and OCaml are often cited as examples of functional languages that don't attempt to enforce purity guarantees even in terms of idiomatic usage, let alone at a compiler-enforced level.
Using higher order functions for, say, promises (remember, they're stateful!) doesn't mean you're not using functional programming, just like using Array.prototype.map doesn't mean you're not using OOP (it implements fluent interfaces, if you haven't noticed). It's the absence of functional tools/techniques that qualifies a program as not functional.
IMHO, the unfortunate situation is that most JS people don't understand there are different degrees of functional-ness and certain guarantees only exist within specific subsets (and React doesn't conform to that subset).
There are 3 benefits, mainly: (1) Ease of verification, (2) Parallelism and (3) Data-centric computation. (See article I linked for details.)
Of these, Parallelism doesn't work in JavaScript. Since JavaScript doesn't support lazy evaluation, data-centric computation doesn't work that well either. That leaves us with the first benefit alone. But ease of verification is reliant on pure functions. If functions aren't pure then it is just regular code that isn't necessarily easy or hard to verify.
React uses FP for a 4th benefit you won't find in any textbooks on FP: Marketing.
No offense, but your argument is kinda self-defeating if you are trying to claim that two out of the three purported benefits aren't even applicable (and I'd argue that even that first so called benefit doesn't have a great story in JS either).
Saying that verifiability is somehow intrinsically related to purity is IMHO making an overly broad generalization. You're starting from the premise that unit testing a pure function is easy, but that doesn't really generalize in any direction. Array.prototype.splice is not pure and yet it's trivially easy to test. Reasoning about the crashing potential of JS tail recursion is not easy even with purity guarantees. Large functional point-free compositions in JS have impenetrable stack traces. Valgrind et al exist so clearly it's possible to reason extensively about messy stateful things.
Different paradigms aren't oil-and-water and they don't have a monopoly on any given benefit, it's perfectly possible to mix and match features of various paradigms to achieve expressiveness, idiomaticness, predictability, etc.
[0] https://mckoder.medium.com/why-react-is-not-functional-b1ed1...
With reference to the article, it builds on top of authoritative articles (see References section at the bottom), so you don't have to take anything at face value!
You're right, I am indeed saying that verifiability is intrinsically related to purity. The concept of pure functions is at the core of FP. You take that core away and you no longer have the right to call your code FP.
Why is it important to label something as FP in any case? React is useful even if it is not functional. What I am opposed to is misappropriating the "FP" label for marketing purposes, by the React team.
Only in the subset that you consider canon, not generically for all FP. Wikipedia is quite authoritative, FWIW.
I agree that the React team has made some flat out wrong claims (e.g. incorrectly calling hooks pure at one point), but you're engaging in exactly the same sort of "marketing" you dislike, by biasedly claiming your specific flavor of FP is the "real deal", when in reality there are many different cohorts within the larger FP community that prioritize different things.
If I had to criticize your purity-centric flavor, I'd say it's very reminiscent of the height of the OOP craze, with algebraic terminology elitism being similar to the one surrounding GoF pattern terminology. Also similar are the grandiose theories of maintainability, and the dichotomy between what loudmouths preach and what code in the wild looks like.
People log things from .map callbacks. They don't grok monads. It seems entirely arbitrary to me to deny the functionalness of some code based on some technicality (case in point, do you avoid promises and do you Object.freeze(Object.create(o)) all your objects?)
IMHO, there's no point defending some notion of an FP brand. Looking around this thread, you can see that people already view React's hot take on FP as problematic. Same goes for general perception of the more elitist corners of the FP community.
There is literally an example React component in that article that the author calls "pure and referentially transparent". How can this be if there is "nothing functional about React"?
Bootstrapping pseudo FP styles into a Prototype Language with no types (JS is technically not OO, even `class` is just prototype sugar). Please no.
I really like concepts behind FP. I have tinkered with Haskell and gone through Bartosz Milewski's Category Theory material. That said, its radically different than traditional Procedural or OO coding. It really needs language level support to be useful, and that usually starts with types and the compiler. Open up "FP" libraries in non FP languages, and you often discover its just the same objects as the rest of the language.
That said, immutability is awesome. The concept of creating mutability boundaries and only exposing immutable data to external services and clients solves a whole class of bugs related to "who changed that?"
I think many of us familiar with the FP inspiration for language features like Promise also understand that it’s a Monad. But this is a weird response to a comment about the oddity of throwing a Promise. I may be mistaken, but it seems unusual (in the FP analogue) to return an Either<Future<B>, A>, and even weirder to obfuscate that in a seemingly synchronous interface to trick you into thinking you’re returning A | B.
which actually has nothing to do with functional programming, it's just sloppy programming
This is because this person is one of those clowns who learnt one thing about functional programming and use that in every conversation to deflect criticism without much understanding of the criticism
> Imagine for a second that a Promise's .then is called .bind, put it in a thunk if you want to be extra precise and tell me what it is. Hint: It starts with "M"
I’m really cautious to agree here. We’re talking about something that’s increasingly core to React’s design (you don’t throw Promises yourself, the internal APIs do, and it’s documented that way so other libraries can interop). It’s a weird design but I don’t think I could call it sloppy.
> This is because this person is one of those clowns
This is also unhelpful. I hope we can get better at critiquing without attacking the person, even where we disagree with them.
Instead of comming up with new API they retrofit existing one (the render function) to add continuation passing. They use throwing and promise, neither is for continuation passing.
Somewhere in this thread there is a link to the crankjs article which does the same thing using a generator-based API. It is also weird from a conventional point of view but at least simpler and somewhat more intuitive
> better at critiquing without attacking the person
How would you critique an attitude (pretentiousness and unhelpfulness) without attacking the person? This is a shitty trait and you have it but do not feel offended?
It probably helps to understand why they made that choice. I’m not going to go deep into archeology to do that, the likely reason has been a central of several front page articles recently: color of function.
Generators, like you mentioned, can solve this without infecting the whole stack, but it’s probably breaking for a lot of tooling. Async function components are almost certainly out of the question. They probably carefully considered the options and found this pattern unusual enough and identifiable enough to not break the world.
I don’t like it or agree with it. I think it’s really weird. But I can understand how it could happen.
> How would you critique an attitude (pretentiousness and unhelpfulness) without attacking the person? This is a shitty trait and you have it but do not feel offended?
I don’t understand the question. You’re presupposing personality traits where many other things may be contributing. I struggle to communicate a lot of ways, and one of my biggest challenges is actually having my person dismissed or being afraid that will happen. I hope this discussion has given you enough context that you don’t think I’m a clown, now or in any future interactions. But now I can’t know if you will unless you say so. Even though I’m just engaging with you as sincerely as I can.
This, on a scale of every internet interaction, can prevent people from learning or even contributing. Even if they’re talented or otherwise open to learning and have a lot of unrealized potential.
I wish Dan Abramov hadn't made this analogy[0], they're nothing like algebraic effects. The core idea behind algebraic effects is more similar to something like dependency injection if it was generally possible to "deasync"[1] things in JS, except it leverages dynamic scoping instead of lexical scoping. The Suspense thing is closer to those jokes where the punchline is something along the lines of the programmer saying "have you tried to restart it?"
[0] https://overreacted.io/algebraic-effects-for-the-rest-of-us/
I bet it wasn't Dan who came up with this analogy. My bet is on Sebastian: https://twitter.com/sebmarkbage/status/941214259505119232
Class components are dead simple. A class, a setState method, this.props, this.state, and some lifecycle methods. SO easy for anyone to understand.
Function components with hooks are not. A whole new (and unnecessary) paradigm; some mysterious hooks engine that needed new ESLint rules to be created just so people can keep the weird, delicate balance in place; hooks having their own timing problems, requiring usage of useRef which the React team tries to get people to avoid; etc.
Frontend codebases used to have several layers, with React just being one of the thin ones. Now, nearly the entire frontend codebase is inside React world. I'm not a fan of this direction.
FWIW I've seen it in many projects outside of the react/js world as well
IMO there's been a general drought in books/material on reasoning/thinking about software in general in-favor of the framework/library centric mania we have now which focus on the least interesting aspects of the field -- the cynic in me thinks this is due to how we hire people but there's likely more to it than that
2) "Hey it doesn't work with edge case X, let's graft on more features to cover it"
3) Repeat step #2 a few dozen times
4) The framework is now neither fast nor easy, invent a new one and go to step #1
I mean, hooks are totally this. They fundamentally break the concept of a "function" despite calling them "functional components." They use this weird notion of state (i.e. magic). The best way I can describe it is a cousin of dynamic scoping from the bad old LISP days. Back before lexical scoping was invented. So you end up with all these caveats and gotchas. Go look up useRef with useEffect and useCallback. It's all a total clusterfuck.
The lifecycle methods weren't perfect. But at least you could understand them. But I lost a lot of respect for React way back when they started fussing with the lifecycle API, a year or two before hooks. Their vDOM abstraction was starting to leak heavily and they were struggling to make sense of it.
When people say they like React, I really suspect they mean they like JSX. React, itself, is a mess. Always has been.
The word you’re looking for is side effect. The `use*` family of functions operate as hooks from the component into the renderer, so the renderer can easily see what dependencies a component has. This is accomplished by producing side effects.
The lifecycle methods are all well and good but there was an ergonomic problem with them with shouldComponentUpdate. No one wants to implement that function by hand when it involves whitelisting all props you want to produce a rerender, which is most of them. People would always write bugs. It’s much easier to create a list of dependencies a la second argument to useEffect.
Even easier to just not do that, either, as in Solid’s version of hooks.
They've been calling them functional components forever. https://github.com/facebook/react/blob/main/packages/react/i... I'm not sure why you're being a language nazi here. It's beside the points I was making anyway.
> The word you’re looking for is side effect.
Enough with your patronizing. Obviously it is using side-effects. That's the entire point I was making. Functions (as in the term from "functional programming") do not produce side-effects. Functions do not contain state. You know what is good at containing state? Objects. The whole paradigm of an "object" is exactly what React is trying to do with functions. It's nonsense. You can't call a hook function outside of React's apparatus. When React calls one of these hook functions, it has to dynamically switch out the context. Which is where my analogy to dynamic scoping comes from.
> an ergonomic problem with them with shouldComponentUpdate. No one wants to implement that function
Yes, well, as I said React has always been a mess and there are just as many problems with useEffect. Throwing out the entire API is just dumb. Libraries are no longer universal. You have to consider whether it's using hooks or not. Especially since they never formally deprecated lifecycle methods. They just shrugged their shoulders and went "here's hooks, use them if you like them."
> Functions (as in the term from "functional programming") do not produce side-effects.
This isn't true, even in the so-called "functional languages." Calling a function in Clojure could produce side effects, and the same is true in Haskell. In Haskell, calling a function that produces a side effect would necessarily return an IO monad, but that's a separate concern from whether the function invocation caused the side effect.
> Libraries are no longer universal. You have to consider whether it's using hooks or not.
You almost never have to think about this. Either a library provides hooks or it provides components. If it provides components, they could be implemented using the old component-style API or using function components; I have no idea, and it's irrelevant unless I plan to fork the library. Conversely if the library provides only a hook, I can easily wrap it in a thin component layer if that's the interface I prefer. The libraries are therefore effectively universal, since there's nothing that says I can't use a hook-based component within a function component, or vice-versa.
State and React have always been fundamentally intertwined, so I'm going to heavily disagree with the claim that hooks are a new magic wrt React. Personally, as someone who has used React for a long time, hooks have been a very intuitive and terse new syntax to use the lifecycle hooks & provides a far superior way to deal with state machine transitions.
> Go look up useRef with useEffect and useCallback
I must say, as a pro web developer who has built loads of applications, including model editors, charts with React views on top of D3 math, interactive 3D renderings, graphs, you name it, I don't know why I would have anything to do with "useRef with useEffect and useCallback". I've never encountered any issue with these things. What use case are you trying to solve that requires those hooks and what issue with those hooks exists that is blocking you?
> I really suspect they mean they like JSX. React, itself, is a mess. Always has been
Oh, you just hated React all along, so you probably never understood it. Easy to see why you don't like it then.
The fact that you are asking and haven't hit the issue suggests you haven't actually used useRef before.
> Oh, you just hated React all along, so you probably never understood it.
Sure, asshole. I've only been using React for 6 years now. But whatever.
I find hooks provide a far more declarative, testable, predictable developer experience. The simplicity of useEffect, useCallback, useRef, etc. makes it so I know exactly what I need to reach for when I need to accomplish certain things.
It can get complex, but I find that usually means you need to back off and rethink things.
React is one of the thicker layers I've seen.
Really, you're kidding yourself if you think React isn't far simpler than Angular or Vue or any of these other frameworks. If you have some different direction in mind, fine, but I doubt it scales
I would call React thin because the JSX components you build are transparently just objects, they interact with types super gracefully because components are just classes with a method that returns nested objects, and your code is just invoking JS and producing JS until the React library itself performs the side effect of rendering.
I understand that React has abstractions and a heavy scheduling engine and all sorts of complexity, but a React component - the core concept of React - reuses directly JS concepts in place of introducing its own in most situations. That is thin.
I admit that if you are just thinking of libraries in general, of course a frontend framework is not "thin", but for a library which enables true composability and reuse, React is so thin compared to is competitors. Which seems a reasonable de facto context for a conversation about React.
I've run into state/props mismatches due to the diff resolving differently than I thought it should. It's possible to solve this, but it further breaks the illusion of a thin layer.
Maybe it's a different way of thinking, but I don't think two-way binding is inherently thicker. To me, thickness is related to the amount of "mechanism". A handlebars-type templating system seems much thinner to me.
I agree that the tooling and even React itself, under the hood, have never been thin, or if they ever were it was only very early on in the project. Well-functioning enough that one could forget about them at times, maybe, but not thin.
1. Providing a general signal to reuse the existing DOM node (or subtree, but that’s less useful) without performing any render logic.
2. Allowing components to use built-in suspension semantics (generators, async/await).
The former would have other really useful applications, like partial/selective hydration. The latter is closer to both the language and the original spirit of React, which embraced being close to the language. (Who ever thought “throw a Promise” for meaningful control flow before this?)
That said, it’s pretty clear from what React team has discussed since Suspense was introduced that it’s part of a larger strategy. Specifically: React Server Components. They’re laying the groundwork for that now, in stabilizing Suspense SSR.
I’m more interested in a less sophisticated solution, but it’s pretty clear RSC is both where React is heading and requires a more opinionated foundation like Suspense.
> difficult-to-track-down ways because of how errors are propagated with suspense
I suspect this has more to do with concurrent rendering generally, than with Suspense itself. Debugging concurrency is harder in general. React's simplistic top-down rendering model was successful in part because it was simplistic and top-down.
- - -
All of that may not be justified for your needs! React is positioned for a very specific set of use cases (even if it’s over-used for similar-looking ones). You may find you’re more comfortable in a more simplistic VDOM (and that’s okay!) or a library based on reactivity (if so, and if you’re coming from familiarity with React, I’d suggest giving SolidJS[1] a look; its rendering model is much closer to the DOM).
I’ll also mention that I’ve spent more time with Preact than React, and have found its Suspense implementation much easier to work with and debug.