React 19 Beta
react.dev
react.dev
Here is what I am struggling with: I am not able to grasp the programming model with Hooks. I am not able to read the code easily, nor am I able to easily understand the interactions in the app. "easily" being the keyword here. I can understand what is happening if I put in the effort, but every time, it is a struggle. I switch between languages and platforms all the time, but react code is where I have to take a real pause to understand what is going on.
My suspicion is that this has to do mostly with the names of the Hooks, and how they are used in the code.
* Why are they named useState, useEffect etc? Are there better names if used will make it easier for me to read this code? Are there any other systems/languages (even in JS) where similar constructs are present? What are their names?
* If JSX is anyway getting compiled to JS, why do I have to still deal with strange looking useState and useEffect declarations? Is there a way to get cleaner syntax and make React code read like regular code?
This is mostly a cry for help, and not a criticism of React. I have used React in the past (several years ago, before Hooks) and I used to "get" React.
It's helpful to remember that functional components are, well, just functions, which on their own don't have any way to preserve their own state without resorting to some kind of global state store. Unlike object instances, which can have members which keep their state across invocations to instance.render(), functional components are just functions which receive props and return something (usually a React.createElement invocation, often disguised with JSX). Since they don't inherently have any way to preserve state, React provides functions to manage state and to trigger re-renders of components. This is what hooks are - they're global functions which manage updating a global state dict behind the scenes, and triggering re-renders when state changes.
* useState declares a stateful variable which is preserved across renders, and a mutator function which is used to update that variable (in the global state dict) and cause React to perform a re-render of any components which depend on that variable.
* useEffect would probably be better named "useSideEffect", since its purpose is to run a callback as a side effect of one of its declared dependencies changing. It is a little overloaded, in that it can run its callback as an effect of: 1. The component initially mounting, 2. the component unmounting, or 3. one of the declared dependencies changing value.
* useMemo is kind of a combination of useState and useEffect, which declares a stateful variable that is preserved across component renders (the memoized value) and uses a generator function to regenerate and save a new version of that variable when a declared dependency changes.
* useCallback can be thought of as a specialized case of useMemo which returns a memoized function.
Essentially all hooks are built on these four (and really, just useState and useEffect, since useMemo and useCallback are trivial derivations from those two).
It's helpful to think about react state as eventual and to treat it as immutable, and to think of components as truly functional constructs, which should just receive external input and return an output. It may be helpful to think of useState values as nothing more than additional values passed to the function by React when it invokes them. When you update state (or run an effect) you aren't changing things in this invocation of the component, you're changing things for the next invocation for the component (and queueing a reinvocation).
Imagine that you have a declared hook `[someState, setSomeState] = useState();`
Calling `setSomeState(val)` doesn't change the value of `someState`, which you should treat as an immutable variable. Instead, it updates the value of `globalStateDict[currentComponentIdentifier]["someState"] = val` and tells React to queue a re-render of this component. React dutifully re-invokes the function, and the second time it's run, the local `someState` variable receives its value from the React-managed global state, which is now `val`.
Each one is simply this: (your data) => <your html>
And then at the top you call render({ my data + functions }), your data propagates down the render tree, and you get an html page back. So simple! Just one function that you call. You put your data in the top, you get your html out.
Except.... what if that's too pure, sometimes. Can't a render function just remember a variable between calls? Why can't a render function two thirds down the tree fetch the data if it's needed? When things aren't so pure, you can optionally pull out hooks to break out of the purity. That way you don't have to do everything at the top level and outside of react, if you don't want to. Just bang a useState in at an appropriate level that makes sense, and it'll remember the state between renders.
> By convention, functions that use async transitions are called “Actions”.
React is the only people who use this "convention". They pick a very meaningless word for their terminology, but then they just can't stick with it and have to name the hook `useTransition` for some reason.
Instead of wasting doc space for sentences like above, why don't they just use the same word for the api and the concept? If you're gonna refer to the concept as "action", then the hook should be useAction. And if you think "action" is a meaningless word and you need to add some explanation about mutation or promises in the docs, then maybe better just call the concept "mutation", "async transition", whatever and same with the hook.
I struggle with almost the exact same issues.
It doesnt have to be that way, SwiftUI is wonderful to work with!
But React I just find to be like trudging through mud. It's such an intellectual drag!
1. The purpose of specific hooks have silently changed over time - You’re not the only one confused. The React devs themselves were confused about what they wanted to do with hooks. For example, useEffect is for managing side effects according to the old documentation whereas the new documentation says it syncs external systems.
The change in behavior is ok, except the devs are not open about the fact that they’ve changed how they see useEffect. If they did that it would reduce some of the confusion, especially with the naming, since useEffect is named based on the previous purpose rather than the new.
2. Hooks are expensive - The React devs were far too hasty with the creation of hooks. For example, useMemo and useCallback are basically the same thing. There was no reason for both to exist but React devs considered hooks something easy to create and easy to understand so believe in creating many of them.
The problem, however, is that this approach is completely backwards. Creating a new hook should be considered extremely expensive and something to be avoided as much as possible. The reason is that while technically they are indeed often lightweight wrappers that are easy to create and deploy, conceptually they’re extremely heavy. Every hook brings highly impactful behavior which may not be entirely predictable without looking at the source code, and may not be related to other hooks in any ways.
3. Hooks are not a thing - Calling all of them hooks is also a massive mistake because there is very little similarity between their behaviors. The only similarities that exist are the restrictions on them. But there is no similarity in what they can do. So, for example, if you learn what useEffect does, you will have to expend the same amount of mental energy learning what useCallback does as someone who has no idea what useEffect does. As someone who knows about useEffect the only advantage you have learning about useCallback over someone who doesn’t is that you know you can only use it at the top level of a function and maybe a slightly better intuition of hooks breaking the pureness of functions.
4. It’s the Wild West out there - There are only 2 “Rules of hooks”. They must only be used in functional components. They must be used only at the top level of functional components.
The “use” hook doesn’t even follow these. The 2nd “Rule of Hooks” does not apply to it. The use hook does not need to be used only at the top level but can be used within conditionals and loops as well.
Conclusion - The reason you don’t understand hooks is because “Hooks” are a lie. They don’t exist. No one can go in and learn about “hooks” in React and do anything useful with that information. Instead, you have to learn about “useEffect”, and “useState”, and “useCallback” etc and treat them as completely independent and different concepts with no relation to each other to have learnt something useful.
Fundamentally hooks was a linguistic invention designed to hide the fact that when switching from class based components and the well established concept of a component lifecycle, the React devs created around a dozen new independent concepts to replace them. By pretending that all these different independent concepts such as useEffect, useState, etc were not actually independent concepts, but were a single concept called “Hooks”, they were able to sell the transition to developers more easily.
The only doubt in my mind is whether the React devs were even aware of this falsehood that they were spreading. I’m not convinced they themselves understood what they created and were laboring under the same illusions that they were spreading.
I suggest you to visit Flutters docs and find the section about its architecture, it resembles React a lot!
There a components (Flutters calls it Widget) and each component has its own hooks and states (in Flutter you have setState), it actually helped me grasp the mental model weirdly enough.
Gotta say, I really love what the react team has been doing, sure it hasn't always been perfect, but it really feels like inching closer to a very smooth developer experience very time.
We’ve come full circle
I think most everyone is on go or python for BE work.
Just really frontend focused apps or heavy react shops are doing js on the backend.
EDIT: I think “use server” is a nextjs thing FWIW
https://nextjs.org/docs/app/building-your-application/render...
Personally,I don’t think php or js are the right tools to build a backend for a business.
Neither are particularly friendly towards growing teams for many reasons, but the lack of strong typing is a big one.
You want your backend to have minimal complexity, that’s why go has been so popular lately
Also, to your second point, some of the largest, most critical, and most at-risk businesses on the planet (namely banks) run on COBOL, but I wouldn’t exactly describe cobol as a language that lends itself well to large orgs, it’s just entrenched. same as php and dozens of other technologies.
https://react.dev/blog/2020/12/21/data-fetching-with-react-s...
React v1.0 was out in 2014. It was already being used in production before that.
React Hooks were released in 2019. Hooks has also spent years as part of React with Server Components not being part of it.
Server Components is an extremely new addition to React, and a significant shift in React’s direction.
But don’t take it from me, I’m just regurgitating information I learned from actual React team members (at least at the time) like Dan Abromov.
But the point is somewhat moot as modern Internet connections and devices won’t struggle with a 2MB payload in any case.
I wouldn't expect React to be replaced any time soon.
The "old RoR" way assumed that all behavior is built by the server through ruby, until client side behavior was needed. Then, that was built in CoffeeScript. (or JS if you rejected omakase.)
The React way is to assume you will have client side behavior, but write it as if it is client-side and the server will compile that into a html that can be hydrated with behavior without intervention. Even with that "magic," it is easier to reason through if you already have a mental model of the browser.