[HN Gopher] In React {Transitions} = F(state)
       ___________________________________________________________________
        
       In React {Transitions} = F(state)
        
       Author : captbaritone
       Score  : 35 points
       Date   : 2025-04-07 20:28 UTC (2 hours ago)
        
 (HTM) web link (jordaneldredge.com)
 (TXT) w3m dump (jordaneldredge.com)
        
       | dvtkrlbs wrote:
       | I dont think this is really true in practice. Most of the time
       | there is context and 3rd party sources components get from. It is
       | good idea to have your actual view use this paradigm though.
        
       | dfabulich wrote:
       | > A React application can be thought of as modeling a state
       | machine. Each render takes a state and produces the UI for that
       | state. This is the famous UI = f(state) mental model of React.
       | But, for complex applications, formally enumerating a transition
       | table is often not feasible. When the number of possible states
       | is not finite, a table will not suffice and we must instead
       | define a mapping: a conceptual function which takes in a state
       | and returns the set of valid transitions for that state.
       | 
       | Not really, though. While you _can_ model any program as a state
       | machine, doing so typically adds nothing to your understanding of
       | the program.
       | 
       | State-machine diagrams are especially useless. A diagram is only
       | useful if it has about a dozen things in it, maybe two dozen,
       | maximum. But that doesn't mean you can model a dozen _states_ in
       | a state-machine diagram; in these diagrams, the _transitions_ ,
       | the arrows between the states, are at least as important as the
       | states themselves. So the diagrams are useless when the number of
       | states + the number of transitions between them are greater than
       | a few dozen. Typically that means state diagrams are only with a
       | handful of states with a few transitions hanging off of each.
       | 
       | But, if your problem is simple enough that you can represent it
       | with a handful of states with two or three transitions each, then
       | you have a _very_ trivial problem, so trivial that the state-
       | machine diagram likely added nothing at all to your understanding
       | of it.
       | 
       | This is why no popular UI frameworks actually _do_ model UI as a
       | set of states with transitions. It 's easier to model the _state
       | diagram_ as a _function_ and then just forget about the state
       | diagram.
       | 
       | That's what React is all about! A pure function, UI = f(state).
       | It's _better_ than a state diagram.
       | 
       | This article is saying: "Hey, you could think of React, something
       | conceptually simple, as something unnecessarily complicated,
       | instead!" Gee, thanks?
        
         | captbaritone wrote:
         | Author here. I think we might actually be in agreement. My
         | point is that in React you don't formally describe the
         | transition table because (and I think this is where we agree)
         | that's infeasible for an app of any reasonable size.
         | 
         | The observation I'm trying to capture in this post is that even
         | though we don't define a formal transition table, we actually
         | _do_ implicitly define the set of valid (user) transitions for
         | each state via the event handlers we bind into the DOM when our
         | React component tree renders that state.
        
         | tshaddox wrote:
         | > But, if your problem is simple enough that you can represent
         | it with a handful of states with two or three transitions each,
         | then you have a very trivial problem, so trivial that the
         | state-machine diagram likely added nothing at all to your
         | understanding of it.
         | 
         | And yet, it's extremely common to see apps with clearly broken
         | states and state transitions for what should be relatively
         | "trivial" state machines. Think play/pause buttons, buttons
         | with loading states, form fields with error states, etc.
        
       | revskill wrote:
       | That is a valid way of thinking.
        
       | mvdtnz wrote:
       | Every time I delve into a large React codebases (and I have
       | worked on some real monsters) I have a laugh to myself at how
       | badly these guys tie themselves up in knots in order to preserve
       | the supposed simplicity of the state -> UI function. When you
       | invent something as insane as the hooks API in order to maintain
       | purity it's time to step back and consider if you're really on
       | the right track.
        
         | paulddraper wrote:
         | Hooks are the best thing for frontend dev since async/await.
        
           | recursive wrote:
           | I would believe that if there were exactly two things in
           | front end.
        
           | LunaSea wrote:
           | I can't count how many issues I've seen due to: missing
           | useEffect dependencies, cyclical hooks, unnecessary
           | rerenders, etc. linked to this API.
           | 
           | It has a lot of expressivity but is incredibly brittle and
           | dangerous.
        
         | taeric wrote:
         | I want to disagree with you, but I just can't. Every simple
         | example on the different ideas for managing state in React is
         | easy and seems reasonable. Every application I encounter seems
         | to quickly take that and just start laughing at me.
        
           | CharlieDigital wrote:
           | Something with React's approach is fundamentally broken, IMO,
           | and this is why we see so many variations of state management
           | libraries on React that we don't see on other frameworks
           | because state kind of "just works" and is really, really
           | simple when you are using signals.
           | 
           | My sense is that in React, the complexity comes from the
           | management of minimizing the "blast radius" of state changes
           | to prevent over-renders. So there are a lot of different
           | approaches and ways that folks have cleverly engineered to
           | solve this problem, but none of them feel as simple as say
           | Pinia on Vue, for example.
        
           | Rohansi wrote:
           | I think state management is the worst part of using React.
           | All of the popular/highly recommended packages to manage
           | state require you to write code in unconventional ways
           | without really explaining the design decisions. Why use
           | reducers? They're basically different (worse) syntax for
           | mutable object method calls.
        
         | eddythompson80 wrote:
         | To me, the state -> UI paradigm isn't simple in the sense "oh,
         | that was one click, simple". It's simple in the sense "anyone
         | can do it if you just understand/follow these 10-15 _simple_
         | rules ". Once you know these simple rules, you can jump
         | straight into 95% of react projects and be productive fairly
         | quickly.
        
       | jschrf wrote:
       | The vast majority of state problems in React are a result of
       | nonsense cargo culting around the idea that classes are somehow
       | bad.
        
         | recursive wrote:
         | IMO it's the central tenet to the dogma that "state must not be
         | mutable".
        
           | geetee wrote:
           | The absolute nightmares people create in order to attain this
           | ideal...
        
         | kccqzy wrote:
         | I'm glad I learned React during the time when React.createClass
         | was the only way. It was simple and intuitive. At that time the
         | docs included a very lengthy discussion of what should be put
         | inside the class and what should be passed via props. It was
         | very helpful when it comes to teaching newcomers to architect
         | their app. It also carried over the years of intuition by the
         | typical dev working with OOP. Much better than the current
         | trend of using hooks for everything.
        
       | tripplyons wrote:
       | I might just not be aware of a better alternative for React
       | hooks, but I don't like useEffect. I feel like it makes it much
       | more difficult to manage state and transitions compared to
       | SolidJS or other frameworks that use signals.
        
         | alpinisme wrote:
         | There's no denying that the idiomatic solution is sometimes far
         | from obvious, but idiomatic react wants useEffect to only about
         | synchronizing react with external systems. Everyone reaches for
         | it to synchronize between components and do all sorts of other
         | non-idiomatic things though, and that's where the pain comes
         | in.
        
           | LegionMammal978 wrote:
           | Out of curiosity, I just looked through some of my old code
           | calling useEffect. Most of it was for fetching data from an
           | API on mount; I'd also written a custom little hook that
           | returns a callback to signal that the data should be
           | refreshed.
           | 
           | But a few instances were to conditionally set one piece of
           | state whenever another piece of state was changed, arguably
           | an abuse of the mechanism. I suppose the proper way would be
           | to wrap the setter function into one that changes both, but
           | it takes a fair bit of discipline to avoid useEffect in the
           | heat of the moment.
        
             | wk_end wrote:
             | There's an excellent article in the React documentation
             | about this ("You Might Not Need An Effect"). Back when I
             | was working on a React team I probably threw it at a code
             | review on average once a week.
             | 
             | I really like React, but given the way developers seem to
             | struggle to use it "correctly" (despite all the lint hooks
             | and weird diagnostics like double rendering to help) it's
             | hard not to feel like there's something wrong with it.
        
             | marksomnian wrote:
             | > But a few instances were to conditionally set one piece
             | of state whenever another piece of state was changed
             | 
             | That use case is explicitly called out on the "You Might
             | Not Need An Effect" article in the docs (which everyone
             | writing React should read, and arguably was published years
             | too late): https://react.dev/learn/you-might-not-need-an-
             | effect
             | 
             | TLDR:
             | 
             | When updating a useState based on another useState, don't
             | use the first useState at all, just compute it inline. If
             | it's expensive, wrap it in a useMemo.
             | 
             | When updating a useState based on props, call the setter
             | _directly from the component function_ , and React will
             | immediately re-render the component (instead of rendering
             | it, running the effect, and then rendering it again).
        
           | Jcampuzano2 wrote:
           | A lot of the time it comes down to the platform not actually
           | providing easy ways to do things that users are reaching for
           | effect for.
           | 
           | For example some people reach for it for fetching data in
           | routes. It wasn't until recently that routers started to come
           | with built in patterns to do this without effects - example
           | being react routers (it's been a while since I used but remix
           | had this) loaders and tanstack routers beforeload and
           | loaders.
           | 
           | People fetched in an effect because at the time this was the
           | most simple and obvious place to do it unless you were very
           | aware of the other ways to do it, and we didn't have
           | primitives like react query either.
           | 
           | Another example of a non obvious things logging an analytics
           | event when a specific component renders. You could attempt to
           | tie this to the specific update that caused a component to
           | show but that update may be very complex or hidden since your
           | component could show based on a variety of states and require
           | so much more work vs just logging in an effect.
           | 
           | I guess one could argue both of these themselves are syncing
           | operations, syncing your network state and server state for
           | API requests in routes and analytics. But at the same time
           | reacts team told everyone if you're fetching in effects
           | you're doing it wrong without providing the answers.
           | 
           | That to say yes effects are not a very good pattern for many
           | things we use it for and should be avoided, but react as a
           | framework (yes it's basically framework in my opinion, we're
           | well past just. library point) itself does not educate well
           | or have easy to understand built in ways to do these things
           | that are VERY common use cases
           | 
           | And this as someone who writes mostly react.
        
       | kccqzy wrote:
       | The most direct way of solving the immediate problem is to make
       | transitions idempotent. Why must it be an error to complete an
       | already complete TODO? Completing an already complete TODO should
       | be a no-op. That simplifies things greatly.
       | 
       | Of course many actions logically cannot be made idempotent, but
       | for the subset that can, do it as much as possible.
        
         | a_wild_dandan wrote:
         | Exposing _invalid_ transitions to a user is a bug. Idempotency
         | here doesn 't solve anything, just hides said bug, which is
         | arguably _worse_.
        
       | veidelis wrote:
       | "This is the famous UI = f(state) mental model of React".
       | Famously incorrect generalization. Why? For example, the useRef
       | hook enables components to hold their own state. React components
       | are not guaranteed to be pure functions. Of course, it can depend
       | on how one writes their code, but it's not a guaranteed that UI =
       | f(state) in React in general.
        
         | guhidalg wrote:
         | It's a mental model, not how it works. Your computer isn't
         | actually executing C code, but it's helpful to think that it
         | does.
         | 
         | If you write React code that strays from that model, you better
         | know what you're doing. When I have to reach for `useRef`, I
         | know that I'm in dangerous water.
        
         | ketzo wrote:
         | "All mental models are incorrect; some mental models are
         | useful"
        
       | bob1029 wrote:
       | The #1 reason I push for SSR/vanilla web is to consolidate all
       | state to the server. Literally the only thing on the client could
       | be a session cookie. A few hundred bits of entropy. That's the
       | client's state. Imagine how simple that would be.
       | 
       | The cost of a round trip for every UI interaction might seem
       | high, but I've never seen a distributed client/server state
       | machine model that could compensate for any of these alleged UX
       | harms without simultaneously bringing in more complexity than
       | anyone was prepared to deal with.
        
         | adamddev1 wrote:
         | But then we lose the ability to do anything offline. Offline
         | web apps are still valuable. Some people want to turn their
         | data off sometimes. Many people live in places where internet
         | access is spotty.
         | 
         | I also love the simplicity of SSR/vanilla web for some things.
         | But I say keep offline-first SPA/PWAs alive. Cross-plaftorm.
         | Freedom from the app stores. Freedom from needing to be tied
         | online all the time.
        
           | LegionMammal978 wrote:
           | Yeah, sites demanding a roundtrip for every small interaction
           | can be a pain to use when traveling. The principle I'd wish
           | more web devs would keep in mind is, "Just because the client
           | managed to contact your server once doesn't mean it will have
           | fast and easy access to it in perpetuity." Indeed, in my
           | experience, too many roundtrips is the cause of most
           | atrociously slow websites, regardless of how heavy or light a
           | framework they use.
        
           | adamddev1 wrote:
           | When you have a website that needs to be always accessed
           | online, absolutely, give us an old-fashioned SSR vanilla web
           | experience. Just give us a page WITH ALL THE DATA that loads
           | in half a second. Don't make us wait for 5 seconds with
           | spinners and placeholders while you make the client fetch
           | data itself from different sources. This is insanity and
           | torture! People are using client side rendering for the wrong
           | things.
           | 
           | But there are good and powerful use cases for client side
           | rendering.
        
           | nkrisc wrote:
           | Freedom from browsers - I'd rather have an executable I can
           | run.
        
           | bob1029 wrote:
           | > I say keep offline-first SPA/PWAs alive.
           | 
           | I have no problem with the properly offline-capable apps
           | using standards compliant web technology. I've been
           | championing the use of PWAs to circumvent the iOS App Store
           | for years.
           | 
           | To be very specific, the problematic solutions in my view
           | tend to be those right in the middle of pure SSR and pure
           | client. They aren't sure if they are always online or offline
           | by default and the actual customer use cases don't seem to
           | have been fully explored.
           | 
           | Did you ask the customer if a ~150ms form post to us-east-1
           | from their main office would be something they'd even care
           | about? Why not? You could save an unbelievable amount of
           | frustration if they don't care. It would take 10 minutes to
           | set up a demo they could try if you think it's going to be a
           | deal breaker at delivery time.
           | 
           | I've not once worked with a B2B customer in the banking,
           | insurance, finance, manufacturing or retail domains who
           | raised a concern about any of this. Only nerds on the
           | internet seem to fantasize about the customer getting
           | outraged at a browser navigation event or a synthetic browser
           | benchmark score.
        
       | whalesalad wrote:
       | Why does it feel like React (not just the lib but the
       | community/ecosystem/everything) took something as straightforward
       | and easy to understand as functional programming and surrounded
       | it with so much fluffy pomp and circumstance that it is
       | unrecognizable?
        
       | the_gipsy wrote:
       | I've never seen a Teact project where UI = f(state). There is
       | always heavy reliance on the "lifecycle" of components. So you
       | compose "functions", but every function is using some global
       | state, shared or not, it's meaningless to describe it as
       | "functions".
       | 
       | The one project I've used that had redux was also a complete
       | nightmare to work with, and hooks are the blessed way now
       | apparently.
        
       ___________________________________________________________________
       (page generated 2025-04-07 23:00 UTC)