Hacker News new | ask | show | jobs
by filoeleven 1653 days ago
This article gives a great rundown of various UI layer approaches, the problems with each, and how the subsequent ones solved them. I hadn’t seen react-query or its listed alternatives before, so thanks!

The one thing I’m not clear on is how this is much different from the “single global store” approach. It looks like that’s what this approach uses, and the main difference is in the “store API.” In other words, usage from components is nearly identical, and it’s the mechanics of the store itself that is changed. There’s a layer of focused queries between the store and components that hides the access (and maybe update?) mechanics from the widgets. So instead of

  getFromStore(“books”, bookId) // pseudocode, I am not a Redux user
you instead use

  useBookQuery(bookId) // which includes some nice things like { isLoading, error }
It doesn’t seem to resolve the need to handle the following bullet point found in the store drawbacks, it “just” pushes it into a group of queries (and presumably updates).

> we now have to deal with a completely new concept, the Store, and care about a bunch of new things, such as designing and maintaining Store structure, appropriately updating data in the Store, data normalization, […]

Is this separation the point? Or am I missing something else? Keeping the store access mechanics separated from the widgets that use them makes sense to me, especially when it has built-in loading/error notifications. I was going to say that “widget driven development” doesn’t really point to what this achieves by making that separation, but I may be coming around to the term with those other considerations.

I suggest emphasizing the loading/error mechanics more strongly at the end of the article. React is doing a lot of work with Suspense to improve their ability to give UI feedback in those states, and it looks like this approach simplifies the data side of that.

1 comments

Thank you for the valuable feedback!

Very good question about the difference between `getFromStore` and `useBookQuery`.

When using `getFromStore` you have the expectation that the value is already in the Store. Someone should have already put the value there somehow.

You have also the expectation that `getFromStore` is synchronous and simply gives you nothing if the value is not there.

With `useBookQuery` you expect the value to be fetched from Server. There is no 3rd party to care about putting the value in the Store. `useBookQuery` is simply like `fetch('...')` from a Component perspective.

With libs like ReactQuery every component "simply" fetches what it needs, sort of directly communicating to the Backend. No intermediary party (like a Store)

>React is doing a lot of work with Suspense ...

Yeah, I heard about React team collaboration with libs like ReactQuery on making Suspense work with those, also on server side. But I'm not much into that Suspense topic, so decided to not mention anything about it.

>I suggest emphasizing the loading/error mechanics more strongly at the end of the article.

Thanks for the suggestion. I will think about it.

> With libs like ReactQuery every component "simply" fetches what it needs, sort of directly communicating to the Backend. No intermediary party (like a Store)

But in the article, you wrote:

> What if we could have an intermediate player between our components and Backend, say an API wrapper or interceptor, solving all those problems under the hood: [deduping, consistency, invalidation/automatic data refresh, hiding implementation]

The way I look at it, I don’t expect (or want) the value to be fetched from the server, I expect it to be fetched from “the single source of truth that abstracts the server away from my widget’s concerns.” I still think of that as a store, because that’s what stores advertise themselves as, it’s just one with a better API. The differences in how we are talking about this may come down to semantics—or maybe you can trust your servers more than I trust mine :)

To me, “directly communicating with the backend” implies that I have to have REST calls in my components, and handle all that comes with that, and that makes me want to run and hide. I don’t think that is your intent. There is still an intermediary here, and it is one that better separates ALL of the data fetching aspects from the widget by being async and providing good feedback on request/response status. Your diagram with the “API Wrapper” in it displays this quite well.

It’s a good design principle; it’s how I want to build things! At work we recently migrated to React, and I tried to follow similar principles without awareness of things like ReactQuery. I will definitely be looking more into this (especially the update side of things), and thinking about if/how it could simplify what we are doing. I’m not sure if it will work for us, but maybe I can at least steal a few more good ideas.

Thanks for writing the article and answering my question!

>But in the article, you wrote:

I also wrote a bit below: "be transparent to components and not affect their logic in any way (make components think they communicate to Backend directly)"

I met people trying to use ReactQuery with the mindset that it's a Store. The result was that they were greatly frustrated with the outcome. That mindset led them to use ReactQuery in a way it's not supposed to be used. Every now and then they wanted to directly manipulate with the Cache (the "Store" underneath ReactQuery).

That's why I find that Store-mindset very dangerous when working with such Libraries.

Better come with a mindset that there is no Store at all. Better think that "useBookQuery" is just a simple hook to fetch data. NO STORE.

>To me, “directly communicating with the backend” implies that I have to have REST calls in my components, and handle all that comes with that

This is exactly what I meant :)

I'm glad that you found the article useful. Thanks again for providing your feedback!

Thanks again for your thoughtful response.

I have more questions about whether ReactQuery can help me out when working with a bad legacy API, but I don’t know how to ask them clearly. It would be unfair to ask you to understand the system I’m working with, especially when you’ve already written an article that clearly describes the idea and have been so generous with your responses. I will be looking at this more deeply for sure.

This kind of thing is why I come to HN.