
React is becoming a black box - keenondrums
https://jaredpalmer.com/blog/react-is-becoming-a-black-box
======
pcr910303
I think hooks aren't really making React more of a black box, but just that
it's invalidating a lot of people's incorrect mental models on how React
works. (It's like C's undefined behaviors in that sense.) And the reason why a
lot of people have these incorrect mental models is that React is a very thick
abstraction.

For a long, long time, I thought that to provide the values that React brings,
the UI framework being a black box is inevitable. Almost all React-esque
libraries including but not limited to React, Preact, Mithril felt like a very
thick abstraction over the DOM APIs.

But then I saw Crank.js[0], and that felt very intuitive and a thin
abstraction, while retaining the good parts of React-esque libraries. I don't
really know why it feels like that - I'm guessing it's because it uses native
JS features that you already have a good understanding instead of some magic
that happens in the React runtime.

I'm very looking forward to it, and I would like to urge everyone to try out
Crank.js if you feel that React is now not intuitive enough.

[0] [https://crank.js.org](https://crank.js.org)

~~~
candiddevmike
After using hyperscript via Mithril, I don't think I can go back to writing
JSX. Hyperscript should be the defacto way to template HTML in JavaScript in
my opinion, it's just so much cleaner and readable.

~~~
kgwxd
To me Reagent is the ultimate answer to the markup/code mix. A single
language, ClojureScript. Nothing is done in strings except text. I absolutely
love it, but haven't been able to use on a production project yet.

[0] [https://github.com/reagent-
project/reagent#examples](https://github.com/reagent-project/reagent#examples)

~~~
aidenn0
I really like clojurescript in theory, but have a dumb practical reason for
not being able to use it. I do a lot of programming in common lisp, and am way
too used to a lisp-2.

I literally can't write more than 100 lines of clojure without accidentally
shadowing a function binding with a variable binding. I think the only way to
break the habit would be to abstain from common lisp for 6 months or longer.

~~~
narwally
I have the opposite issue trying to write in emacs-lisp after doing lots of
clojure. I try to:

    
    
      (mapcar my-func my-list) 
    

and it throws void-variable and then I remember that I have to add the #'
reader macro to have it read as a function not a variable.

    
    
      (mapcar #'my-func my-list)
    

It just takes some time to switch the mental model over each time. Clojure did
get me in the habit of using unique names for all functions and values because
accidentally shadowing a function binding is that more difficult mistake to
debug.

In practice I haven't missed the flexibility of a lisp-2, if anything it's
just made my code more readable because my names are forced to be more
descriptive

------
ritchiea
This is the kind of post that suffers from lack of specific examples. I would
love to see an interesting discussion of how hooks are not in line with most
developers mental model of React and what problems it's causing (if that is
indeed true, or at least true in the eyes of the author). But this post is far
too generic to illuminate what the real problems are or convince me that there
are any.

~~~
Exinferis
Although the article is too generic, or not detailed enough regarding examples
of what he states, I have to agree with what he is trying to say. React hooks
are a mess, or at least code based around it tends to be. We have had our
share of hooks based applications and they've become unmaintainable when
reaching a certain size and I am glad that we are back to class based
components wherever we can. In may opinion this comes down to the fact - as he
states - that the mental model (what will happen, when I do this) is not
simple to grasp, thus not predictable for many people.

~~~
alfonsodev
> React hooks are a mess, or at least code based around it tends to be.

I've read a lot warnings about the pitfalls, and about hooks not doing what
you think they are doing, but honestly, I haven't experience any of that,
maybe because my use cases are so close to the documented ones, that I don't
need to stretch the concept, and it just works as intended for me.

Could it be, that as with many other programming patterns, some developers are
using it as a silver bullet, and trying to solve everything with hooks?

Otherwise I'm failing to understand, it would be useful to see examples as the
mentioned above.

~~~
emerongi
Hooks are a bit of a double-edged sword in my opinion.

On the one hand, they are nicely composable. You can make one hook call depend
on another and you can easily build a lot of cool functionality thanks to
this. On the other hand, you are no longer able to directly follow the flow of
the code. Making a change to a series of hook calls can sometimes be scary to
me as it can be hard to fully understand the cause-and-effect of that change.

On the one hand, you can hide a lot of complexity behind a simple
`useSomething()` call, on the other hand the code inside `useSomething()` can
be absolute horror, because all the stateful logic is handled through hooks.
Any non-obvious use-case ends up being a mess of hook calls. If you only write
the code once and never need to touch it again, `useSomething()` can be an
amazing hook though. There are some hooks that I have written that I hope I
(or anyone else) don't ever have to touch. I might just be a bad programmer
though, or missing some obvious patterns.

TLDR: hooks work well, but they have downsides in terms of maintenance burden

~~~
ssijak
On the other end you can compose class components which have lifecycle methods
which you need to jump through up and down the code to figure out the full
behavior. Which to me is much more unreadable than hooks and effects. Not to
mention that lifecycle methods have their own gotchas.

------
rglover
This is a symptom of a lot of developers thinking they have to write code
exactly like everyone else (or at least, strictly adhere to "best practices").
It's a very subtle disease, but I've noticed it again and again over the
years.

Reading between the lines, this is a criticism of hooks if they're viewed as a
wholesale replacement for classes; from experience I'd argue they're
not—they're just a convenient tool for simplifying common patterns. I'd
imagine the author knows that to be the case and instead of just using classes
where appropriate (or where they wanted), they had to rationalize using hooks
because of the aforementioned "but everybody else is using hooks" problem.

I suffered from this behavior for years before I realized it was impeding my
work. The term that came to mind for the phenomenon was "The Invisible
Developer:" a non-existent developer sitting over your shoulder always judging
you for your programming choices. That developer doesn't exist. If instead how
"in fashion" your code is is the standard on your team: you're on the wrong
team.

~~~
stefan_
That's not a developers fault, that is the insane JS ecosystem. Every year,
everything old breaks and everything new is different. Of course no one can
keep up, develop intuition and good practices, so all that's left to do is
copy. That is how learning works, only the curve never flattens (and nothing
is really learned, nothing is gained).

~~~
rglover
That's just the illusion that's created by the inexperience of most JavaScript
developers. You don't _have_ to continually learn the bleeding edge stuff.
What they don't tell you (arguably, because it doesn't pay their bills) is
that what you should learn is the language. Once you understand that, you can
comfortably adapt to any new library/framework/whatchamacallit relatively
quickly.

Most of what you've described is just peer pressure. The only reason I know
that is that I shared this exact opinion until I said "this is stupid" and
started doing things my own way (to much success and peace).

~~~
perlgeek
> Once you understand that, you can comfortably adapt to any new
> library/framework/whatchamacallit relatively quickly.

I disagree. If you know typescript, it's _still_ quite a leap to be able to
code with angular, and debug weird stuff where you stare at a blank page, and
the back trace in the dev tools include not even a single line of code you
wrote.

Also, the language isn't really enough. You need to be familiar with the
tooling (npm/yarn, babel, whatever) to use most libraries; so unless you do
everything from scratch, you have to deal at least with the churn of the
toolchain.

------
eiriklv
Hooks are both a blessing and a curse.

The most telling difference after starting to use hooks when working with both
junior developers and more seasoned ones is that code that seemingly (and
intuitively) behaves in one way actually does something slightly different, or
worst case - something entirely different. Most often the culprit is a
combination of the hooks themselves, the rules and the more general issue of
the dependency array and lack of built-in immutability in the language.

This happened before hooks as well, but the class syntax and lifecycle methods
felt like a thinner layer on top of JavaScript. Hooks is a much more
proprietary concept that tries to solve a much wider problem - having stateful
functions, except they make no sense outside the realm of react as they exist
right now. Maybe some form of implementation using generators would bring it
closer to the language, but that would most likely introduce it’s own set of
challenges.

Don’t get me wrong - I enjoy working with hooks, but it just doesn’t feel
quite right that they are so tied to some «magical» implementation that
requires a large set of rules to behave as expected. It helps to look into the
implementation, and especially to reimplement a simple version of react with
hooks yourself - but that’s just not a realistic option for many.

Kudos to all the innovation coming from the React team and community though -
I’m sure they think about this stuff all the time.

~~~
ceedan
Well said. I like the idea of generators if possible, but have no idea if it
actually is possible.

> they are so tied to some «magical» implementation that requires a large set
> of rules to behave as expected 100% agree here & with your sentiment about
> the Class API

~~~
mrloba
I tried this, and it's possible using a monadic interface. Just like replacing
promise.then with async await you can replace monad.flatmap with generator
yields. But I've already seen this concept discussed by the react team and it
seemed they didn't like it.

What's cool with a monadic interface is that you can create lots of other
interesting things, as long as you adhere to the interface. For instance, I
think it's possible to achieve something similar to async render functions
without specific support for it.

------
schwartzworld
Every time I see one of these posts glorifying class-based components and
shitting on hooks, I always come away with the same impression: this person
doesn't understand what hooks are for.

There are plenty of examples where a specific interaction might be more
'intuitive' in a class-based component, especially to someone who knows the
lifecycle methods well, but class components had a tendency to become very big
with lots of instance methods and be responsible for too much.

React has always had an eye towards being pure functional, preferring that you
hide your application logic in pure functions, but when you're dealing with
complex interactions that rely on various combinations of state and props,
there wasn't an easy way to abstract that away. Forget about DRYing out your
code base, it was really common to see identical functions in
`componentDidMount` and `componentDidUpdate`. Hooks represent a way of
removing complex behaviors (that can't be represented as pure functions) from
the component altogether.

A lot of people _consume_ hooks, and these are the kinds of usages that people
are really complaining about. Components with 3 or 4 or 10 useState,
useEffect, etc at the top. These behaviors get copy-pasted all over the app.
They are hard to reason about in the same way that code where you never wrote
any functions would be hard to reason about.

So yeah, you have to get used to thinking with hooks, just like you have to
get used to thinking with pure functions. Sorry you had to learn something
new.

~~~
mplanchard
Hooks are not pure functions, though, or purely functional. A function that
returns different results when called with the same arguments is not pure in
any sense. One of my biggest issues with hooks is that they make it difficult
to reason about which functions are pure and which are impure. Just because
it's using functions doesn't mean it's functional.

See for example this comment [0] from the hooks RFC discussion how they could
have been made more functional.

[0]:
[https://github.com/reactjs/rfcs/pull/68#issuecomment-4331556...](https://github.com/reactjs/rfcs/pull/68#issuecomment-433155682)

~~~
yazaddaruvala
Hooks definitely meet the dictionary definition of the term “functional
programming”.

Like Wikipedia states, you’re conflating “functional programming” with “pure
functional programming”.

[https://en.m.wikipedia.org/wiki/Functional_programming](https://en.m.wikipedia.org/wiki/Functional_programming)

~~~
flowerlad
So is C language a functional programming language?

Definition of functional (from Wikipedia page you linked to): _In functional
programming, functions are treated as first-class citizens, meaning that they
can be bound to names (including local identifiers), passed as arguments, and
returned from other functions, just as any other data type can._

In C language you can do all that. But C is not a functional programming
language at all. Neither is Hooks functional. Even assembly language has
"functions" but it is not a "functional language".

~~~
Summershard
C is a FP language. So are C++, C#, Java and JavaScript.

They're not _functional first_ like F# or Scala.

A programming language can embrace multiple paradigms.

~~~
flowerlad
> _C is a FP language._

Well then so is assembly language.

------
kin
I don't think it's becoming a black box at all. Classes were more intuitive,
sure. But, they really allowed you to write some gnarly and inefficient code.
I've always felt that React lets people get away with not fully understanding
JS fundamentals. It's very apparent when dealing with some bootcamp devs who
never had to write production vanilla JS. One example is that you can get away
with not fully understanding that with classes you're dealing with different
instances of objects.

Understanding hooks did take effort. Only after I read Dan Abramov's article a
few times was I able to write hooks w/ deterministic results. It is a MUST
read. Don't let these Medium authors you've never heard of confuse you with
their understanding and basic examples. [https://overreacted.io/a-complete-
guide-to-useeffect/](https://overreacted.io/a-complete-guide-to-useeffect/)

To me, understanding Hooks feels exactly the same as learning Physics in high
school. You not only have to keep track of variable scope in your effect
callbacks. You also have to keep track of function iteration. All the
variables in your dependency array are like variables in a physics function
and as they change so too do the variables you reference in the function
scope.

~~~
artemave
> Understanding hooks did take effort. Only after I read Dan Abramov's article
> a few times was I able to write hooks w/ deterministic results.

A tool for building web pages that requires that level of effort to learn it
is not a good tool.

~~~
kin
Having worked on large scale production apps through jQuery days, Knockout,
Backbone, Angular 1, and now React, I still think this is the best tool for
the job. What do you use?

I don't think spending a few hours to fully grasp an article should be the
metric to deter someone from a good tool.

~~~
artemave
[https://hyperdom.org](https://hyperdom.org)

------
eric_b
React was always a black box, more or less. To me, what happened was the React
team decided boilerplate was worse than cognitive load and the _appearance_ of
simplicity, and changed the framework accordingly.

Class components are easy to understand and reason about (mostly) - but they
result in a lot of boilerplate code for simple functionality and event
handling. Hooks, to me, are the opposite. They have all kinds of limitations
and footguns which you need to be aware of (yes linters help) but they give
the code a much cleaner appearance.

I personally prefer obvious boilerplate over clean aesthetics but I know lots
of people who prefer hooks. I've sinced moved to Preact and have not missed
real React once.

~~~
ng12
I'm not sure if I would describe it as boilerplate because it includes very
real cognitive overhead. The best example is the lifecycle methods: if you
access a prop in componentDidMount you need to remember to handle what happens
if that prop changes in componentDidUpdate. It was incredibly easy to write
broken components using the class API and much harder with the hook API.

~~~
sktguha
couldn't you just write the same function to handle the prop in both
componentDidMount and componentDidUpdate ?

~~~
ng12
Sure, but you still have to know to do that and to do it correctly by checking
whether the relevant values have changed in componentDidUpdate.

------
tabtab
Too many things in web-ville are becoming black boxes, or at least dark-grey
boxes. ORM's, route mappers (with URL beautifiers), most "progressive" UI
kits, etc.

This is usually "solved" by hiring technology-specific specialists to focus on
each mystery meat layer. The result the same kind of application takes TWICE
the resources that it did with simpler tools of the past. (I don't know if
they were simpler, they just were a better fit for business CRUD itself, web
is not, it originated for static documents.)

"The web" may have simplified deployment (installs & updates), but it
complicated everything else. I don't even know that it's either/or, we just
need better standards, such as a stateful cross-platform GUI markup language.
Businesses don't really need or use mobile-centric UI's for their
productivity-oriented applications. Progressive (mobile) UI's are a solution
looking for a problem, in the business world.

Some architects say "choice is better", but that choice seems to be costing
the business dearly. There may be bias in that complexity and confusion
benefits technicians more than businesses. The "mono-culture" IDE's at least
got shit done without an army to manage all these "organic" web layers.

We de-evolved. Ooga Booga.

~~~
jordache
>The result the same kind of application takes TWICE the resources that it did
with simpler tools of the past.

what is an example of a simpler tool? .net Winform?

~~~
tabtab
Visual Basic 6, Delphi, PowerBuilder, Paradox, Oracle Forms, etc. They had
warts, but generally got better after each release.

~~~
jordache
VB6 is terrible. I much prefer the current front end landscape rather than
that

"Dim it up!"

~~~
tabtab
For who? Its bad points were mostly fixable. MS just stopped working on it an
threw out it.

~~~
jordache
for everyone.. terrible IDE that is more suited for simple scripting, than the
complex client logic that exist in today's webapps.

Terrible language. End Sub as opposed to curly braces? Really?

~~~
tabtab
Example "complex client logic" that we can analyze here?

As far as programming language syntax preferences, that's a different subject,
and largely subjective.

------
ehnto
Maybe I am being naive, but I'm just not sure what people are building with
React that requires such heavy focus on optimization that we're starting to
look at Concurrent Mode. Is it an issue with React performance, or are we just
asking the client devices to do too much work? React is a UI library after
all, how complex does a UI need to be before you run into performance issues,
or is it that the UI framework is doing work outside the scope of a UI?

I understand less capable devices is a concern as well, but that just makes me
wonder even more why people are building such taxing applications with React.

PS: Please contribute to the conversation, I'm genuinely curious, this isn't
my area of expertise. If you're sending a downvote, spend a moment to tell me
why I'm wrong.

~~~
lhorie
The fundamental problem with UI frameworks is figuring out what to re-render
based on some event, while also providing a declarative view of the code to
the developer.

Some libraries optimize this via micro-optimizations (e.g. inferno is
carefully crafted so that browsers use the hidden classes optimization nearly
all the time). Some libraries do this by compilation (e.g. svelte takes
assignment expressions and rewrites them into a reactive trigger call). And so
on.

The problem though is that no matter what the framework does, there's no way
to render 1 million things in a page all at once (and yes, people do try
that). On a fundamental level, doing anything a million times synchronously
will block the main thread (javascript is single-threaded, you see).

In the mithril.js community for example, the solution is to say "well, don't
render 1 million things, use pagination or occlusion culling or search or some
other mechanism since no one's ever going to meaningfully interact w/ 1
million UI elements simultaneously anyways". In the React world, concurrent
mode is a technical attempt at addressing that same issue.

There are various different use cases that fall within concurrent mode's
scope, e.g. avoid stuttering animations (the mithril.js community answer in
this case btw might be "well, use CSS" or "use lifecycle events and vnode.dom
to drop down to vanilla JS").

The React team is corporate-sponsored, so they solve problems in very
different ways that an OSS project run by volunteers.

------
b212
I wrote a few huge class component-based Apps in React and they were working
like charm and were very maintainable even for junior programmers. A few days
with Redux and development was as easy as in jQuery days.

Then we hired a few front-ends who started pushing functional components where
possible as it became the new paradigm and recommended way of writing React
apps. From my perspective there is absolutely no difference between class and
functional components, class is a few lines longer and it's supposedly harder
to test but I don't know exactly why because testing classes was never an
issue.

A few months passed by and maintenance became a headache because suddenly
functional component X, Y and Z needed lifecycle methods and those were only
available in class components! But class components are bad, right? So let's
update React and use newly introduced hooks.

Now instead of me and 2 juniors you need 10 seniors to maintain the apps,
nobody knows what does what, it's a nightmare. Class based components and even
everything redux-related is much easier to comprehend than small logic in
hooks. It's extremely easy to write unmaintainable code with hooks.

~~~
foofoo4u
Yes, I am experiencing similar issues as well in our codebase. Half of it is
class based while the other half is now in hooks. Apparently classes are now
"bad" and therefore it should be immediately abandoned. Unfortunately this
leaves us with a fractured codebase. The real pain to productivity comes when
trying to onboard new developers. They have to now double their learning
efforts by having to understand two programming paradigms. It's easy for them
to get confused and intimidated. I don't blame them. Even I hit some level of
mental fatigue of having to remember how things are done when switching
between the two. What I dislike and don't understand is the lack of discipline
developers have to stick with an existing library or framework. This desire to
constantly hop to the next latest thing — in this case classes to hooks — ends
up fracturing the codebase, making it more difficult to understand and manage.
For what? A trivial gain in supposed productivity? Perhaps writing the hook
itself versus a class is indeed more efficient, but the fracture in the
codebase it brings, I believe, ultimately brings a net loss in productivity.

Anecdotally, I am starting to get more used to hooks, but I'd prefer to go
back to classes if I had the choice. I found classes are much more explicit on
what is going on, especially when trying to understand the various states of
render cycles. What's happening in the cycle in hooks is challenging to me.
There is also a proclivity to accidentally introduce infinite loops with
hooks, which was a rare problem when dealing with classes.

~~~
crooked-v
> There is also a proclivity to accidentally introduce infinite loops with
> hooks, which was a rare problem when dealing with classes.

That makes me quirk an eyebrow. Somebody's doing something fundamentally wrong
in how they're writing the component if they're making an infinite loop happen
with hooks.

~~~
acemarke
I'll disagree with this a bit.

It was always possible to do this in class components if you had some kind of
a `setState()` call in your `componentDidUpdate` method. But, this was a rarer
stumbling block.

On the other hand, with hooks:

\- Effect hooks always run after render by default unless you specify a deps
array to limit how often they re-run

\- It's fairly easy to queue a state update that changes one of the values in
your deps array, causing the effect hook to immediately run again

So, it's "fundamentally wrong" in that it's a thing you don't _want_ to do,
but it _is_ a lot easier to make that mistake now.

~~~
crooked-v
If you're using setState in useEffect directly in a component then you're
probably doing something wrong. All the valid use cases I can think of for
functionality like that should be using a wrapping hook function, rather than
re-implementing functionality separately in components.

------
franciscop
I highly recommend this talk (first half) for a great introduction of how
React Hooks work internally, Ryan remakes the basics of hooks from scratch in
30 min:

[https://www.youtube.com/watch?v=1jWS7cCuUXw](https://www.youtube.com/watch?v=1jWS7cCuUXw)

I agree on 2 of the points of Jared Palmer but disagree on one:

\- [agreed] The new "Concurrent Mode" will take things to a new order of
complexity. I am actually very afraid of this, it seems like one of the things
that might actually kill React, and I love working with React. I like it so
much that I've invested into creating few React libraries to make my life
easier.

\- [agreed] React Hooks are difficult to get started with and to really
understand them. IMHO this is mainly due to "React lifecycle", which is just a
difficult concept (even with classes!). Life is not easy, and there are some
times that there's complexity and you need to learn new complex concepts. No
issue here IMHO.

\- [disagree] React Hooks is currently magic. While it's a complex piece of
software with many small details, once you understand fairly well the
lifecycle (and React docs are great at this, and Dan Abramov's
[https://overreacted.io/](https://overreacted.io/) digs a lot deeper for the
curious) all bugs are very clear.

I am currently mentoring someone in React who already knew HTML+CSS+JS, my
recommendations are: get used to the syntax by practicing, learn the 3-4
typical libraries, and learn very well the lifecycle including how useState's
setState and useEffect's dependencies work. That's most of day-to-day React
work.

------
woofie11
I think the problem is not so much with the React architecture, but with the
culture of JavaScript, which:

* does a horrific job with documentation

* delivers millions of packages with demo-grade half-finished projects

* has tutorials which show basic functionality, without going into any sort of depth, which people glue together by pattern-matching

That doesn't work well in general, but for something as complex, deep, and,
well, architected as React, it doesn't work at all. People really do need to
understand reactive programming, functional programming, and deep concepts to
handle React well. Resources to do that don't exist.

This is the claim for React's documnetation:

" __ _The React documentation assumes some familiarity with programming in the
JavaScript language. You don’t have to be an expert, but it’s harder to learn
both React and JavaScript at the same time.

We recommend going through this JavaScript overview to check your knowledge
level. It will take you between 30 minutes and an hour but you will feel more
confident learning React._ __" source: [https://reactjs.org/docs/getting-
started.html](https://reactjs.org/docs/getting-started.html)

Really? Read that again. REALLY? Someone with 30-60 minutes JavaScript
programming is expected to code in React?

That's the target audience of most of the docs, and nothing goes far enough to
get people qualified to use the tools. It becomes a magical black box. The
posts in this thread show this attitude too: " __ _You don’t really need to
understand how React works, you just need it to work_ __"

~~~
mpalmer
> People really do need to understand [...] deep concepts to handle React
> well.

"Handling React well" is subjective. What are you building?

> but for something as complex, deep, and, well, architected as React

I'm not sure what "architected" means in this context. But re: complex and
deep -

React is complex to the extent that you need to build complex things. It is
deep to the extent the developer requires. This is a great aspect of its
composable design - it's just components made of components made of...etc.

But people don't learn React by building huge, complex, deep things. They
build simple things, and go from there. In this respect, React does a great
job with documentation. They start small.

~~~
woofie11
It's deep and complex in the same way Lisp is deep and complex. Or if you
don't know Lisp, a weaker analogy is Go.

I'm a huge fan of React, but without understanding of why it is, people use it
wrong all the time.

------
Merad
I like hooks and prefer them over class components, but I think this is a
problem. Almost every React developer I know has a poor understanding of how
hooks work because it's so fundamentally different from what they're used to.
In most simple cases (probably 90+% of the time) you can get away with a
flawed understanding of hooks; it doesn't typically bite you until you get
into trying to write custom hooks with complex logic and/or side effects. Dan
Abramov's dissertation on useEffect is a great example of how much complexity
is hidden behind what appears at first glance to be a simple function:
[https://overreacted.io/a-complete-guide-to-
useeffect/](https://overreacted.io/a-complete-guide-to-useeffect/)

------
brundolf
Is there anyone who would argue that React Hooks are "intuitive", or at least
become that way after you've used them for long enough? Genuinely asking.

I worked with React for several years and I've worked with the web for almost
a decade, but when hooks came out I immediately "noped" out of there. Not that
I couldn't learn them, but they just felt like a deeply contrived way of
managing state changes. I'm comfortable with a functional style for lots of
things, but when it comes to your actual core application state, FP has always
seemed very out of place to me. It's almost antithetical: FP's whole thing is
being stateless! It feels like a square-peg-in-a-round-hole situation.

By contrast, using something like MobX for reactivity combined with as-
stateless-as-possible class-based React components (and some totally-stateless
functional components!) was extremely easy to reason about and scaled really
well for us with almost no boilerplate.

I realize that doing something like concurrent-mode requires some unique
accommodations, but I just don't understand the big push for hooks. Do they
only exist because of concurrent mode? And if so, was there really no other
option for getting the same results?

~~~
kls
I agree, I think they took a left turn at Albuquerque trying to get into the
state management game and honestly saying this as a person that likes FP for
everything but UI components, I prefer objects when it comes to modeling UI's
it's the one domain in which it fits without impedance mismatch. The problem
is UI has state and state and it's management does not fit well with objects
as it tends to be event, time and data dependent.

There are some good solutions to state management that are complimentary to
React such as XState and it really should be dealt with as a separate concern
from a UI component library.

I am concerned that React's object based approach is going to become a second
class citizen in lieu of Hooks and that state management is going to get to
hardwired to the UI component library.

~~~
brundolf
Exactly. I'm a big believer that state-as-an-implementation-detail is a code
smell, but that if your program is fundamentally concerned with state (as UIs
nearly always are), you should equip yourself with tools that let you
ergonomically manage that state instead of trying to sweep it under the rug
and pretend it doesn't exist. Hooks feel like state-denialism to me.

------
wincent
Some related discussion from a few months back (specifically, a critique of
hooks):
[https://news.ycombinator.com/item?id=22995928](https://news.ycombinator.com/item?id=22995928)

FWIW, I think the single tweet that sums up the reason why hooks are the way
they are is this:
[https://twitter.com/sebmarkbage/status/1094093984211787776](https://twitter.com/sebmarkbage/status/1094093984211787776)

> A property of Hooks is that it forces you to confront them early and then
> you just learn patterns that don't have the same issues. I don't know if
> that is worth the tradeoff, but I stick to the claim that this is the
> tradeoff.

(That's Sebastian Markbåge, who's basically been chief architect of all things
on the core React team for the last 5 years or so.)

------
rvanmil
Our team has seen a boost in productivity thanks to hooks. It has resulted in
more straight forward and cleaner component code, making it easier to reason
about how they work.

We've been able to get rid of a lot of annoying and confusing stuff when
working with class-based components (though perhaps not all of that was
related to hooks but also due to early React boilerplate/tutorials which may
have proposed things which are now considered bad practice even with class-
based components). No more componentDidThis componentWillThat but a simple
effect api (the cleanup function can be a bit confusing at times though). No
more unclear setState calls but clear and logically separated state updates.
No more class method callback binding hacks but simple functions. No more
`this` confusion. No more "Pure" and shouldComponentUpdate confusion but a
simple memo api. No more weird Redux 'connect' biolerplate but a simple select
and dispatch function.

As far as our team is concerned, React has always been a black box and it has
helped us a lot being productive. Perhaps it has become harder to reason about
how React itself works, but it has definitely become easier to reason about
the components built with it.

------
davnicwil
The best way of thinking about hooks I've seen is they're an attempt to
describe all possible states of the component at once, right in the render
function.

Instead of tracing through various imperative lifecycle handlers to see how
side effects are handled, you have them all in one place. It's kind of a
declarative(ish) approach to side effect management.

I personally like hooks and think they achieve this goal pretty well. The API
is good, the abstraction maps over decently once you've grokked it (though
this is honestly non trivial), and they end up simplifying 80%+ of common
usecases.

 _But_... I think it comes with a huge caveat. To consume, hooks are much
quicker, easier, cleaner, etc. To write, I'd say less so. The problem is that
in order to write and debug custom hooks, you have to deeply understand _both_
the underlying component lifecycle model _and_ the mapping onto the hooks API.
This naturally makes creating, modifying and debugging hooks that bit harder
than working directly with lifecycle methods in the class model, where there's
one layer less of abstraction to deal with.

------
sunaurus
I've used hooks in 3 different teams now, each team had engineers who weren't
really familiar with React before using it with hooks.

The only thing I've noticed is that built-in hooks with dependency arrays
consistently caused confusion for newbies - for some reason, people aren't
used to thinking in terms of "call this function every time this data
changes", but they are very used to thinking in terms of "call this function
on initial page load" for example. The second way of thinking will probably
lead to bugs or just weird code. Other than that (relatively tiny) hurdle, I
don't think I've noticed any other common issues with understanding hooks.

I would be very interested in hearing specific examples of cases where hooks
have worked in confusing or unexpected ways.

~~~
ZephyrBlu
I think the paradigm of thinking in terms of your data rather than your code
is what throws a lot of people off with hooks, but it makes infinitely more
sense to me.

------
satvikpendem
I've been following a Github issue about hook support in Flutter, and I
understood React hooks much better after reading that than I ever did before.
It is clear now what exactly the problems hooks solve are, composable life-
cycle state reuse. I think that because most people don't really understand
why hooks were even needed, they can't wrap their minds around them.

[https://github.com/flutter/flutter/issues/51752](https://github.com/flutter/flutter/issues/51752)

~~~
Izkata
...That doesn't clear up a whole lot for me. Keeping in mind I know React but
not Flutter (there may be details that make this inaccurate for Flutter):

> Reusing a State logic across multiple StatefulWidget is very difficult, as
> soon as that logic relies on multiple life-cycles.

The logic should be inside StatefulWidget, and StatefulWidget reused - so no
code duplication or hooking into the parent's lifecycle methods.

> A typical example would be the logic of creating a TextEditingController
> (but also AnimationController, implicit animations, and many more).

Looks to me more like TextEditingController should be turned into a stateful
component so it can be reused in the render - this lets the framework handle
its lifecycle and none of the boilerplate is necessary. I've done this a
couple times with variations on AnimationController: It uses
React.cloneElement on its children to pass down the appropriate state, and
because it was itself a component that simply rendered its children, React
handled all the lifecycle stuff within that component with no hooks to the
parent.

Quick edit: This reply in that issue is very relevant:
[https://github.com/flutter/flutter/issues/51752#issuecomment...](https://github.com/flutter/flutter/issues/51752#issuecomment-665380355)

I can here kinda see where it's coming from, but we've never had reason to use
hooks like that, so I guess I just don't see it as as much an issue. Also, a
very important part of it that some other comments over here seem to not be
aware of:

> In practical terms, there are a few things here. First, it's worth noting
> Hooks aren't an "extra" API to React. They're _the_ React API for writing
> Components at this point. I think I'd agree that as an extra feature they
> wouldn't be very compelling.

~~~
satvikpendem
The problem arises when you want to reuse a lifecycle function in multiple
Stateful or even StatelessWidgets. For example, if you go to the bottom of the
issue, I make an example where I needed to have an AnimationController with
complex initState and dispose methods. With hooks I could encapsulate all of
that and make it work with any Widget I wanted, I didn't have to rewrite it
each time.

There are a lot more examples, it is worth going through the entire ~250
comments, even though it may take some time. I only understood after doing so,
not necessarily by just reading the initial post.

------
krzepah
I haven't rushed out to hooks when they got out (i'm a preact user not react)
to the point that I got an intern tell me "Oh you don't use hooks, I'm not
used to work like that".

After digging into them, they are a nice addition for some specific niche
scenario where the component is not using any kind of global storage. But from
the little experience I had, they bring almost nothing new (I could do the
same without them) and they are also kind of difficult to read.

If I had to put a ADR for it, I'd simply skip it trough and specify storage /
class components as being much better just because of readability and
consistency.

Now maybe they have some better perf but it seems to me they are an addition
that came because of the functional frenzy that react has gone trough.

Maybe we got too far, maybe we didn't really need them. Maybe they just look
cool.

In the end, i've replaced all my hooks with either GS or Component just
because I'm more confident about how my peers will be able to read the code.

~~~
mplanchard
I agree with your take, and what bothers me about hooks is that they aren’t
even “functional”. They’re making what otherwise look like pure functions into
stateful functions, whose return values can change on subsequent calls. This
could have been largely averted by passing a hook manager into component
functions, an idea that was brought up in the hooks RFC but rejected.

I prefer the class-based approach for stateful components because at least
then it’s clear that the component has some state it is managing and how.

------
irjustin
From my ultra naive perspective - this was always the case with me.

At the very beginning, Virtual DOM manipulation/management was beyond me. Then
they updated the engine to React Fiber. If I thought I understood anything
under the hood, I _really_ didn't then.

I believe the author is talking about tiny unexpected side effects as a result
of the complexity. Like on a particular hook, 1+1=2 out to 7, 9's. But if you
do it just in the right way, you'll get a weird side effect (i.e. 1.0+1=3).

This is a typical result of being a ultra power user and I feel the author's
pain.

FWIW, I don't think being a black box is bad. Kernels are black boxes, CPUs
are black boxes, to so many of us anyway.

The spirit of what the author is trying to make is - this black box isn't
completely predictable. It's only mostly predictable - it needs to get better
so everyone can rely on it.

------
thiht
At first I had the exact same reaction as the author. React hooks seem
obscure, and you can't understand what happens just by mimicking what you see.

Then I read the docs on React hooks and everything became clear.

Hooks are a new way to think in React, don't try to resist and learn it. Also
RTFM. The React official doc is amazingly clear and easy to read.

~~~
ZephyrBlu
I don't understand why people don't read the docs for everything.

For me, it's natural for the docs to be the first place I look and to be my
source of truth.

~~~
thiht
Because new features are often close enough to what we know that there's no
need to read the docs.

But when we come across a feature we struggle with, it's easier to blame it on
bad design than just reading the docs :)

------
royletron
This is kind of just explaining supply and demand. I would say a large
proportion of React devs just want it to do the things they need and easily,
and hooks certainly aide them. Sure if you need to dig a little deeper then
you find that hooks can be a warren of complexity - but nothing stops you from
approaching the code directly to understand more (and you can still use
classes). For me and my team we actually leverage the 'black box' nature of
hooks for the good of the team. Senior members can write high level hooks that
they understand and juniors can just use them in their components and not need
to go too deep too soon.

------
ricardobeat
It has always been a black box. Not a single one of the people I've worked
with over the past four or five years could understand or explain even a
fraction of React's internals. Reading the source is a massive undertaking. Of
course not every dev has to know the the tools inside out, but it was not
unusual to discuss the inner workings of Backbone / MooTools / jQuery / etc
back in their day and I think that made all the difference. We have Preact,
Riot, Svelte and many other options that are much more accessible, pick one
for your next project :)

------
ceedan
I agree.

I do not envy people struggling through the adoption curve of using Hooks. I
don't know enough about them to know how to "fix" them, nor do I have the time
to care about that problem - but I would love to see a different syntax,
abstraction, or some kind of guard rails around them.

I might be wrong, but it has always felt like scope & hoisting are the primary
language features that hooks operate on... both features that I prefer to
avoid.

Adopting them seems to require the same leap of faith that is required with
something far more complex like early angular versions. The "I don't get it
but I'll just follow the rules" kind of vibe... But the web community seemed
to understand and fall in love with Rx a few years ago, so I'm sure hooks can
become more well understood, too.

------
Waterluvian
I use React because it pushes the magic into a well tested library and out of
my code. React and hooks are great because they make my code so much less
magic-filled.

------
yepthatsreality
Probably more so that React is gaining complexity in order to lock-in with
features. I see a similar pattern with Jest and snapshots feature.

I guess the single boon to the lock-in theory is that JS devs will happily
spend time rewriting code to the latest, hottest framework.

------
cdelsolar
One of the things that I don't like about React applies to maybe all
frameworks. It's easy to get 90% of the way there, but the last 10% is the
hardest. For example, I'm building a real-time websocket app with React.
Everything seems pretty easy to build, I'm using hooks, React Router, etc. But
coordinating socket connections / reconnections / etc and fitting it into a
very functional paradigm is just very very difficult, much more than it would
be in a more straightforward library.

~~~
crooked-v
For that kind of thing, rather than tightly coupling it to your React tree,
you should have components that sanely handle each possible state (no
connection, connected but no data yet, new data available, stale cached data
available, etc), then have separate handling for the socket stuff that updates
data via a global store like Redux.

------
hitekker
In case it's not clear, the author is the maintainer of Formik, which is the
#1 form library for React. He's also prolific engineer who wrote a litany of
other JS projects and is an active contributor to the React community.

His opinions have weight to them, and they happen to resonate with my own
experiences.

------
dwhitney
"becoming" \- it has been since the beginning. You have to import the react
library or it doesn't work. You create classes but never instantiate them. JSX
is invalid JavaScript syntax. It's a veritable cornucopia of black box
features, with hooks being just the latest.

~~~
coffeefirst
But most of those are easily understood the second you say "Babel is going to
take the JSX, convert it to javascript, and expects React to be there." Is
that crazy? Sure, but it's also pretty easy to update your mental model for.

The most telling thing about hooks to me is that I need a library just to use
intersection observer, because the way you have to implement it to replication
the same 5 lines of code from vanilla js is so much more complicated.

~~~
dwhitney
Pure functions with clearly defined type signatures are always preferable, in
my opinion, because there is far less thinking involved. Elm's vdom is done in
this way, as is the vdom used in PureScript Halogen.

React is great, and groundbreaking, but with 20/20 hindsight, there are better
ways.

------
xrd
The corollary to all this. Companies with open source strategies should really
consider hiring and retaining good writers alongside the core developers. This
is the reason everyone thinks Dan Abramov created React, he is simply the best
communicator when it comes to explaining the mental models around React
development. You might have amazing technology, but if you have no one
advocating it in a beautiful and powerful way, it won't matter for adoption.
React is at a precipice for sure, and there are a bunch of great writers on
that team, but there have been a lot of good ones that left recently as well,
and that's something Facebook should strongly address.

~~~
sktguha
Funny enough, Dan describes explicitly in his bio that he is not the creator
of React

~~~
xrd
Yeah, I think it is his Twitter byline too!

------
sushshshsh
Can anybody offer a friendly explanation to me as to why it's not wise to
update the DOM directly?

I understand that React is supposed to be an efficient and "ergonomic" way to
develop for the increasingly complex array of devices out there in the world,
but I have had too many poor experiences with React to consider it better than
direct UI programming for my needs.

~~~
grzm
One of the motivations for using a virtual DOM as opposed to updating the DOM
directly is that DOM updates can be slow, with a minimum duration per change.
Applying changes to a virtual DOM can be faster for individual changes, and
then those changes can be batch-applied to the actual DOM, minimizing the
number of changes to the DOM itself. For larger client applications this can
be a win. Like all trade offs, the choice depends on the context.

~~~
ric2b
If that were true how would virtual DOM ever be faster than the DOM? It would
still have to update the DOM itself.

What V-DOM is trying to address is tracking what is changing in your
application so that it can modify the DOM on your behalf, simplifying app
development and reducing bugs, sort of like how a Garbage Collector manages
memory for you and gives you similar benefits.

Look at Svelte, it doesn't have a V-DOM and it smokes any V-DOM framework in
terms of performance.

~~~
littlecranky67

      > If that were true how would virtual DOM ever be faster than the DOM? It would still have to update the DOM itself.
    

It uses a very smart algorithm to diff two vDOMs (previously rendered vs.
newly rendered) and "calculates" a minimal* set of operations required to get
the current DOM (=prev. rendered vDOM) into the new state of the DOM (=result
from current vDOM render). Think in source code patches produced by tools like
_diff_ : A _patch_ between two different code tree versions can fit just a few
lines and is quickly applied against the tree, while shipping and writing the
full tree is more expensive.

*: ideally it would be minimal in a sense there is no smaller/faster representation, but thats of course not the case in real applications.

------
azangru
I wonder if we are starting to see the initial symptoms of a future exodus.
Exodus where though? I don't think Svelte is that place.

~~~
pier25
React growth has stalled for the past couple of months:

[https://npm-stat.com/charts.html?package=react&from=2015-09-...](https://npm-
stat.com/charts.html?package=react&from=2015-09-01&to=2020-09-01)

I moved to Svelte and I'm quite happy.

~~~
52-6F-62
Have you found any successful patterns outside of Sapper for SSR?

I was demoing Sapper for a side-project and didn't like how much of the server
work and routing was relegated to the folder structure. It might just be a
personal preference matter, mind you. That and I did find it a bit sticky to
get working with TypeScript and it would break frequently after adding that
in. So I nixed that idea for now.

Outside of the CLI being pushed so heavily for project structuring, I still
find Vue 2 to be one of the simplest to reason around.

~~~
pier25
You can set up your SSR project very easily.

I actually have a demo of SSR + hydration using Fastify here:

[https://github.com/PierBover/svelte-ssr-
example](https://github.com/PierBover/svelte-ssr-example)

No SPA though.

------
flowerlad
The JavaScript community is not very critical; we accept whatever framework
developers put out unquestioningly. This is how we end up terms like
"transclusion" and the community just laps it up. React started as a simple
and elegant library -- anyone with knowledge of basic JavaScript and HTML
could glance at the code and understand what it is doing. Sadly it has become
more complex since then, and I wouldn't be surprised if the next release has
"transclusion" and whatnot.

~~~
steveklabnik
"transclusion" was coined by Ted Nelson in 1980.

------
hinkley
A decade ago I decided that I should take longevity of team members as a
virtue signal on project health. Boy, was I wrong.

As a project maintainer, your facility with the codebase is entirely based on
long-term memory (unless you actively fight it). Every new important thing
about the code is just one more thing for you to remember, and you quickly can
lose sight of how many concepts you need to juggle to reason about the code in
a new-to-you scenario.

When that number exceeds short term memory capacity, you start creating an
underclass of developers (or worse, teammates).

It’s easier to prevent this than to fix it, and I’m still trying to develop
ways to determine if you’ve crossed that line. The best is always to sit and
watch people use the code and see where the struggle. Try to make that happen.
If you can’t, I feel like a good proxy is this: if there are features that you
get hives just thinking about how much code you’d have to change to get it to
work? You’re probably close to the line or over it. If you’re the only person
who doesn’t get hives? You’ve crossed over it.

------
DLA
Totally agree with this article. I am operationally allergic to complexity and
React us fully complex these days. Based on this pain I did an experiment with
a new application.

I just recently developed a complete 12 component app using AlpineJS ...
probably pushing the boundaries, but it's awesome!

Components have their own internal state and reactively update their part of
the UI using Alpine Directives. We have data CRUD ops with the databases,
dynamic tables, dynamic forms, UI panes with dynamic content, etc.

For updates across/between components, we use messaging between components
which also triggers reactive updates via updates to message receivers' local
state, as needed. QED.

Works beautifully and with 12 components on the SPA (and growing) this is no
Hello World or TO DO app. Not by a long shot. Oh, and for the win, no build
step at all. Just reload. Time to paint hovering at about 1.7ms.

Tech stack: Go web and API server. CockroachDB. AlpineJS. TailwindCSS and the
awesome TailwindUI components.

------
Sophistifunk
Hooks just aren't a good solution to most of the problems of front-end dev.
They're abstruse, hide implementation details that don't need to be hidden,
and make many common behaviours much more complicated to implement.

------
crispyporkbites
React is simple it's just a few hundred lines of code, it's easy to understand
in an afternoon. Just make sure you pull in a JSX transpiler, and something to
do your routing, oh and you'll want something to store your state of course,
don't forget that - oh remember to pull in the right version of the transpiler
that support decorators for your state management (you do know what decorators
are, right?). What do you mean you have a conflicting dependency in your
existing codebase? Just fork that repo and upgrade it, that won't take long
and cause a bunch of other problems.

------
dlandis
Reading through this thread seems to validate the point of the article. A lot
of people agreeing that hooks and other features are too complex or hard to
understand, and then just as many people arguing that they're actually simple
and make perfect sense if you can just manage to understand them properly.

This seems to happen in almost every discussion about react over the past
couple years.

My point is that I don't quite understand the purpose of arguing that
something is not complicated after so many people have struggled with it. I
feel like those people's experiences a priori proves it is a difficult topic.

~~~
TurningCanadian
Something can be difficult simply because it's new: there's work in learning
the new thing and updating old code even if the new thing is easier than the
old thing.

------
gregopet
As a developer with 15 years of JavaScript experience who has recently had to
learn React & React hooks:

They're fine, but weird. There's a lot to like in React, but I constantly
wonder whether I've joined a cult. Somebody learned a couple of cute tricks
and wants to use them _everywhere_, no matter if they fit the situation or
not. Because of this there are a lot of do's and dont's that probably could be
avoided with a different design. And there is a lot of gray area in between,
specific things the React manual wants me to avoid but in the end I cannot
(and I have to quote a whole lot of blog posts from various known React
developers to my code reviewer to prove they were really necessary).

Classes have their failings and inexperienced (or overzealous) developers can
often turn them into a big mess. These are also well known problems to the
computer science community that has come up with a number of ways to manage
the mess. Hooks are just a completely React concept where no previous
knowledge has any use. Despite looking innocent they have a load of problems
and peculiarities, just like classes and methods do. I constantly wonder why
they had to go and reinvent the wheel and currently still do not feel like it
was worth it.

Learning new things is great and I am glad I got the chance to learn React and
its hooks. Now that the project is slowly coming to an end however I am also
glad I will soon start learning something else, perhaps something a little
less specific to a particular ecosystem.

------
axegon_
It is true. Full disclosure - I'm very inexperienced when it comes to
javascript - it is on par with my German skills - I can do basic shopping,
order a coffee or get a bus ticket, get from A to B but that's it. But I do
feel like it's been a black box by design from the start. At the end of the
day, we are talking about transpiling code. Which is fine(depending on the
definition of transpiling to begin with). If we look at how C affected
Assembly, there's no question that the appearance of C skyrocketed the entire
CS field in general: Even the most basic of "hello world" programs is a
testimony of that. At this point Assembly is in the Cobol universe - a handful
of people know it to an extent at which they can work with it. But in the case
of React... That really isn't the case - the fundamental problem I see with
React(and the entire NPM universe for that matter) is that they try to make a
simple solution more simple by making it more complicated and convoluted. On a
more general note, the web is broken. It has gone against it's core principles
and design. HTML was meant to serve readable documents and that's it.
Javascript's purpose was to add some interactivity. But in this day and age,
according to reacters anyway, HTML is pretty much Assembly or Cobol, while
javascript is C. Which in theory sounds great as far as the analogy goes but
in the real world, javascript's purpose was never to take over. It's purpose
was to supplement. The flaws in React(and all other 5000000 frameworks) are a
symptom of it, not the cause.

------
anilakar
Being a "black box" is good. I don't have any expertise with React in
particular, but any complex enough framework will break down when you extend
it beyond the official documented APIs and start relying on undocumented
behaviour. Nobody guarantees it will work after the next version bump.

I'm speaking from past experience with Django. Years ago I naïvely made the
mistake of assuming that clean, readable source code in the framework implies
a contract between the API author and user.

------
nojvek
More than React I am excited by what Svelte is doing. No concurrent mode, no
super duper runtime magic that needs 1MB of runtime. It analyzes existing code
and figures out what uses what, and the code output is hyper optimized so only
the things that need to be changed are changed when a variable is set. Svelte
runs around react in terms of both startup and runtime performance.

It's like the difference between gas guzzling engine with 100 moving parts and
an electric motor with a fewer moving parts but way better mileage.

That for me is true brilliance and thinking of UI as a reactive thing.

Hooks is a giant mindfuck because you have state bound to functions, when
99.99% of your other functions behave like good ol' functions, take inputs
from params and return results. If you want state, classes are made to hold
state in a thing called `this`. This is how 99.99% of all things in JS work.

~~~
crooked-v
> 1MB

React is about 5 kb.

------
jtdev
I recently gave Ember (Octane) a try on a project and couldn’t have been
happier with the simplicity and productivity in comparison to React.

The React community seems to want to over complicate everything lately and
spend more time arguing about philosophy than getting shit done.

~~~
Mc_Big_G
I find it very, very sad that Ember lost the marketing war. It was painful to
work with for the first 5 years or so but then became a real pleasure. I'll
never understand why anyone would prefer JSX over templates. I like
opinionated frameworks like Rails and Ember because, even if it's not
initially designed that way, a "right way" to do things becomes apparent over
time and it's built-in, documented and blogged about. You could switch
companies every month and be productive in days because you know where
everything should be and how it should be done (mostly). Yes, you can do
everything wrong and it will still "work" but it's difficult to get anything
done the wrong way in an opinionated framework. When you find yourself
struggling hard to do something that should be relatively simple, it means
you're doing it wrong. In contrast, React gives devs more freedom to reinvent
the wheel and so when you dig in to a new-to-you React code base, you're
completely lost and must learn how the previous dev decided to architect
things, which can be a total nightmare. Redux feels like a valiant effort to
make React more opinionated and remove the opportunity for devs to repeatedly
make bad bad decisions or write similar code in multiple different ways, but
it doesn't fully solve the problem. I'd choose Ember over React in a second if
they were equals in terms of mindshare but trying to hire someone who wants to
work in Ember is nearly impossible.

~~~
acemarke
FWIW, Redux has never been pitched as "an effort to make React more
opinionated". It's always been about trying to make state management more
predictable.

See my post "The Tao of Redux, Part 1: Implementation and Intent" for details
on the original design goals of Redux:

[https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-
ta...](https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao-of-redux-
part-1/)

~~~
Mc_Big_G
That's why I said "feels". Redux is quite obviously about making state
management better but just try to build a reasonably sized app using the
Context api instead of Redux and you'll quickly realize that the structured,
opinionated, "right way" of doing things in Redux makes for a much happier
experience.

~~~
acemarke
Heh. As a Redux maintainer, I do appreciate seeing comments like this :)

Btw, if you haven't yet seen our official Redux Toolkit package, you should
check it out. It includes utilities to simplify several common Redux use
cases, including store setup, defining reducers, immutable update logic, and
even creating entire "slices" of state at once:

[https://redux-toolkit.js.org](https://redux-toolkit.js.org)

Also, I just published a brand-new "Redux Essentials" core docs tutorial,
which teaches "how to use Redux, the right way", using our latest recommended
tools and practices like Redux Toolkit and the React-Redux hooks API. I'd
encourage you to check it out even if you're already familiar with Redux:

[https://redux.js.org/tutorials/essentials/part-1-overview-
co...](https://redux.js.org/tutorials/essentials/part-1-overview-concepts)

~~~
Mc_Big_G
I'm actually on "Performance and Normalizing Data" right now. :) The
documentation and tutorial is really well done, so thanks for that! I'm glad I
attempted to build something without Redux first because at every step of the
documentation/tutorial my brain just keeps exploding with "wow, this is going
to make my life so much better" and helps me understand why it's built the way
it is.

Also, the toolkit is great and feels very Rails-y by providing default, built-
in (and I'd argue opinionated) ways of doing things that simplifies
development and reduces design decisions. Much appreciated.

~~~
acemarke
Thank you, it's really great to hear that feedback!

Totally agree that RTK works best if you already know how to write Redux code
"by hand", so that you're familiar with the concepts and can see what the
abstractions are doing for you.

That said, my goal for that "Essentials" tutorial is that folks who have never
used Redux before (like, say, someone in the middle of a typical bootcamp)
would hopefully be able to start writing real Redux code using RTK and be
productive with it, even if they don't understand everything that's going on
under the hood. The feedback we've gotten on this new tutorial, as well as on
RTK in general, tell me we've mostly managed to hit that goal.

FWIW, my next task is to rewrite the existing "Basics/Advanced" tutorial
sequence. It will still be a "bottom-up" explanation that teaches the
underlying mechanics and shows how to do things "by hand", but I want to clean
it up considerably to remove outdated references and show simpler patterns.

If you're interested, my notes on how I want to redo it are here:

[https://github.com/reduxjs/redux/issues/3855](https://github.com/reduxjs/redux/issues/3855)

If you've got any feedback on the contents of the existing tutorial and what
you'd like to see improved, please feel free to leave a comment there.

------
jupp0r
It’s funny how the author attributes hooks to functional programming hype when
in fact the allow state to be mutated, removing referential integrity from
functional components to some degree.

------
svachalek
I’ve been thinking about the “je ne sais quoi” that makes hooks troublesome
for a lot of developers and I think it comes down to this: hooks are heavily
reliant on memo-ization, and memo-ization is a form of caching. Maybe the
worst form, since it creates lots of micro-caches throughout your code.

Along with GOTO statements, global variables, and bare thread models, cache
consistency is a well known bane of programmers. For some reason though, it
seems “memoization considered harmful” has not become a meme yet.

------
goodhacker
Isn't abstraction of any sorts essentially creating a 'black box' I.e the
higher level system doesn't need to understand the lower level system as it's
not need or isn't relevant.

My thoughts are it's scary for engineers to feel like they are abstracting
themselves away from a lower level systems, a bit like how it's hard for
managers of people to let go the tasks they used to do themselves...

------
mesaframe
Hooks is something I found no problem understanding. That's in total contrary
to majority. This makes me wonder if I did really understand it.

~~~
kayodelycaon
I don't think there's a lot to understand. The issue is classes and hooks deal
with complexity the in opposite ways.

Working with hooks drops you into programming with functions instead of
objects. The component lifecycle in the background rather than foreground and
state becomes spread out into different layers of functions instead of
centralized.

They are two very different modes of thinking. I came in very late to React.
After digging through the classes I inherited from a previous developer, I was
struggling to understand what was happening. After reading up on hooks, I
immediately got what React was and was able to understand classes better.

Of course, now the app has both classes and hooks. Any future developer who
comes along will have fun with that.

------
have_faith
After memorising the rules surrounding hooks and how they work I've managed to
have a mostly positive dev experience with them. That said having to keep
track of the rules, with or without a linter, feels like walking a tightrope
with a safety net. Sure I'm not going to get hurt if I fall, but I didn't want
to walk the tightrope in the first place.

------
nallo
In my opinion JS was never meant to be used the way it is in all these
frameworks. It should be used to do very simple things to improve the user
experience. Modern web development is the result of meddlesome engineers
abandoning the KISS principle trying to solve a problem outside of their reach
(web browsers).

------
suyash
Avoid React if you can, keep your tooling and frameworks minimal and simple
for productivity and high performance.

------
burtonator
React hooks I think are 70% cool and 30% anti-pattern.

The problem is that there are subtle bugs that just aren't obvious at first.

Here's a simple one.

let count: number = 0;

const myCallback = React.useCallback(() => { ++count; return count; }, []);

... so if you had a button that read the value of 'count' it would always
return zero.

The reason why is that useCallback caches the value of 'count' and you get the
stale version each time.

You have to add 'count' in a dependency on useCallback before the last paren.

There are about 2-4 of these that I need to write down and document but this
one has bitten me most often.

Also, React, in general, can't work well with Typescript to catch compiler
issues.

For example, Typescript can catch compile errors when you're building a
component and you're missing a variable name.

With React context it's more of a global and if you are using a component
which doesn't have context setup you will/could get a runtime error or at
least a bad bug.

It would be MUCH better, IMO, to have a React-like language that was
Typescript aware from the beginning.

~~~
arcticfox
> You have to add 'count' in a dependency on useCallback before the last
> paren.

My linter yells at me that there's going to be a bug if I do that, have you
looked into your linting settings?

~~~
burtonator
I saw that recently they added this to eslint... you're using eslint or
tslint?

------
kra34
I for one would love to see Crank.js take off in popularity, shoot up in
usage, implement hooks, then be consumed by the next light weight super
focuses JS framework.

I think after 20 years of this repeating pattern JS frameworks might finally
die off. We can only hope!

------
ferdowsi
The addition of hooks feels more like an ideological decision than anything.
The current fad in the JS world is for functional programming, even if
misusing hooks can completely crash your application (this happens if hooks
are run in an unexpected order).

------
rodmena
I don't understand. people can try Svelte in few hours and for every
experienced frontend engineer, it's obvious that React is not only slow but
anti pattern. IMO Svelte is the best possible answer at least for now.

------
jdauriemma
On the contrary, I think that React has done an admirable job of maintaining
an elegant core feature set. We are free to (and probably should) completely
ignore concurrent mode absent a very clear use case.

------
throwaway7281
The amount of javascript used for the simplest of websites is getting out of
hand. In 2025 we'll be back at "server-side rendering", aka mostly static
sites, I promise.

------
browserface
This was always the case. React always totally sucked, but you all jumped on
the bandwagon instead of using something simpler. It surprises me that they
made it worse over time. But it doesn't surprise me that all the fanaddicts
are coming out to defend the newly discovered flaws and complexity, and
responding to any criticism not with cool confidence or generous reason, but
ideological hysterics.

Why'd you ever sign up for React in the first place? Are you now too invested
and deluded by sunk cost fallacy to admit your flaw and get out? Just keep
sinking more into it. Who does that benefit?

Maybe if FB wants to tie up startup competition with convolution...

~~~
cryptica
It's sad that we live in a time that the truth gets systematically downvoted
like this. Many experienced developers had been saying this about React for a
long time; it's bloated and over-engineered. Like ORMs; they just keep
creating new problems and then inventing new solutions to patch up the old
problems and introduce new problems at the same time.

It's all about where the capital is. Give me a few million of dollars in
marketing budget and I can convince all developers on earth to use Angular 1
(with a different project name).

~~~
browserface
Thanks for saying that. Yeah, it _is_ about this time we live in. It's like
the internet was supposed to make us all more open minded to new info, but
instead all the unfamiliar-to-each-of-us-info made us all more hard-shelled
and narrow minded. So anything not part of our worldview is a scary threat
that we need to respond with hostility to.

It doesn't matter what's true. It matters what confirms existing biases.
Paradoxically I think people used to be more open minded before the internet,
because it was safe to be. They weren't swimming in a infinite ocean of
unfamiliar new ideas, they could afford to be open without much risk of having
to do the hard work of challenging their beliefs and updating their worldview
at every turn.

It is totally about marketing budget as well. In this age of "outside my
worldview is fearful, I must respond with hostility" a consequence is you get
more group-think and safety in numbers type behavior. So it is easy with
enough capital to create these tribes of zealots for particular stacks. It's
not adaptive, it's not true, but that doesn't matter. It's safe and
comforting.

I just don't wanna work with tools that suck, as I guess you don't too.

~~~
browserface
Another consequence of this age we live in, that I recently discovered is it's
basically impossible to change anyone's mind on the internet. It's not just
because it's strangers, or because it's text, tho that does make it harder.
It's the dynamic I state above. I used to think it was worth sharing and
discussing ideas because maybe I could contribute to somebody else. Now I
realize that nobody can change their mind because of what I do. If they
somehow did change their mind, they were simply open and ready for it from
their own state, and it was accidental that I was involved, it could have been
another person or idea. If I bring to them really valuable (as in really
surprising) information (the highest quality ideas), the dynamic above ensures
they cannot hear it and must respond with hostility. And the lowest quality
ideas are ones where people agree with what I say, since those ideas are
already widely known. So I have learned to let go of wanting to share my ideas
with people online and discuss, or being upset about downvotes. Downvotes
mostly indicate quality and entropy. Nowadays I only say what I want for
myself...and don't get into discussions, because it's just people trying to
prove they're right, prove someone else is wrong, protect their worldview,
just pathetic stuff, and I don't want to be part of it.

~~~
cryptica
True. The main reason I write comments on HN is for the handful of outliers
who still understand logic and reason and are not blinded by power or
consensus. I only comment on articles where my view is contradictory. I don't
comment on the articles which I agree about because that doesn't add any value
to society for the exact reasons that you mentioned here.

I believe that there are enough intelligent people around to avoid taking us
back to the feudal dark ages.

~~~
browserface
thanks :) ;p xx

------
jeffrallen
hn.js is the only framework I need:
[https://news.ycombinator.com/hn.js](https://news.ycombinator.com/hn.js)

------
kokizzu2
you guys need to learn Svelte XD [http://svelte.dev/](http://svelte.dev/) less
pain, more beauty

~~~
pier25
"less pain, more beauty"

That would actually be a great catch phrase for Svelte :)

------
paganel
I know almost nothing of React but this looks eerily similar to the
(in-)famous Drupal hooks. Back in 2005-2006 there were articles like this [1]
which were mostly caused by people not understanding (or mis-understanding)
how the hook system was supposed to work.

[1] [https://www.drupal.org/forum/general/general-
discussion/2006...](https://www.drupal.org/forum/general/general-
discussion/2006-08-07/the-road-to-drupal-hell)

------
atrilumen
[https://github.com/choojs/choo](https://github.com/choojs/choo)

------
Ambol
Nice headline, but a lacking article.

~~~
bromuro
As non native speaker I had to look for “black box” in the English dictionary:

> (informal) a complex system whose internals are not easily understood.

So what the article author does not understand of React internals? I don’t
care about React internals either until the API is well written and easy to
understand. Hooks did not go in this direction :)

------
sam1r
Soooo, who’s been keeping up to date with angular & observables. Couldn’t be
happier.

------
tenbino
Please list specific actual links where people say that classes are better.

I love hooks.

------
macklemoreshair
Disagree. React hooks are great. Takes us less than half the code to build the
same things and more reusable.

Learn it. Jquery feels like a black box compared to JS but it’s where things
are headed, especially when it has demonstrable impact to the pace of web
development.

------
pts_
How useful are react editors where you drag and drop components?

------
xwdv
I don’t get it. You don’t really need to understand how React works, you just
need it to work. If you’re building a React app you’re probably just building
some simple CRUD like thing. What are you going to abandon React for? Some
other black box?

~~~
dsfdsfsdfasd
The author has addressed this in the article:

> Remember that React is supposed to take care of the “how” so that we can
> focus on the “what” of our apps. This mantra though, assumes that we can
> predict the “how”-part correctly.

Their claim is that it's becoming increasingly difficult to predict how React
is supposed to work in different scenarios.

~~~
xwdv
Hasn’t been my experience. The author must not be very experienced in working
with React.

~~~
recursive
Perhaps the experience disparity goes the other way.

------
rafaelturk
Missing examples or clear review to support this argument

------
lhnz
FYI, this article is from 2019.

------
kokizzu2
you guys need to learn Svelte [http://svelte.dev/](http://svelte.dev/) less
pain, more beautiful :3

------
dave_sid
React should be put in a black box. And buried somewhere nobody can find it.

------
sergiotapia
React started going down the path of "redux". Lots of sugar on top and blog-
driven-development. We use it today reluctantly, but the bloat is hardcore.

Goddamn 'useMemo'? - come on son.

I'm looking forward to abandoning ship, this is getting crazy and I don't have
the same energy I did when I was 19 reading blogs all night and writing code
katas. I just want to get work done and go home.

------
ChicagoBoy11
This is a really disappointing take on so many fronts.

First, definitely lacks a historical perspective. The React team is certainly
not new to accusations of banking their platform on certain
mental/implementation/stylistic decisions which people REALLY scratched their
head at, only to then become the behemoth of a framework that it is. JSX????
CSS and JS in the same file??? Etc.

But more importantly, this completely overlooks the amazing work the core team
has done to make sure you DO NOT NEED TO TOUCH ANY OF THIS STUFF AT ALL if you
never want to. React powers one of the most complicated and widely available
web apps in the world. That the company and team building it are including
tools and philosophies which feel awkward for your CRUD app should simply
feel... right. But what certainly doesn't feel right is to see the core team
build out more and more features, which support more and more advances and
highly specialized use-cases, only to then see the community turn on them
somehow because it is "too complicated" or a black box.

~~~
dsfdsfsdfasd
The author addresses this as well:

> I think a good ol’ Pete Hunt-style “Thinking in X mode” blog post would go a
> long way.

They point out that maybe all that's missing is a simple explanation of the
thinking behind the new React features is, much like React and its developers
did when they first introduced ground breaking features.

