("We recommend defining components as functions instead of classes." at top of page at https://react.dev/reference/react/Component)
("We recommend defining components as functions instead of classes." at top of page at https://react.dev/reference/react/Component)
Although React tutorials start by saying your UI becomes a pure function of your app's state, React components do have encapsulated state. Any time you call useState inside a react function you're doing something that doesn't exist in real FP programs. Additionally React boils down to a way to create DOM elements, which are highly stateful C++ objects exposed to JavaScript, implemented using inheritance:
https://source.chromium.org/chromium/chromium/src/+/main:thi...
An HTMLButtonElement is a HTMLFormControlElement is a HTMLElement (and a ListedElement and a FormAssociated).
The rules for how you write code in React (or Jetpack Compose) violate even the most basic rules of the host language. useState defines or returns what is effectively an object field (it's data associated with that widget), but it looks syntactically like a local variable. It's not a local variable though because its value will survive the exit of the scope. Nor is useState a normal function call because there's a hidden invocation counter used to work out what state slot you want, which is why you aren't allowed to call it inside conditional branches and why loops need special handling.
So in React's "functional style" we can see that you're actually defining objects with encapsulated state, that register event handlers, that export properties and so on. It's just obfuscated to look like it's not OOP.
Honestly for recent simple GUIs I've made for my own in house tools I'm still using JavaFX. Mostly because I always seem to end up needing a good table view, and because I happen to know it. If I were working with it a lot I'd end up maintaining a TornadoFX style set of wrappers but for simple stuff the plain API works OK.
Because I'm weird I'd probably use it for low-traffic web apps these days too, with JPro (jpro.one). Probably not for mobile web, and not for stuff where users are on high latency connections in general, but if the user has a nice big screen and a low latency connection I'd personally find it a lot easier and more productive than dealing with HTML and CSS. The results are indistinguishable for the user if you are careful.
Meh, it's just a monad, hidden in a fake syntax so people don't panic.
> Additionally React boils down to a way to create DOM elements, which are highly stateful C++ objects exposed to JavaScript, implemented using inheritance
And C++ and JavaScript are just ways to run machine code, which is fully unstructured. But all of that is an implementation detail. React creates DOM elements because that's what you have to do to render UI in the browser, not because its creators think the DOM is a good idea.
> So in React's "functional style" we can see that you're actually defining objects with encapsulated state, that register event handlers, that export properties and so on. It's just obfuscated to look like it's not OOP.
It's not OOP - it doesn't have inheritance, most state is (idiomatically) immutable and exposed, and as you noted, React state does not follow the same rules as OOP state. While it's not fully pure functional (I'd actually say the React state model is a novel and interesting thing, that I expect may end up being a language feature in the next generation of successors), it's closer to functional than traditional OOP, and most of the benefits are those of a functional rather than OO style.
Jetpack Compose now, that is a pure implementation of the React concept all the way to the bottom. And their compiler plugin basically makes the React model a part of the language, so you could go take a look at that if you're interested in language-integrated approaches. There's essentially no OOP there and all state is handled with their useState equivalent. But as I write in another post it actually does suffer badly from that decision, in my view. The combination of the React concept with static typing doesn't mix well at all. There's an astonishing amount of copy/paste coding going on in the Compose landscape and worse, a new generation are starting to learn that this is normal and just the way UI code looks.
On the web the React approach took off due to the history of JS/HTML not really supporting proper componentization or indeed proper OOP until very late (arguably it still doesn't). Then the Android guys decided to adopt it to be more familiar to web devs and as a way to justify the huge expense of starting over, which they did need, the old Android toolkit has a lot of tech debt in it.
But I think we will come to regret that evolutionary path. Once you get past the convenience of being able to add/remove widgets by rebuilding the whole layout from scratch, it's just not a good way to express UI in statically typed languages.
For someone writing stuff in React all that is effectively the "runtime", and whether it's being managed in OOP, FP, or some other fashion is an implementation detail. (You don't e.g. subclass DOM classes when writing React).
> The combination of the React concept with static typing doesn't mix well at all.
Hasn't been my experience at all, shrug, my main job does a lot of stuff with React in Scala.js and it works very well.
(This change has little to do with OOP vs functional. React calls them function components, not functional. React has always used functional patterns, even in the class components.)