Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

For me the issue of state management mostly went away after starting to use React Query. It turned out that the most problematic state was server-side state for me, which is handled very well by libraries built for that purpose.

The state that remains is often simple enough that plain old React state management with useState/useReducer is sufficient. A lot of state can be local, and local state is easy to handle with the built-in tools of React. And global state is only really an issue if it changes often. For mostly static state like information about the current user, theme or UI settings and similar kinds of state using React Context works perfectly fine.

Of course this depends heavily on the kind of web application you write, if your application is closer to Photoshop in the browser than a simple CRUD app you probably can make good use of more complex state management libraries.



Agree completely, React Query has made it so much easier to build any kind of app that deals with server state, stuff that would have been extremely challenging to write in the past is now just a couple of lines and works better than before.

I personally like using Jotai (if I just want a better version of React Context) or Zustand (if I need a bit more than that) for “client state” alongside React Query, but I’ve also built projects where I didn’t need a client state management solution at all.


What’s wrong with React Context in your opinion?


For anything even slightly complex you need to either use multiple providers or be very careful about rerenders


Exact same experience here. We were using Redux to manage server-side data and switching to React Query massively simplified everything. It appears that managing server-side data in an efficient way is an insanely complicated topic and React Query just solved everything about it that I can think of.


Yeah, both the React Query and Redux maintainers agree that you shouldn't be writing data fetching and caching logic yourself. That's why we recently added a new "RTK Query" data fetching and caching API to Redux Toolkit, so that if you're using Redux it handles that work for you:

- https://redux.js.org/tutorials/essentials/part-7-rtk-query-b...

- https://redux-toolkit.js.org/rtk-query/overview

and if you're just using React, definitely look at React Query.


RTKQ is terrific. Between things like that and MUI, the level of productivity you can achieve really is amazing.

Also, thanks for your work -- really, really appreciate it.


Yes we chose Redux 6 years ago for data fetching and caching when there wasn't as many alternatives as today!


Hah, yeah, the ecosystem landscape has definitely changed over the last few years :)


I took a look at react query and it seemed to me that the core of it was caching the network request promises with named keys, so that you could inefficiently call the same endpoint redundantly a bunch of times and not get punished for it. Even if a codebase could get away with such sloppiness it should probably avoid it.

And then as I recall it featured some out of the box refetching to unstale the cached data. I think this core idea is pretty good, though I don't like the cultishness of the people who use this lib. And the vast majority of pages in the wild I have worked on don't need this auto-refresh, as the data will be static until the user does something new (i.e. because the user is viewing personal data). Even if I wanted to refresh the data often (i.e. I had a site like reddit) I would prob just roll my own custom refresh logic.

And then this

https://ui.dev/checkout/react-query?from=tanstack

If server side logic is "insanely complicated", and is routinely being solved in two lines post react query, instantly working better than files worth of server side data fetching code, why the need to charge 149 to learn the fundamentals? If I had taken a paid course to learn a state management library I would probably advocate for it everywhere I went.


It's a great benefit for a component to be able to specify what data it needs from remote without worrying about if an ancestor or sibling also needed it. React query will only fetch once the unique queries in the whole tree.

Without this feature, every component needing remote data D must share a parent ancestor fetching D for all of them, even when the children are not conceptually related. Adding another component higher in the tree means you have to hoist the fetcher up to that level, etc. React query is an incredible upgrade to anything else I've used over the years.


> must share a parent ancestor fetching D for all of them

What happened to the whole "service" pattern? Isn't this the core problem it solved for Java in the 90's?


An external service fetcher doesn't have integration with React because the entire tree potentially needs to know when the data changed. Once you write the code to subscribe to those changes where necessary, you've basically invented another state library.


* Service fetcher does fetching and updating store

* Component does subscribing

* React does updating component tree with changes.

If a component wants changes it must subscribe. If not, it doesn't.

If there is a change, subscribed components get updates. If not, they don't.

Responses are (conditionally) cached in the store by its respective service. Any component that wants data just asks the service. Service fetches from the store or remote. I can customize and unit test the the service.

I don't see the overlap in responsibility between any state lib (react or whatever in this case) and the purpose built service.

What is react query's role here ?


You’re hand-waving away “subscribing” as if it’s not a time bomb.

The set of possible events any given query might need to subscribe to is massive. Yes, you can build a large app with a pub/sub model but the number of subscriptions runs away from you and it gets really hard to know which of 1000 subscriptions you need to refresh when an association between two random pieces of data is created/deleted.

Associations are where you really get screwed IMO.

