Contrary to some commenters here, I think React is just about the best thing that has happened to UI programming in recent memory.
Everything I tried before it (jQuery, Backbone, Knockout, Angular, Meteor (with Handlebars)) felt like it fell short or, in the case of the databinding-oriented ones, like a broken abstraction. I get a similar feeling when looking at Vue though I have no experience so I might be wrong.
I too am a bit skeptical about hooks making what looks like pure functions act like stateful ones. I am not using hooks yet but besides from Dan Abramovs excellent articles about their rationale, I think I will look at them like a new paradigm, only using a syntax that we know from something else. In fact, I wouldn't be surprised if I some time in the future will be using React to write state machines for something that doesn't have anything to do with UI, where "rendering" composes state related to something else entirely. I could see hooks being a game changer here.
One reason I love Vue over React is how beginner friendly it is. You can't make a "Hello World" app in React without getting bombarded with concepts and terms—states, props, JSX, stateful components. Just look that the "Getting Started" example of Vue [1] and compare it React's [2]. You don't need anything more than a notepad to get the first example running.
Progressing down Vue, you realize how they have tried to prioritize convenience. For example, using "v-on:keyup.enter" you can map an action to "Enter" key without writing code for handling that key.
I liked the React's approach but it seems its focus is on purity of abstractions than convenience. Don't even get me started on Redux which is epitome of needless complexity—containers, reducers, event emitters? Was all that really needed?
Note: I have no idea how Vue fares when code base is huge, but my intial impression makes me feel it's far better choice than React.
>Just look that the "Getting Started" example of Vue [1] and compare it React's [2].
Thanks for feedback!
The linked React guide is intended to be a pretty comprehensive tutorial — not a getting started guide in the same sense. I wouldn’t say they’re comparable in how much about either of them teaches you about using a library. Maybe it’s not obvious from the wording.
If you do want a simple “getting started” guide that doesn’t require any tools, it’s right here:
Thanks for feedback. I do think the “main concepts” guide goes in roughly the same order but I agree there could be a more condensed single-page version of it. We’ll keep it in mind for the future!
The linked React guide is intended to be a pretty comprehensive tutorial — not a getting started guide in the same sense. I wouldn’t say they’re comparable in how much about either of them teaches you about using a library. Maybe it’s not obvious from the wording.
FWIW, I think the current introductory material on the React site is not as effective as how things were in the early days. IMHO, a significant benefit of React in its original form was its simplicity. The whole API practically fit on a single screen. You could write a tutorial that showed the basics of rendering a component or two on a single screen. Today React itself has become more complicated, and the tooling around it even more so, and I'm not sure that extra complexity offers a good return.
Just as a demonstration of my point, please imagine for a moment that you are a developer who understands the basics of the modern JS world but is new to React. Go to the React site and find the instructions on how to just install React with npm or yarn, the way you probably would with any other JS library.
OK, so there's nothing readily visible. No, really. How to just install React like every other JS library in the world isn't even described on the introductory pages. Well, maybe you try running
{package manager} {install command} react
That used to do the obvious thing, but now it doesn't because even the essentials are divided among multiple packages with non-obvious names. So at this point, just a couple of minutes after you decided to give React a try, you're already confused about how it works in NPM and thinking basic documentation is missing, and you haven't even installed it or written a line of code yet.
Maybe you find a link somewhere to the page about the "most popular and approachable toolchains". OK, that looks promising. You click the link and... you're confronted with create-react-app, Gatsby, Next.js and a bunch of other dubious, heavyweight tools, not that you know that because you've never heard of them. But there's still no sign of how to just install React and try it out like any other JS library.
So you go to the kitchen, make a coffee, come back and ask your mentor whether it's really necessary for you to use such a complicated and difficult tool, and whether you can just use Vue instead.
And it’s linked to from the other pages you mention with a disclaimer that a simple HTML page is still the best way to get started. Sure, you can ignore that, but what can we do.
But whether we like it or not, plenty of people want to kick off a single-page app with a whole toolchain rather than just “try React”. Earlier docs that you fondly remember didn’t help with that at all, leading to a lot of frustration.
Some people will be unhappy with either approach. That’s why the docs include instructions for both.
I think this page is written for that exact use case!
I understand that this is what the React team think. I am trying to explain that that page (and the other "getting started" level material on the current React site) is not necessarily working very well.
Maybe we're unusual, but among my professional network the overwhelming majority of React users do so with what now seems to be considered a custom tool chain, even if it's just "Bundler + Babel plugin for JSX". The first question everyone asks when they want to try out React, like any other new JS library or tool, is what they need to npm-install or yarn-install to get a minimal example going. And this information has now been hidden away several layers deep on the React site, as if it's an unusual use case.
Loading scripts from CDNs is fine for a very early experiment but quickly outgrown in production environments. There is create-react-app, but most people I know are sceptical about such tools and in any case it's debatable whether you want to start with scaffolding/framework tools if you're learning a new library for the first time and want to understand how it fits into everything else you're doing.
In short, the current site (and your reply here) seem to be predicated on a false dichotomy. Presumably you have access to better metrics than I do as a random individual and you know that most people really do fall into one of those two groups. All I can tell you is that almost no-one I know does, including those I have introduced to React myself in recent times.
Maybe it's just the curse of the modern JS world that everyone feels obligated to try to show how their individual tool or library works with 500 different other tools and libraries. Even so, there's probably a reason that almost every modern JS library's home page seems to have a screenshot with the words "npm install" in it above the fold.
Thanks for feedback! Will keep that in mind next time we look at the docs. (FWIW we used to do exactly what you said and heard many complaints about that — people didn’t want to see npm, didn’t know what Babel is, and so on.)
You're welcome. Again, I appreciate that you probably have much more comprehensive data to go on than my mere anecdotal experience, but I think it would be useful to include a more standard introduction for visitors who don't need so much handle-holding, such as those coming from other libraries/frameworks and already happy setting up tools like Webpack/Browserify/Rollup/etc. Those of us who play the mentor in the previous story would certainly appreciate it. ;-)
If your project grows big, you will at some point need to use a state management library like VueX which has similar concepts than Redux, so I'm not sure this argument holds.
My biggest problem with Vue is the template syntax. Since JSX is a thin layer over Javascript, few modifications have to be done over Javascript (or Typescript) tools to make them work with JSX (or TSX). Vue templates are a totally new language which requires more complex tools. I've never had any problem using refactoring tools (renaming variables, go to declaration, find usages, ...) with React, while in my last Vue project, renaming a variable broke code.
Vue has Vuetify, which has been a breeze to use, though. I don't know if there is a React equivalent.
Vue templates are not in any way more of a totally new language than JSX is. Vue templates are simply XHTML snippets with added data bindings. JSX is not quite XHTML (you have to use className instead of class) with added data bindings.
I find Vue templates slightly cleaner for that reason, but the difference isn't big. How they're used is different, though: React wants everything, including the XHTML, to be javascript. Vue puts it all in HTML, with script tags for the javascript.
<div v-for="item in items">
<span>...</span>
</div>
The refactoring tools must know that the "items" inside the "v-for" refers to a property of the data object. In other words, the content of the data bindings is a totally new language by itself (the content of v-for has its own syntax, with a parser).
Compared to the equivalent in React, which would be:
{this.items.map(i => (
<span>...</span>
)}
Or possibly
let elements = [];
for (item in this.items) {
elements = <span>...</span>
}
It's way easier for a refactoring tool to support JSX since it's just syntactic sugar over JS. If you were the developer of such a tool, you would just need to consider "<>" as values and possibly consider anything inside "{}" as normal Javascript.
And indeed, as pointed by another commenter, React supports classes and integrates very well with Typescript since React 16.
JSX is a dsl, like typescript or flow, it doesn’t change or affect your code, all assumptions stand, it doesn’t break scope. Vue templates are not a dsl, they break all assumptions and your scope. There is no difference between Vue and angular in that regard, both could not do this with templates:
const A = () => <div />
const B = () => <A />
JSX turns that into:
const A = () => createElement('div')
const B = () => createElement(A)
That is all that JSX does. Vue on the otherhand parses its own language, breaks scope, separates concerns that shouldn’t be separated and in the end joins them via dependency injection again. We’ve been through this years before Vue existed with angular and others.
BTW, your info is outdated. "class" is allowed in React as of V16.
> I think React is just about the best thing that has happened to UI programming in recent memory.
I completely agree that it’s the best thing that has happened to web UI programming in recent memory, but for me, personally, I think Qt’s QML is the best thing that has happened to UI programming in general in recentish years. I like using react, especially from clojurescript using re-frame and I’m very thankful that it exists, but QML has been some of the most pleasant complex UI development I’ve done in the last few years. Now, if only Qt were more like re-frame, then I’d be super happy, but I love the declarative nature of QML and the anchor-based layouts.
> I too am a bit skeptical about hooks making what looks like pure functions act like stateful ones.
What’s wrong with that? Any conceivable application needs to actually have state that changes over time. That’s true of all software written in a purely functional style.
That’s true of all software written in a purely functional style.
By definition, any software that is purely functional does not have explicit mutable state. In practice, it is often useful to have parts of a system written in a pure functional style but other parts that do use mutable state, either explicitly or via some mechanism that simulates it in a functional context.
You mention a lot of frameworks and libraries that abstract frontend development into its own "kind". I feel like you're already colored with the "crap" they come with. They all abstract something very simple into something that doesn't scale well for solving many of the common challenges for frontend development. They are all leaky abstractions.
Of all these I have used jQuery and React, but I prefer plain vanilla over these. No breaking changes, no hype cycle, excellent documentation and with good old design patterns any complex problem is easily solvable. Believe it or not, but managing state is dead simple with just vanilla javascript.
> Believe it or not, but managing state is dead simple with just vanilla javascript.
Keeping state and the view in sync, however, is not. For example, if you have a list of TODO's that the user can edit in the browser, and that you want to be able to send to the back-end, every time the user adds a TODO, you'll have to remember to update both the model and the DOM. Likewise after an edit or deletion.
After reading numerous articles (starting with the docs), I'm still not convinced, and will not be using React Hooks any time soon. Some of the things I do not love:
- Magic, in the unfavorable sense: if hooks were implemented in an indepedent library, just hearing that they "must be called in the same order every time" and "cannot be used inside conditional statements" should make anyone wary.
- Scope creep: if anything, I wish React focused on reducing its size and API surface.
- Entanglement: related to the point above, the goals of hooks would have been better served with a separate, tiny library that doesn't need to know anything about React, and usable anywhere else, with plain functions that can be tested or reused independently.
Well, the topic deserves a deeper criticism than "it feels wrong", so I hope someone can write a worthy article called "Why I Do Not Love React Hooks", with an example of a better, alternative solution.
I hesitate to bring up a cliché, but it's starting to feel like React is the new jQuery. I'm already trying to anticipate what comes after React, in which case I want my code to depend on the smallest possible API surface area.
But then again, maybe it's my wishful thinking that we would move towards "universal components" (using dependency injection to pass in React or other view renderers like Web Components). Since much of the JS ecosystem seems to be going "all in" on React, perhaps I should surrender to its current. As long as I continue to use React, it looks like there's no escape from its hooks..
EDIT: I should add that the above is just my opinion at the moment, and I'm open to changing my mind. Who knows, I may unwillingly start using them (since everyone else seems to be), and come to love hooks after all.
I'm all for an advancement that simplifies things, and from the sound of it, hooks enables writing of simpler code.
Two things stand out about hooks to me (from what I have read, have not used them yet):
1: well suited to writing functions rather than classes - this is appealing because there is a line of thinking that values function composition over object orientation.
2: it sounds this finally solves one of the major challenges in react which is simple cross cutting. Cross cutting was always painful and I'll be very happy if this is cleanly solved.
I'm hesitant about new functionality that increases complexity, or is harder to understand and grasp. I'm very enthused about anything that goes the other way.... the industry must constantly strive for simpler ways to do everything.
I think the crux of the issue is agreeing on what is 'simpler code'. I think using lines of code as a measure of simplicity is flawed.
For me simplicity is the three C:
Clarity, in terms of how many concepts do I need to know to understand given some lines of code. The fewer the better.
Coherence, how similar is the expressions I write to what I want to say in terms of the given language. The more similar the better.
Confound, how surprising is the behavior of the code? the less the better.
The issue with hooks I think is that they're trying to treat symptoms rather than solve the problem, if you read the original motivation document by Dan, it talks about State Logic Reuse, Complex Components and People Don't Understand Classes; I think these problems can be tackled much better by their own without trying to add more APIs to React or taking drastic measures like completely change the way people think about React components.
@omeid2 I think you've distilled the issue very well -- it's all about "what is simpler code?".
I hadn't thought of the issue in terms of the three C's you've mentioned, but the criteria also seems accurate.
In my opinion, the popular SPA frameworks (Angular, React, Vue, etc) all suffer from similar problems. They build abstractions on top of abstractions, they force you to learn domain-specific languages (e.g., JSX), lots of new concepts to learn before you can be productive, they are fairly opinionated about how your application should be structured, etc.
If you have the time, take a look at this JS framework I put together ( https://github.com/elliotnb/nimbly ) and it's state management dependency ( https://github.com/elliotnb/observable-slim ).
I built the framework so developers can take advantage of the benefits of modern frameworks (templating, data binding, state management, no explicit DOM manipulations, automated unit testing, loosely coupled modular components, etc) but without the typical drawbacks of modern frameworks. The framework has far fewer abstractions than React or Vue, requires no domain specific language (i.e., you write in plain HTML, CSS and JS), and does not require compiling/transpiling. The framework embraces the DOM instead of abstracting away from it and still refreshes/re-renders components in a highly performant manner via DocumentFragments.
We've used the framework fairly extensively at my work because it plays very nicely with our jQuery-heavy legacy code and allows for much easier re-factors.
The observer library has gained a fair bit of interest from other developers (~2k monthly downloads via npm) and it'd be great if I could interest others in trying out the framework too. I'd love to hear feedback from anyone who takes the time to try it out. Other contributors would be fantastic.
> I hesitate to bring up a cliché, but it's starting to feel like React is the new jQuery
I don't understand this comparison. jQuery extended the existing DOM API to make it more user friendly and made it cross browser compatible (an incredible thing in it's age). React does nothing like this - it brings a completely different concept to designing user interfaces that has nothing to do with the DOM api.
If anything, I see hooks as a response to the community that was installing React+Redux(mobx/whatever global state manager library is flavor of the week) by default. This feature makes it possible to use React as more of a one stop solution, which I definitely welcome.
> I'm already trying to anticipate what comes after React, in which case I want my code to depend on the smallest possible API surface area.
That's a fools errand. The code I wrote 10 years ago that relies on jQuery still relies on jQuery (and guess what -- it still works the same as it did when I wrote it!). And the code I wrote 5 years ago that relies on angular1 is still in production (and guess what -- it's fast and incredibly bug free because it's had so long to work out the kinks). Despite these frameworks no longer being fashionable, they still serve in production environments fantastically.
You don't have to rewrite your user interface code just because something else came along. You can embrace the positives of the library or framework that was being used at the time you wrote that code and create a rock solid application. Your goal shouldn't be to write code that depends on the smallest API surface because good code that correctly uses a well written API (which both jQuery and react are) will not be hard to maintain down the road regardless.
2. Don't hooks remove the need for redux, etc.? Meaning, don't hooks radically reduce the amount of libraries you need to know about?
3. I prefer to use pure React and not have to choose between Redux, Flux, Mobx etc. And, then do I need to use redux-thunk, etc?
I actually really like the progression towards hooks. I think the articles from the core team (like Dan Abramov) have been well written, explaining not just the how but the why, and it feels like hooks serve to make things simpler and more readable. Yes, you have to throw away a lot of things you spent time learning, but I'm not sad to see anything go away that hooks now handles.
What Redux brings to the table is separation of Data from Components, it is not uncommon to use the same data point (user profile, user organization/s, et al) in various components. Moving this to component states either requires a lot of prop passing or duplication (api calls!), short of using Context, which is kind of Redux-ish all over again.
That's true, especially JSX caused an uproar in the beginning as "too much magic", and then was gradually accepted as a vast improvement to previous/other ways of templating.
> Don't hooks radically reduce the amount of libraries you need to know?
I'm really hoping so! If they do indeed "serve to make things simpler and more readable", it would be a net positive, regardless of any initial misgivings and possible effort to migrate.
React's core isn't magical insofar as its core functionality (virtual DOM + "update everything on any change") could fit on a 3x5 index card. Implementing it is definitely hard though...
Yes. You need “magic” to be able to write and Reason about your programs in a functional style, while still having side effects and state that changes over time. All functional programming environments have this.
Perhaps not, but React hooks in my opinion aren't any more magical than the other internals of React that allow you to use a function style to implement component trees that change over time.
This is a common first criticism. There isn’t much magic going on implementation-wise (you could probably implement a simple version of Hooks yourself in <200 lines).
The static call order is controversial. But I strongly encourage you to play with it before forming a final opinion. Pretty much everyone who loves it now hated it at first. (I’m not an exception to that.)
It’s not even as much a technical limitation (we could make arbitrary order work) as confusing semantics if you remove it (how can state be conditional?).
So static call order seems like something you’d enforce with a linter anyway. At that point the cost of allowing dynamic call order becomes not worth it. (Both in API and runtime overhead.) I wrote about it here: https://overreacted.io/react-as-a-ui-runtime/#static-use-ord...
Magic is bad when it’s confusing to use or debug. There are some challenging aspects in using Hooks (like in any programming model, there are cases made easier and cases made harder) but the static call order is not one of them in practice.
>Scope creep: if anything, I wish React focused on reducing its size and API surface.
Regarding file size, ironically, Hooks can decrease the overall app file size because function calls minify better (more things can be mangled). The implementation itself makes up for less than 4% of React.
We’re working on making it smaller — but there’s a balance between size, runtime performance and providing abstractions that help remove application and other library code (usually much more impactful). Numerous libraries that migrated to Hooks reported savings in size.
>the goals of hooks would have been better served with a separate, tiny library that doesn't need to know anything about React, and usable anywhere else, with plain functions that can be tested or reused independently.
Regarding API surface and the notion of what should and shouldn’t be in React, you might think about it differently if you think about React API from first principles.
Thank you for the thoughtful reply. I'm a fan of your work and writings, they've been valuable for the whole JS/React ecosystem.
> you could probably implement a simple version of Hooks yourself in <200 lines
It reminds me of the Egghead video course in which you described "how to write your own Redux". That was a great explanation of the paradigm, and transformed how I think about state management in an application.
What I love about the concepts behind the paradigm, is that they can be implemented (as they are in Redux and elsewhere) as a handful of tiny functions that work with or without React, for composable and reusable state and actions.
I think my hesitation about Hooks as they're implemented, is that it seems to go against the ideal of de-coupled, pure functions. Although it does encourage that for the users of hooks, its own implementation feels coupled and impure.
For example, people are applying the Flux/Redux paradigm outside of React components and the UI/views layer, like server-side or independent features that need to manage their own states. I wish that Hooks had taken a similar approach to Redux, as a canonical approach to a generic and generally applicable paradigm, where one could "write your own Hooks".
> I strongly encourage you to play with it before forming a final opinion. Pretty much everyone who loves it now hated it at first. (I’m not an exception to that.)
Yes, I'll keep an open mind and study it more.
I read "React as a UI Runtime" when it was published, and it was insightful (will read it again to really digest it). I do love the concepts and principles on which React has been built, so I'll try to understand the reasonings behind how/why Hooks were implemented the way they are.
I think the next big framework will build on top of the declarative jsx-style rendering from react, while also providing pure abstractions of the side-effecting browser APIs
I think I agree, but we'll see. Personally, I'd like to read about the politics that lead to this kind of feature, rather than just the feature by itself.
While I do like the idea of more functional components, I don't think hooks are the answer. The reason I like more functional components is because I want to keep components small, stateless and dumb. Hooks encourage people to write more functional components, but I'm not sure that they'll encourage people to write functional components properly. Instead they'll just transfer the anti-patterns they're writing in class components to anti-patterns in functional components. For instance, I could see people writing large functional components with big globs of state and side effects.
The real issue which I want to see solved is getting people to remove business logic from React. I see components loaded to the gills with data fetching and overly complicated async rendering schemes. Personally I try to keep my React components extremely dumb. Instead I try to keep most of the business logic on the server side when possible, and in Redux otherwise. But even that's not great. Redux is fundamentally a data store, not a business logic library. Trying to do complicated logic with selectors/actions is a nightmare. I suppose that's why front end frameworks like Angular and Ember are popular. React ultimately is a view library and yet it provides no good option for the business logic.
Fighting advancements because they could be misused is a battle you cannot win. If your team is going to misuse features because they simply exist then you need to address the root cause — your team — not the library.
> The real issue which I want to see solved is getting people to remove business logic from React. I see components loaded to the gills with data fetching and overly complicated async rendering schemes. Personally I try to keep my React components extremely dumb.
Hooks are great for this. You extract all business logic into custom hooks and your components are left as dumb renderers calling other functions to get values. It’s great.
How is it that React gets celebrated for “solving” problems that React created in the first place?
The entire paradigm of React keeps changing as each pervious iteration proves to be “messy” or “over complicated.” createClass? Nah that’s obsolete. Mixins and HOC - oh wait, bad idea, hooks to the rescue!
At what point do people start to call BS and say you shouldn’t build around a framework that needs to be reinvented every year or two?
(I worked on React.) Many people have adopted React and are happy with it, evidently because they believe the problems it creates are minor compared to the problems it fixes.
It’s rather reasonable for them to be excited about a new version that keeps (or improves!) the good parts while having fewer tradeoffs.
React is amazing. I'm teaching myself JS — started October '17 — and I've gone through a few iterations of my little project as I learn more.
- Vanilla JS: it works, but holy moly it looks bad and the amount of code I have to write to do even basic stuff really really hurts my brain. (Actually what am I talking about, it never got close to "working" before I moved on to...)
- jQuery/Node: ooh, this is better. But still, doing stuff takes ages.
- React: OH MY GOD WHAT IS THIS HEAVEN.
People will say that "people like me" shouldn't be writing web apps if we don't know what we're doing. To them I say, screw you. These tools enable us to do things that would never have been possible.
Thank you from the bottom of my heart for doing whatever it is that you did. :-)
I was initially resistant to a lot of react, for example, jsx. However as a backend dev (functional) I was very pleased when I could dive into react code and reliably implement features as needed.
Thanks for all your great work sophiebits. React is perhaps the most important milestone in bringing functional concepts to the mainstream to date, and the project has been really well managed. It makes backend people like me actually enjoy writing JavaScript! Excited to see what you do next.
Without trying new things, you get stuck with, say, UIKit + CoreData which make me miss React every second I'm building an iOS app. All the KVO stuff that make it hard to actually reason about state changes.
Of course React, like any library/framework, is going to have its own idiosyncrasies. That isn't the question. The question is if it's still better than alternatives, and people clearly seem to think so. My first React app I ever made years ago still works on the latest React, seems pretty stable as far as the web client ecosystem goes.
Client development isn't trivial on any platform, btw. But I think we have it pretty damn good on the web, relatively.
To me, Web Components are bound by the fundamental anti-pattern of having to globally register unique tag names. Didn't people already learn the problems with doing this from Angular 1?
The contrast I mean to emphasize is React, where the tag you use is either an actual var declaration or a string placeholder for a browser (or other environment) built-in.
This seems pretty disingenuous to me. React didn’t create the problem of class methods not binding this correctly. That’s purely a javascript problem, which react now provides a way to solve.
This is a question that’s been puzzling me for quite a while.
For one, react is a fairly competently done, roughly MVC UI framework. The components are views, render() is drawRect. Being in the browser, render() doesn’t draw into a bitmap, but rather returns structured objects.
That also means painting optimization is diff-based rather than damage-rect based.
Which brings us to what appears to be the biggest difference: traditional MVC GUI toolkits such as Cocoa clearly separate creating a UI from updating the UI with data. For updating the UI from the model (and the model from the UI), you follow MVC, which specifies how the Views map the model to the display and vice versa.
The actual views stay the same during that time, the data changes.
React combines these two steps into one, conceptually recreating the entire UI at each step like a game.
While this solves some issues that have crept into toolkit programming due to a shift towards handling dynamic aspects via changes in the view/widget hierarchy, it is conceptually rather muddled[1].
This conceptual muddle, claiming that the UI is a “pure” function of the state when it is clearly not, seems to the major source of those problems that keep needing to be solved.
To me it would seem that looking dispassionately at the problems react solves without the conceptually troublesome baggage might be useful, but that’s just my € 0.02.
The linked post is a great comparison of functional and object-oriented approaches to building UIs. Thanks.
I think the crux of the issue is here:
> "So if we don't make the incorrect assumption that UIs are unstable (pure functions of model), then we don't have to expend additional and fragile effort to re-create that necessary stability."
In Cocoa, and generally in desktop UIs, your assumption is true. A UI is a set of "slots" into which dynamic data is displayed. But on the web this is a lot more fluid. You can have visibility toggles across the application, and the UI can vary drastically between one state to another. I think this is the fundamental mismatch between the object-oriented approach to UI and the functional approach to UI.
Also, in the "Lists" section, the functional approach would not be to create a persistent Map, which then has to be invalidated as its source data changes. Instead, the mental model in the functional approach is to always re-compute everything; memoization is an optimization that should be transparent.
I think your analysis is very insightful, but there are some additional wrinkles. I don't really think it's just OO vs. FP or Desktop vs. Web, though those aspects definitely play a role.
First, if it's an actual User Interface, something that the user interacts with, stability is not something imposed by platform convention or frameworks, but an inherent requirement: if I edit text, my text field (or editor) better be stable as I type, or it will be impossible (and infuriating)
to actually interact with. If I interact with a list, that list better be stable. etc.
If it's just (mostly) visualisations that I consume mostly passively, that's a different matter (and then there are games, where you interact with a full-screen visualization).
That's not to deny your observation that interfaces have become more fluid, certainly on mobile and web, and that there isn't a certain kind of desktop application with very static/forms based interfaces (business CRUD...). You can be more static on desktop because you have the screen real estate, and disabled but visible controls are generally considered to be better than things that hide/show/slide.
So there's a bit more going on, and I think a crucial difference is how the more dynamic parts of interfaces are created. After all, it's not as if "classic" user interfaces are incapable of doing dynamic visulations and interfaces: you create a view, and within your view your drawRect: (Cocoa) method draws whatever you want however dynamically you want it. As an extreme example, 3D games tend to have an OpenGLView (now a MetalView) and inside that you have all the action.
After all, "object orientation" has both: data-structures and methods that act on them, and OO user interfaces also have both, meaning you can get as "functional" as you want. You can compose objects, draw procedurally/functionally and mix and match both to your heart's content.
For some reason, or maybe set of reasons, that doesn't seem to happen much any longer. Instead "object oriented" appears to be interpreted more in the way of "object oriented graphics", where you have a set of shapes (or widgets) that you can assemble, but without the part where objects can have arbitrary behaviour.
What this unwillingness or inability to embrace the full capabilities of OO means is that when you have dynamically varying content, you now have to dynamically change the composition of your objects/widgets. Which, admittedly, those frameworks were not created for, I am guessing at least partly because they have a different mechanism for achieving those effects.
> [Lists, functional approach, re-compute ]
If you look at NSTableView and related, you will see that they also provide a fully lazy interface to the data source[1], which can be infinite. However, the caveat from above applies: those lists better be at least somewhat stable if you want to be able to interact with them.
I really think we should talk about this over a proper medium like email or Zoom or something :)
The point about stability as an inherent need for good UIs is true. I'll keep it in mind when thinking about this problem.
Here's two examples I can quickly think about where web interfaces are more fluid than desktop ones: 1) new UIs on hover. 2) accordions. In https://unsplash.com/, when you hover over any image, three new buttons appear; all of them are interactive elements. And accordions are anything that expands on click to reveal more content - expanding a Twitter thread in the web UI is one example.
These kind of interfaces were very rare in the desktop world. Winamp was one of the rare UIs in popular memory that worked like that. I think they were rare because the tooling - static widget-based UIs made with form builders like Delphi and VB6 - made them very difficult.
But even if we fully code the UI using objects; like say in Qt, or even in Cocoa, I think the development experience and the robustness of the code is better expressed in a functional paradigm.
I think both of us are ultimately using the affordance of writing UIs to judge OO and FP as computational paradigms. I think UI is one of the most concrete but underlooked ways to discuss this topic and measure relative trade-offs.
I've been doing OO programming for about a decade, but recently something clicked about "computation" which I've tried explaining in the first section here: https://protoship.io/blog/how-functional-is-ruby/. It is something around "OO vs FP = Stateful programming vs Explicit/pure programming = Turing Machine vs Lambda Calculus"
Just to add, I wish I was able to articulate clearly why I prefer one over the other. One way might be to contrast both OO and FP approaches with a reference UI and have discussions based on concrete code. But that's a lot of work. For now having worked with both approaches, I have a visceral preferences to express UIs as a function of state.
I'm interested in this area because I've been trying to figure out a way to express UIs visually (like thru erstwhile Delphi or VB6 forms, or today's vector drawing tools like Sketch), but unlike all existing renditions, they have to be composable, reusable, and Turing complete. This is a little more tractable than it might seem if we use Lambda Calculus rather than Turing Machines to think of the problem, and so expect the interface to be pure and side-effect free.
Honestly i struggle when people argue that 'this' and class components are complicated, and that hooks remove that complexity. Yet then i see people composing together dozens of various hooks and HoC's to achieve the same balance is beyond confusing.
Recently i was assigned a PR for a component (a login form) i wrote about a two years ago which was a whole 300 lines. The person who wrote the PR also took the time to make it "functional", which has now resulted in it being split into almost a dozen different files. I don't find this cleaner or easier to understand at all.
Current team i am on uses MobX, and Typescript for our app and frankly it is painfully simple, and yet people keep arguing that we should drop mobx, and switch to hooks and i don't see any benefit.
One part of the functional promise seems to be that if every piece of functionality is small, isolated and easy to understand that the whole of the application becomes easy to understand. However, I would agree that I often find the opposite to be true when everything is scattered around in mini functions over hundreds of files.
> One part of the functional promise seems to be that if every piece of functionality is small, isolated and easy to understand that the whole of the application becomes easy to understand.
This part is wrong. Your huge components are made of what? Small things. Isolating all those small things just let you add more boilerplate and mental load when trying to debug. To reduce complexity you have to remove code, not move it around.
I don’t think we promote isolating every little thing. That would indeed be counterproductive.
It’s more about being able to reuse some stateful logic between components. That’s the point of custom Hooks. There are pretty cool libraries existing already. For example React Spring takes advantage of that programming model for animations: https://www.react-spring.io/docs/hooks/use-spring
This whole thread is wrong. Nobody said you had to split the functions off into a bazillion files that's just stupid. Youre taking the worst part of enterprisey OO culture and ruining the best part of functional.
And no, you do not need to remove code to reduce complexity you're mistaking correlation for causation.
Boilerplate may occur in the short term during a refactor to pure functions but that can eventually be refactored out once things are unshackled enough to be refactored.
Are you using Storybook or a similar system? I've got a lot of value in defining my application in decoupled components when I can verify the implementation of each part in isolation.
We write tests to verify if things are working correctly using Cypress + Mocha. We have simple unit tests for validating basic functionality and extensive integration tests. We typically have a set of tests per feature.
The problem i have noticed is that people say "well it works in isolation", but on integration with other components it doesn't work properly. Unfortunately this is a huge problem i find, and frankly the idea of numerous shared hooks and ensuring they are side affect free is very painful.
mobx-react-lite (supported by the main mobx team) uses hooks under the hood, but extends mobx-react behavior to SFCs. I don't think it creates any additional boilerplate and it aligns with the direction React is going.
I'm a bit dumbfounded about the "this" and "class" confusion concern as well. I'm not surprised to hear people have trouble with that per say.. I am surprised a company like Facebook cares about those people. Isn't this the same company that wouldn't hire the homebrew author? I get the sense the only UI people who really know programming work on the React team.
>Isn't this the same company that wouldn't hire the homebrew author?
I think you’re confusing it with Google.
>I get the sense the only UI people who really know programming work on the React team
I haven’t worked in many companies before, but I find my colleagues across the company to be very good UI engineers. Not sure where you got that impression.
>I'm a bit dumbfounded about the "this" and "class" confusion concern as well
In the grand scheme of things it’s a pretty minor concern (although people do tend to overfocus on it because it’s easiest to explain and discuss).
The motivation for Hooks is:
* Share reusable stateful and effectful logic between components. Like mixins but without name clashes or the diamond problem. Hooks can be applied more than once, and are instantiated per call.
* Colocate related logic instead of artificially splitting it into lifecycle methods.
* Accurately model component as being in multiple states at the same time for concurrency. (Important for future React features.) Closures can do that because they capture specific props and state.
Finally there are some difficulties related to optimizing class code at compilation time. Such as inlining and fusing classes together. Functions make this simpler and they also minify better due to safer mangling.
All of these motivations can be challenging to explain. So people tend to overfocus on “this”.
> All of these motivations can be challenging to explain. So people tend to overfocus on “this”.
> I haven’t worked in many companies before, but I find my colleagues across the company to be very good UI engineers. Not sure where you got that impression.
I can't recall if I've seen it brought up in other "official" channels, but it does certainly get talked about a lot in discussions such as this and I believe that's because of information sources such as the link. I will defer to you on the real situation, but I think hearing about classes and "this" being confusing, coming from React, is where people might wonder what's going on. Mentioning it at all may have caused a large distraction as people latch onto it as you say, and find the situation a bit incredulous.
It is unfortunately the only point that we can clearly explain to beginners, designers, and other people who aren’t deeply familiar with programming principles. We still care about them and want to emphasize we’re not ignoring them with some new paradigm. When you have such a vast audience as React does, someone will get upset anyway.
> * Share reusable stateful and effectful logic between components. Like mixins but without name clashes or the diamond problem. Hooks can be applied more than once, and are instantiated per call.
In the mixins are considered harmful blog the point is made that sharing logic between components is a mistake and you should be using composition to achieve the desired outcome. Why do I need hooks? Is composition considered harmful now?
> * Colocate related logic instead of artificially splitting it into lifecycle methods.
Nope, all this did was make a mess. If splitting your logic into lifecycle methods was too disjoint there was way more going on in that component than their should have been. All useEffect and useState does is turn pure functions into mud that reads like a class but drops all the syntactic sugar that makes it readible.
> * Accurately model component as being in multiple states at the same time for concurrency. (Important for future React features.) Closures can do that because they capture specific props and state.
Besides this not making any fucking sense, why don't you call new and leave me out of it?
As a user, Why do I need hooks today?
> Finally there are some difficulties related to optimizing class code at compilation time. Such as inlining and fusing classes together. Functions make this simpler and they also minify better due to safer mangling.
>In the mixins are considered harmful blog the point is made that sharing logic between components is a mistake and you should be using composition to achieve the desired outcome. Why do I need hooks? Is composition considered harmful now?
Hooks are composable, unlike mixins. That's pretty much their whole point. Hooks are functions so you can pass values between them.
Consider that reading everything with a cynical mindset might be obscuring the design. I encourage you to play with it a little bit to get a feel for it.
>If splitting your logic into lifecycle methods was too disjoint there was way more going on in that component than their should have been.
Dismissing them as unnecessary doesn't really point to any concrete solutions so it's hard to debate.
>Besides this not making any fucking sense, why don't you call new and leave me out of it?
Sorry, I don't know what you mean by that.
I tried to answer your questions the best I could. It seems clear that you don't find Hooks useful. That's cool.
I'd be happy to continue this discussion but I'd appreciate if you could tone down the aggression and snark a little bit. You seem to be very annoyed by our conversation, in which case I'm not sure why you talk to me at all. Answering comments like this isn't a part of my job, and I'd appreciate if you could at least talk respectfully even when you disagree. Thanks.
First of all I apologize. I wrote that late at night and couldn't really get out what I wanted to say down without the frustration but I also really didn't want to miss the opportunity to pick your brain on this. Its rare you get a chance to speak with the people who build these features.
> Consider that reading everything with a cynical mindset might be obscuring the design.
I was concerned about this, I have pretty strong criticisms about redux. Well, actually, I love redux, I hate that flux dictated its design choices and blurred its abstractions which eventually resulted in the mess you now see in "userspace".
> I encourage you to play with it a little bit to get a feel for it.
I plan to, I'm simply still not convinced they're a solution that has a problem to solve.
> Hooks are composable, unlike mixins. That's pretty much their whole point. Hooks are functions so you can pass values between them.
Hooks are composable, yes, well sorta, at the top level, in a certain order, but if I want composable components I cannot use them.
By definition, calling a hook within a function gives it state. Once it has state, that function is no longer pure.
At that point, you may as well just use a class object and instance, at least then you can separate logic from state in a clear language defined way. This is preferable opposed to in amongst a bunch of useThis and useThat callback hell.
But I'm wasn't really arguing they're not composable, they API is a bit meh but its workable. I'm really just saying they don't have a reason to exist in the first place: Why do I need hooks? or why did/do I need mixins? What is the use case they solve when I have a correctly designed composable implementation of react components?
>> If splitting your logic into lifecycle methods was too disjoint there was way more going on in that component than their should have been.
> I don't find this argument convincing.
What is not convincing? Why does logic need to be colocated further than it is unless there is more than one thing happening in the component confusing things.
subscribing to data - why would I want my presentation layer to be subscribed to data? The whole reason for binding data into the presentation layer via props is to avoid that proverbial shitshow.
form input - use browser builtins, if they don't work because react broke them then maybe react should fix them? or, you know, you just do what we all do right now - use a stateful react component class.
or animations - this smells like a jquery sales pitch. We don't need marquee, never did and never will. But see above, if it needs state, its a class.
I guess my confusion is stemming from the fact I don't see classes as a problem, or at least, I don't see pure functions as a sole solution. Pure functions solve a lot of problems by ensuring boundaries are correctly drawn and all state flows through props but that data needs to come from somewhere. Dropping state via hooks into things does the same thing redux does right now. Only hooks violate prop boundaries where as redux (correctly) respect them.
Personally, I would just fix redux if you have a problem with it.
> Sorry, I don't know what you mean by that.
"Accurately model component as being in multiple states at the same time for concurrency." - this is just words and needs a lot of context to unpack correctly.
(Important for future React features.) - As a user, I don't know or care about future React features.
Closures can do that because they capture specific props and state. - You know what else captures specific object state? Instances of objects. Call `new`, don't re-invent OO with pure functions.
All of which is besides the point ant still doesn't answer my question: What developer/user problem do hooks solve? Why should I use them as a developer? - opposed to refactoring into composable stateless components.
> I tried to answer your questions the best I could. It seems clear that you don't find Hooks useful. That's cool.
That's not quite correct I can see they solve the problem they set out to in an elegant, if kludgey, way. I'm just not convinced of their need (which still remains unclear and undefined)
Why do I need hooks? You keep falling back on framework or js reasons, these are not good enough reasons for a user to use, want, or even understand your new feature.
> All useEffect and useState does is turn pure functions into mud that reads like a class but drops all the syntactic sugar that makes it readible.
You've nailed it. Their solution to the issues with certain JS OO features was to re-implement Objects minus the features that were a problem, with new syntax. The code's worth a read for anyone who's read how the feature works and is still thinking "no, surely they didn't, it must work some other, magical way".
Hooks are a big deal if you use TypeScript with React. Explicitly typing the state is gone (it will be inferred by what you pass as initial value to useState()). So is weird Partial<TState> typings when setting the initial class state in the constructor or via this.setState().
And if you ever had to deal with correctly typing HOCs or render props you had to dig very deep into conditional/mapped types in TS. With hooks this is basically gone.
Yes you do, you have to give the type of the state in the 'extends' clause: 'class MyComponent extends React.Component<TProps, TState> { ... }'. If you omit TState, an empty object {} is assumed for state.
And you have to specify the type when updating the state via .setState(), because setState() auto-patches/merges the state. So its fine to pass a Partial<TState> to setState.
With Hooks, the auto-patching goes away, so your call to setMyCustomState() always requires an argument of type TState.
There are similar issues if you use the 'static defaultProps = { ... }' on a class - you have to manually specify the type of defaultProps - often it is Partial<TProps>
> With React Hooks, I do not need to deal with the messy “this” coding pattern of class components. And there are no three ways to write this code.
Yep. Now there are four.
I have no specific opinion about React hooks (or about love for that matter), but “languages” with a simpler vocabulary do tend to have an advantage in the long run.
Devs beware, hooks are not quite there yet it turns out.
You get warnings in jest about needing to use act from react-test-renderer if you use async code to trigger state updates - the solution being recommended currently is mock every promise with a synchronous version, which then litters your app code with conditionals in many places for whether to use the mock or real promises. At that point, you're much better off using Angular for writing decent component/unit tests, where you don't have to fight with any async DOM or JS api in order to write working tests, or pollute app code with test specific branching logic since that is all handled at a single injection point via the IoC container.
If you have promises, you're forced to bleed a isMounted type of flag into the cleanup function scope in order to guard against promises attempting to trigger state changes after the promise is complete with its async function (i.e. data fetching).
These are two frustratingly painful dev ergnomoics situations that are unsolved with hooks. Otherwise, I am happy with them, but these are major pain points I have encountered with them so far, and given FB doesn't use promises in their internal apps for the most part, I don't see them likely to put in much work solving these problems unfortunately.
Disclaimer: I would love to put in some effort to solve these pain points with design discussions & code, but unfortunately I cannot put in that work without going through approval processes with 5+ people.
>given FB doesn't use promises in their internal apps for the most part, I don't see them likely to put in much work solving these problems unfortunately.
This is inaccurate.
The first problem has an issue tracking it (https://github.com/facebook/react/issues/14769) and even a pull request (https://github.com/facebook/react/pull/14853). It’s barely been two weeks since the first release and we’ve been focusing on fixing actual bugs as soon as possible. As I hope you can understand, warnings in tests are a bit less critical and can wait behind production bugs. But we’ll get back to fixing the warnings as soon as possible — maybe even this week.
As for isMounted-like flag. This has nothing to do with Hooks. Classes need exactly the same thing. If you forget it, you’ll likely have both the same kind of warning, and possible race conditions from requests arriving out of order. In longer term we’ll offer a much simpler data fetching integration (read about Suspense) which doesn’t involve effects or lifecycles at all. I think you’ll like it.
If you can't answer that without talking about what react broke first I don't think we we need whatever you're selling.
Added responses there too.
I feel like hooks are a solution to shit code that just needs a refactor.
This happens a lot in frameworks that try to please everyone all the time. You give people of all experience levels the same feature set. It's no wonder at least half your user base goes out back and shoots themselves in the foot.
If you want to fix this problem you need to remove flexibility. Not give them yet another method to hurt themselves.
I'd start by splitting component concerns. MVC might be a good candidate. React.fragment components tend to smell like fat models. Pure functions basically views and connect code/prop/state mapping looks a lot like controllers.
Fwiw this small UI component thing is originally what the MVC pattern was intended for. The big laravel style classes we have today are a misappropriation of the patterns name onto something that it shouldn't have.
They give you the ability to reuse stateful logic between components. You’ll need to be more specific about why it’s an “excuse” to you. Lots of people seem to find this ability useful.
They're excuses because none of them involve explaining when, where and how they are useful to a user.
They all basically say "framework needs it" or "we heard you like functions, so now we're getting rid of classes and making everything functions, but you still actually need classes and state and all that stuff so we're shoving state into globally accessible static functions that you have to call in the same order every time or things just won't work."
Like this whole thing is just absurd.
> They give you the ability to reuse stateful logic between components.
Stateful logic a code smell, we do not want this.
Redux actually gets this stuff correct - binding logic and effects to props and state should be done outside of the presentation layer.
I would have just fixed the redux API so people stop shooting themselves in the foot with it.
---
In any case, thanks for your comments, this has given me a lot to think about, I'm now wondering about how to replace useState with a prop named state. I'm also wondering if bi-directional prop mutation would solve all this cleanly - i.e. bind props instead of passing them, I think KnockoutJS did something like this.
Calling classes messy isn’t really a strong argument. classes are one of the valuable tools in a programmers toolbox. Emulating them via a bunch of closures that act on shared state isn’t necessarily better.
Not only that, but classes are at odds with advanced render scheduling like React is moving towards (concurrency, prioritized rendering, context switching, bailing out of renders, etc.).
With a class instance, what happens if you need to bail out of a render and potentially restart it again later? The developer could have done literally anything to their class instance the first time through. They could be inheriting from anything and doing whatever they want to `this`. You can't easily "restart" it from its original state, unless you made a perfect snapshot, which is not easy with class instances – you'd need to perfectly deep clone the prototype chain and such.
With functions and hooks on the other hand, there is no class instance or prototype chain to worry about. All state (whether stored via useRef or useState) is controlled by React – the actual object it gets stored on is hidden from the developer. If React wants to ditch the "instance" it was updating on the previous attempt and reuse the one it started with, it can do that without worry.
It's the same reason "time travel" features are easier with more functional approaches. Adhering to functional programming ideas pays off in the long run.
As a developer of a extremely large code-base written in Rect (https://launchpad.secapps.com for reference of the kind of apps we are talking about), I am not convinced that "Hooks" solves anything in particular that it is not already solved through decorators. We use decorators quite extensively, from assigning styles in a way that does not force the component to re-render due to props changes, to controlling the props themselves with onChange events and so on.
In my professional opinion, which is based on years spending time with react, the typical gotchas in this framework are down to experience. Experienced react, and more importantly js, developers will write better, more performant code. This is applicable across the board regardless of the framework/language. Hooks will not particularly remove this need nor will make you a better programmer.
While hooks look functionally ok what worries me is that they will be subject to a number of problems. For example, complex hooks/components might be subject to memory leaks. With hooks, we are defining closures inside the functional component which will be subject to having access to proceeding scopes. This is an anti-pattern that we removed from our code-base by using classes. The second problem is that your component will needlessly re-render in those cases where the component is not entirely functional. This may not seem like a problem in the simple examples seen thus far, but it will be with more complex components as I've seen in my experience.
React is one of the best frameworks we have seen around so I am happy that we keep pushing the boundaries but what worries is me is that the React team seems to declare that they are moving towards components written with hooks (not removing classes) which in my opinion is not based on solid evidence that will amount to anything useful in particular.
Again, as far as I am concerned, hooks does not contribute to anything that we are not solving in much better way and I doubt they will ever be used at all as far as our code-based is concerned.
While I don't disagree with you generally, this part
> The second problem is that your component will needlessly re-render in those cases where the component is not entirely functional.
is addressed by the react developers in the FAQ [1].
The answer wasn't obvious to me, so I made a toy example in CodeSandbox [2]. There are 3 counters that can be updated using 3 corresponding buttons. Each counter uses a different approach:
1. The "handler" counter uses "useState" + "inner function in the parent's body". The corresponding button rerenders every time the parent rerenders (i.e.: the problem you are highlighting)
2. The "callback" counter uses "useState" + "useCallback" to memoize over the counter's value. The button rerenders only when it is clicked (and hence the counter it controls is updated).
3. The "reducer" counter uses a react context to inject a "dispatch" function that calls an out-of-parent reducer. The button never rerenders. The docs are clearly pushing the reader towards this solution (albeit it is contrived for very simple examples such as this one, I can see the benefits surpassing the boilerplate overhead of reducers in more complex situations).
Part of the point of solutions #1 and #3 is that they pass in exactly the same function on each render, so it's possible to avoid unnecessary rendering further down by knowing that the props are the same as before. The hooks solution will make a new handleChange closure each time, so it'll be a different function. Is there are way with hooks to pass the same function each time?
Hooks seem great for simple usecases but I can't see how you'd not end up with a mess once you have 3+, and since most components inevitably gain complexity, why use hooks to start with?
I think the `useDarkMode` example is awful. Disregard it. And probably disregard this as well since I most likely don't capture what makes hooks so nice from a development perspective:
I'm currently rewriting my product's rich text editor in SlateJS and hooks and they're making customizing the editor much easier that was possible with class based components.
SlateJS has a concept of plugins that you can pass to the base editor to customize behavior. For example, I can write my own "AutoCapitalize" plugin that will auto-capitalize the first word of each sentence. Or maybe a "Highlighter" plugin that highlights certain key phrases in the text.
Some of these plugins need to read data from my store and/or call actions, and some don't. For the ones that do, I can instantiate the plugin with a hook (e.g. useHighlighterPlugin()), which nicely hides the fact that the plugin is hooked up to my data store / actions.
Why is this useful?
I have about 10 different text editors in the product, and each has a different set of plugins associated with each... I need to be able to mix and match them, reusing some the same plugins over and over.
Maybe one editor has a list of plugins: [autoCapitalizePlugin, highlightPlugin, spellcheckPlugin]
Another might have: [highlightPlugin, readOnlyPlugin].
Without hooks, to hook up these state and action dependent plugins, I would have to have higher order components wrapping each of these editors, each of these HoCs grabbing the different specific data / actions needed to make these plugins work properly, and passing this data explicitly to construct these plugins via props. Very difficult to reuse code this way.
I suppose I could write an HoC for each plugin, but then suddenly I'm wrapping my component in 10 HoCs for 10 plugins. Plus there'd be possibility for props naming collision.
It would have been impossible to both have reusability _and_ brevity without hooks.
Instead, I can just create the plugins I want declaratively using hooks:
Everything I tried before it (jQuery, Backbone, Knockout, Angular, Meteor (with Handlebars)) felt like it fell short or, in the case of the databinding-oriented ones, like a broken abstraction. I get a similar feeling when looking at Vue though I have no experience so I might be wrong.
I too am a bit skeptical about hooks making what looks like pure functions act like stateful ones. I am not using hooks yet but besides from Dan Abramovs excellent articles about their rationale, I think I will look at them like a new paradigm, only using a syntax that we know from something else. In fact, I wouldn't be surprised if I some time in the future will be using React to write state machines for something that doesn't have anything to do with UI, where "rendering" composes state related to something else entirely. I could see hooks being a game changer here.