It is much easier to accidentally create infinite loops with useEffect that you would never create with class components, and some of the code you write turns out to be more verbose and less expressive, such as when trying to diff previous and current values of state & needing to create extra state variables with useState for each such value you need to react on.
Hooks seem very appealing at first (I lean more FP than OOP in general), but the bugs and slipshod initial rollout out of beta really does not inspire much confidence. Even today I still encounter weird issues.
Say you have a component that renders some data it fetches from the backend, and it received the ID via a prop. In a class based component you might be inclined to write the fetching logic in the componentDidMount or maybe the constructor. However, if you change the ID you feed the component, the component will update instead of being recreated. In the naive class based version it won't refetch the data, and won't behave correctly. With useEffect hooks you don't really care anymore, you can reason about side effects in the same declarative way. You express the fact that fetching new data is a dependency of the prop changing, which holds true both on first render and later on update.
The hooks API fixed a handful of these 'mistakes' that were still present in the class based API. I agree that the syntax might look awkward at first, but the hooks API is much better thought out than the class based one.
(Some anecdata: almost any component that I rewrote in hooks-style has been halved in number of lines of code, the concepts have been much less spread out over the file. See this tweet for an example: https://twitter.com/threepointone/status/1056594421079261185)
The constructor is the wrong place for data fetching in React class components as far as I remember anyway. I don't remember the exact reason, but it always has been somewhat non-obvious and you always needed to understand the React lifecycle to avoid bugs in that kind of code.
Classes in React generate false expectations.
In ASP you wouldn't put initialisation code in the page constructor either, it would go in Page_Init, Page_Load, etc.
Of course the tooling there made it both easier to put in the right place and harder to edit the page constructor to stick it in the wrong place.
I agree that for the easiest of use cases, lifecycle methods make sense. But you very quickly leave that comfortable zone and then it just becomes painful and confusing.
Less so than I've been tripped up by react hooks certainly so it's been a surprise that many here are describing them as being much easier and simpler than classes.
Classes had limits and some pitfalls but it's been frustrating that lifecycle methods have been retired and deprecated because sometimes they felt like the natural place to do something.
onCreate/onStart/onResume and onComponentDidMount, onPause/onStop/onDestroy and onComponentWillUnmount are basically the same. Be it Android, Swing, or Qt, everywhere it's the same pattern.
React is the first framework which actually feels like UI development on the web, not anymore like JS spaghetti.
In fact, having internal state, externally given props, exposing events, and being declared through markup is exactly the same between React, Android or Qt.
The only thing React brought to the table was allowing you to basically just recreate the children every time something changed, and it'd diff automatically.
For us native devs this thread is hilarious, because it's just JS decs complaining over things we've always done
> JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
You've been tricked into thinking you're using a class, but you're really not. I understand it's a useful trick, but hooks are more idiomatic for JS as a language.
As a side note, one of the problems with JS is that the community often disagrees about what JS is: https://babeljs.io/blog/2018/07/27/removing-babels-stage-pre...
It may be technically correct, but C++ and now JS have a "class" keyword for a reason, and that's to steer you towards organising your code into classes which operate in certain ways. In both languages you can avoid using classes, sure, or abuse classes in various ways. But fundamentally they do have classes.
I guess, yes, there's different semantics between the constructor and componentDidMount, but it's UI library, this is common that "when a constructor is call there is no guarantee the component has actually mounted".
You can't `new MyRecyclerView(...)`, you've got to `LayoutInflater.inflate(MyRecyclerView, parent)`, which isn't any different from `React.render(MyApp, parent)`.
Was the issue with `this` in componentWillRecieveProps not solved by using an arrow function? If so, that just sounds like normal JS binding woes.
Facebook recommend composition over inheritance, but you can totally extend React.Component and even get abstract classes involved. In my custom React renderer, all the components in the library are based off React.Component class inheritance.
But that’s the point. The way in which classes operate in JS is different from the way classes operate in OOP focused languages like C++, Java and C#. That’s because the language doesn’t have classes, but rather syntax to make it look like it does. On the surface your code will be organized in similar ways but the underlying behavior is different.
At least it looks like we agree that React is a decent framework :-)
That said, for us devs who do both native and JS code, the condescending part is quite hilarious as well ;-)
It's just funny when pure JS devs go all "no you won't convince me to compile my code / use classes with lifecycles / etc, that's against the natural order!!!"
Not really because there's nothing object oriented about React.Component. It's just a wrapper for a function implemented as a class.