That said, despite exploring lots of possibilities I don’t think there’s any perfect way to do this automatically. So while I think you’re hand-waving away a hard problem, I also think your proposed solution is probably one of the better ones.

Still, I don’t think you should pooh-pooh people trying to solve the general problem. It’s a worthy one.


That's a sensible response, so thanks for that.

Being hard to define and manage subscriptions is a problem, a bigger deeper problem that react query or any other lib isn't solving.

By "set of possible events any given query might need to subscribe to is massive" i assume you meant "component" and not query, if not then i don't know what that means, if yes, that component needs refactoring.

I'm interested in libraries not because of what it can do for my code or me or my team but what problem it solved for the team that needed it in the first place, bad enough to write a lib for it. I want to avoid those problems.

I start with importing libs for quick TAT and slowly replace them with a few hundred lines of code that i can understand, modify, debug, monitor, unit and integration test. I usually end up redefining or better defining the problem and rescoping the issue to not needing to solve said problems.

Most libs do NOT provide that level of valuable solutions to worthy problems to go keep them around as deps. Deps are not free and have no liability to me or my code. React query is one more in that long list. IMHO.


I do mean “query”. I am presuming you want every query in your app to live update when the results change. The problem I’m indicate is: how do you know which queries are invalid after any given event?


> What is react query's role here ?

Its role is to do everything you just said in one package, plus other networking features. It fetches, updates the store, subscribes the components, caches the responses, performantly rerenders. It allows configuration of when to refetch, how to cache, polling, pagination, infinite scroll, etc etc via a simple API.

Nothing is stopping you from writing all this yourself, but libs exist for a reason. It's a terribly useful networking package. If you just use a generic store and write a fetcher yourself, you have to at the very least write logic for when to (re)fetch and for persisting the responses to the store.


  The state that remains is often simple enough that plain old React state management with useState/useReducer is sufficient
hah this is an understatement. For hooks, the React runtime already does a ton of non-standard-js things under the hood. useState gives a method to update and "subscribes" a component to updates on the hook's value. Put that code in a custom hook, export it and you re-invented Redux. In fact, exporting a single big useReducer for all your state gives you something almost identical to old style Redux.


FWIW, there _are_ a number of technical and conceptual differences between Context+`useReducer` and Redux. I wrote an extensive post describing those differences and potential use cases for each:

https://blog.isquaredsoftware.com/2021/01/context-redux-diff...


Redux now has its own query solution as well, it's pretty useful [0].

[0] https://redux-toolkit.js.org/rtk-query/overview


React query is one of the highest quality react libraries I’ve ever used


React Query's critical design flaw (from when I used it, anyway), is that data is scoped globally by default, as opposed to per mount.

Using the global cache is kind of the point, yes, but that's implicitly the case and that's the exact opposite of how useState works.

I think that is an egregious mistake, since it is totally unclear to a higher level consumer that this is the case.

This may seem unreasonable, but I've seen it cause severe issues due to this choice and I would recommend against it for many teams unless they can properly communicate that it does not match the behaviour of useState - you need to look through layers to be convinced it's going to do what you expect.

A simple flag to opt-in to the global cache associated to the provided key would solve a lot of problems.

To summarize, I like the API they provide a fair bit, but it's just too easy to misuse and create a damn mess.


data is scoped globally by default, as opposed to per mount.

Uh, is the cache key the same? To me it is 100% clear that the cache key is used for a global cache, and that this is one of the core design principles of the library. This global cache management is exactly what I desire over useState without writing my own boilerplate.


I personally liked the library for its query and mutation APIs, but would have preferred caching be left out or opt-in.

I ended up having to do this myself by wrapping it all up and providing an option for the caller to opt-in to the underlying global key. If the option was not passed, it would append a unique ID to the base key by default so it would become scoped to the particular mount.

IMO that should be the default behaviour.


Nothing implicit about react query caching requests. That's the whole point of the library in the first place, otherwise it would just be a fetch wrapper.

And having it behave differently from useState is fine, and correct. The library is used to fetch data, not state. Those are two different things


I disagree with the entire premise of the library then, because I consider a shared, global cache to introduce nothing but problems.

I like its query and request primitives, but I don't like that they are coupled to the cache.


It’s purpose in my mind is to model server state, which is fundamentally global state.

Are you using it for transient state? What are you using it for that’s meant to change between different parts of the app?

It kind of sounds like your namespace needs to be broader, are you using a singleton where a collection is needed?


This matches my experience as well. Additionally, React Query has support for features like retries and caching.


I've only used SWR. How does it compare? I


SWR does basically the same core thing (query, cache and mutation help) with less features.


That's exactly the reason why I choose SWR over ReactQuery.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: