Earlier quoted context omitted.
The general use reducer is a infinite state machine, while this is a finite state machine. The normal reducer can allow your app to be in any state, while finite state machines let you list the only possible states (like ON, OFF, UNKNOWN; or DRAFT,SENT,BOUNCED) - and offers state transition functions to move between them that can refuse to move unless certain conditions are met.
This still mostly sounds like a useReducer. With TypeScript you can guarantee the built code only respects a finite state shape. Depending on the dispatched action, you can just default to returning the previous state - refusing to move unless certain conditions are met.
useStateMachine: A ½ kb state machine hook for React
81–90 of 103 posts
Re: useStateMachine: A ½ kb state machine hook for React
#82Re: useStateMachine: A ½ kb state machine hook for React
#83As someone that works with finite state machines, I can’t begin to describe how annoying I find it when everyone needlessly reduces the name down to just “state machine”. To me, it makes it seem like the people making “state machines” don’t understand the whole “finite” part and thus don’t understand half the point.
Re: useStateMachine: A ½ kb state machine hook for React
#84Earlier quoted context omitted.
Interesting. I have the opposite experience, the more I use them the more clunky they feel. * If there’s only useState, then everything is mostly fine. All is good. * To avoid unnecessary re-rendering you’ll have to move callbacks into useCallback. These callbacks then also need to specify all of their dependencies. So many lines of code that are merely noise. * They encourage having state locally in the component wh…
Regarding useCallback, you can probably skip it in most cases, unless the extra renders are a problem for you. Linters should help with missing dependencies.
Re: useStateMachine: A ½ kb state machine hook for React
#85I can't get over how amazing hooks are and how resistant I initially was to them. They encapsulate logic so well and do an amazing job being this isolated data/event source. I find that I reuse them far more than I reuse components.
Interesting. I have the opposite experience, the more I use them the more clunky they feel. * If there’s only useState, then everything is mostly fine. All is good. * To avoid unnecessary re-rendering you’ll have to move callbacks into useCallback. These callbacks then also need to specify all of their dependencies. So many lines of code that are merely noise. * They encourage having state locally in the component wh…
I’m curious what you think of https://rxstore.dev/ it basically is a pattern I tried to outline where you write logic with rxjs and it tries to bridge the gap to react/hooks for you. I address some of your points in the faq.
Re: useStateMachine: A ½ kb state machine hook for React
#86I can't get over how amazing hooks are and how resistant I initially was to them. They encapsulate logic so well and do an amazing job being this isolated data/event source. I find that I reuse them far more than I reuse components.
Re: useStateMachine: A ½ kb state machine hook for React
#87I can't get over how amazing hooks are and how resistant I initially was to them. They encapsulate logic so well and do an amazing job being this isolated data/event source. I find that I reuse them far more than I reuse components.
Interesting. I have the opposite experience, the more I use them the more clunky they feel. * If there’s only useState, then everything is mostly fine. All is good. * To avoid unnecessary re-rendering you’ll have to move callbacks into useCallback. These callbacks then also need to specify all of their dependencies. So many lines of code that are merely noise. * They encourage having state locally in the component wh…
This is by design. When you start making a component worry about what it needs to do on an update, rather than just rendering its data, you are introducing a whole new level of complexity. That's why class based React components could turn into these unwieldy confusing things where you never knew for certain what was going to render every time, because the shouldComponentUpdate method gets stuffed full of business logic.
Re: useStateMachine: A ½ kb state machine hook for React
#88Re: useStateMachine: A ½ kb state machine hook for React
#89Earlier quoted context omitted.
> You forget one value in your dependency list and the weirdest things happen. Don't you get eslint warnings right in your editor? If you're using VS Code there's an extension for that...
Not only this but I need the freedom to control the dependency list for an effect. Sometimes it isn't as simple as "every variable being referenced inside the effect."
Re: useStateMachine: A ½ kb state machine hook for React
#90Can anyone provide an example of a situation where something like this is a pragmatic solution? Please also provide the drop dead simple version too and explain why this would be more elegant and intuitive in comparison. Types of examples I am not interested in seeing: - a DropDown list using a state machine (or something similarly simple that’s been solved a million times in a simple way). Edit: I just think stuff l…
I am using state machines to write reactive applications: https://brucou.github.io/documentation/
So far I have to say that it is a mixed experience. There is a cost to the abstraction and the indirection (that is fairly well known easy to describe even if we rarely do so due to some self-imposed no-negativity bias or having some interest in the game), and then there are the benefits that are less easy to describe because they depend highly on the nature of the problem that you are addressing.
I implemented a Medium clone application (https://codebase.show/projects/realworld) with state machines. The result is 47Kb (brought down to 39Kb after compiling the machine and other optimizations) vs. 70Kb for the Vue implementation or 160 KB for the React/Redux one (that implementation piles abstraction over abstraction in the form of libraries and pays the corresponding price). I would count that as benefit. Also cf. https://brucou.github.io/documentation/v1/tutorials/index.ht... for the full pitch.
The high-level machine is that one: https://brucou.github.io/documentation/graphs/real-world/rea...
At this level, you can follow the routing of the app. Every route is a compound state. If you open it, you see the details of the behavior. The full machine (post refactoring) is like this: https://brucou.github.io/documentation/graphs/real-world/rea...
So one advantage is that with those graphs, it is easier to onboard new folks arriving to the codebase. They just have to follow arrows to know what the code is doing in response to a series of inputs.
I could continue but with all that said, the Hyperapp implementation of the same application is 27Kb and also fairly simple (even if arguably not as simple) to get into. So there isn't a clear-cut ex-nihilo benefits to state machines here. In fact if you would have implemented the same application as a MPA instead of a SPA, for most, if not all of the pages, using a state machine to model the behavior is simply overkill. Most of the job and value of the machine in my example is to do the client-side routing done in the machine (so no extra library cost).
Anyways the bottom line is the tool is useful but you have to figure for what, and where is the value maximized. The obvious cases have already been figured out.