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 alle…
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.
In React {Transitions} = F(state)
31–40 of 55 posts
Re: In React {Transitions} = F(state)
#32Earlier quoted context omitted.
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.
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…
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).
Re: In React {Transitions} = F(state)
#33The one project I've used that had redux was also a complete nightmare to work with, and hooks are the blessed way now apparently.
Re: In React {Transitions} = F(state)
#34Every 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.
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.
Re: In React {Transitions} = F(state)
#35I 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.
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.
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.
Re: In React {Transitions} = F(state)
#36"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.
Re: In React {Transitions} = F(state)
#37The #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 alle…
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.
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.
Re: In React {Transitions} = F(state)
#38Why 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?
- is the default way that most humans interact with computers
- is an extraordinarily broad problem space and solution space
- is something that basically every modern software company needs to do in some capacity, and with even a few developers, abstractions become desirable
I'm not saying there wasn't a better way for React to adopt FP principles. I certainly have my own gripes.
But to start a conversation with "why does the most widely adopted framework for the most broadly-used software interface in history have some rough edges?" seems, to me, to be sort of begging the question.
Re: In React {Transitions} = F(state)
#39The #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 alle…
You know, about 7 years ago I would have heartily agreed with you. KISS, right?
The thing is, it just doesn't make financial, UX, or security sense to do that. The cost of storing every jot and tittle on the backend is huge. The collateral of anything happening to the backend becomes larger. Enjoy benign things like preferences/app settings, unsent comments not having to be rewritten because your session expired, etc? If you're not storing them via local storage, you can KISS that goodbye.
Re: In React {Transitions} = F(state)
#40Earlier quoted context omitted.
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.
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 befor…
Unfortunately, many people use inappropriate levels of abstraction (useEffect and/or redux) and it becomes an architectural problem.