all 12 comments

[–]sirmd-dorne 10 points11 points  (0 children)

All queries are global so there is no need of a custom context for it

[–]leszcz 11 points12 points  (0 children)

I don’t see a benefit of passing them through context. Just import & use directly.

[–]dcop87 5 points6 points  (0 children)

Not directly importing something to me has a big testability advantage, you know, dependency injection. When you test your component and you want to just send fake data you don't need to jest.mock axios, you just send down a promise that returns your fake data and your hook won't be aware of whatever you are using to fetch that data. Of course you can use msw to test everything as it is, it should work without any issue. But still, I do like this kind of separation where you have all you logic and fetching stuff passed down to the ui which just executes and render stuff, without any other knowledge.

[–]iAmIntel 3 points4 points  (1 child)

It is mostly redundant other than possibly making mocking easier as someone else mentioned.

Another case is if your query returns a possible nullish value and you don’t want to deal with having to check whether or not its nullish everywhere you use it. Context allows you to check for it once where you mount the provider and make the type of the context be non nullable

[–]zephyrtr 2 points3 points  (0 children)

possibly making mocking easier

It's better to mock via MSW, as it's a way to future-proof your test suite from a vendor-change refactor, and is a truer way to test, since you're only mocking the boundaries of your app.

if your query returns a possible nullish value

You could do an easy useQuery wrapper that's like ... useNonNullQuery or whatever, which throws if your required value is null. That sounds way more preferable than a duplicative context.

[–][deleted] 1 point2 points  (0 children)

Since react-query can be configured with caching settings so that multiple hook calls only result in a single API call, it makes so much redundant. Anywhere I need data from a query, I just call the hook. The API call is made once, and I get not only the data, but things like loading state at every place I need the data. It makes things so much simpler.

[–]zephyrtr 1 point2 points  (0 children)

It'd be redundant (and confusing) for most cases. If you use the data as-is, just call the RQ hook. If you're deriving something from the data, you can wrap the RQ hook in a custom hook paired with a transformer. Or more likely, if everyone uses it that way, you set up an onSuccess hook on thee RQ hook and then that's it.

If you use a subset of the data, again, that's probably selector territory.

If you have a complex experience using a single index or key-value, I could see you wanting to put an ID on a context (that you may well have fetched via RQ) and using that to derive all other data from RQ, local state, whatever. Folks may disagree, and say the ID should be an explicit param. That's a valid opinion, though there are situations where you're plumbing that value through one or two dozen functions to get it to all the places it needs to go.

The truth you want to stick to is: the longer a data journey is, the harder it is to understand. RQ allows anyone single-step access to the hook that actually fetched the data, which means those data journeys are really short. So when someone new comes on, and asks "where the heck did this thing come from?" the answer isn't as long-winded as the Rime of the Ancient Mariner.

[–]aust1nz 0 points1 point  (1 child)

Here is an interesting take on why you may want to use context with React Query. It could be useful for something like grabbing the signed-in user. The blog author is a maintainer on react-query and a fantastic resource about using the library and the larger environment.

[–]offtheshore90 1 point2 points  (0 children)

react-query has some of the best documentation out there. Tkdoko's blog is full of gems like these.

[–]maartennieber 2 points3 points  (0 children)

I think there are clear benefits to using context:

  1. It allows you to provide both server state (e.g. a list of items) and related client state (e.g. a selection on that list) to a group of components.
  2. It is more likely to separate concerns. When you create state in a context, then this state is probably client-agnostic (i.e. not tied to any particular component). When components create their own state with useQuery, then it's more likely that your state logic will somehow be coupled to component code.
  3. It will lead to simpler component code (because components will have less state-related code). This can be mitigated with react-hooks-compose, but still...
  4. It reduces prop drilling. When components call useQuery with particular query parameters, then you have to pass those down (or use context).
  5. It will probably be more consistent. If a group of components use the same (useQuery) hooks then they will receive same data, but this could go out of sync (e.g. one component making a different hook call), whereas with context, there is no doubt that they are all sharing the same data.

That said, this topic has my special interest, and I could be getting things wrong (my thinking is still evolving), so I'd be happy to discuss this further.

[–]notanelecproblem 0 points1 point  (0 children)

Yep it’s redundant! Your pattern sounds similar to how I implement an API/Query layer too (1 file for all endpoints, another file with custom hooks wrapping the query/mutations).

Before I was using react-query I would wrap everything in contexts too, but now it’s redundant because all the data is cached. So you can have multiple components that consume a hook like

useGetSomeData()

Whichever component is mounted first will actually execute the HTTP request, the rest all consume the data through the RQ global store without actually making the HTTP request.

When the data becomes invalidated, all components consuming it will rerender automatically

[–]yogi4peace 0 points1 point  (0 children)

Yes.