Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: useFragment hook #8236

Closed
hwillson opened this issue May 17, 2021 · 7 comments · Fixed by #8782
Closed

Feature: useFragment hook #8236

hwillson opened this issue May 17, 2021 · 7 comments · Fixed by #8782

Comments

@hwillson
Copy link
Member

hwillson commented May 17, 2021

This issue will track the development of a useFragment hook.

Description

useFragment is a read-only reactive/live binding into the cache, providing an always-up-to-date view of whatever data the cache currently contains for a given fragment.

@smikula
Copy link

smikula commented Jun 8, 2021

@hwillson, is there any further documentation about the useFragment hook anywhere — what it does, or what problems it is intended to solve? If it is what it sounds like, it's a feature I'm very interested in.

@benjamn
Copy link
Member

benjamn commented Jun 8, 2021

@smikula I'm still working on a more official proposal, but what do you think of the following sketch?

const {
  data,     // Whatever data the cache can provide right now for this fragment
  complete, // True if no missing fields. Useful with returnPartialData: true
  errors,   // Provides any MissingFieldErrors from the cache
  // Last complete result read by this useFragment, in case data is undefined
  // and displaying stale data is acceptable
  previousData,
} = useFragment({
  // DocumentNode containing the fragment
  fragment,
  // Name of the fragment you want to use, in case the document contains multiple fragments
  fragmentName,
  // Minimal representation of the entity to read the fragment from
  // Can also be a Reference or an ID string, if you have that handy
  from: { __typename: "SomeType", id },
  // Various options shared by cache.diff and cache.read
  variables,
  returnPartialData,
  optimistic,
  canonizeResults,
});

As this sketch suggests, useFragment is a read-only reactive/live binding into the cache, providing an always-up-to-date view of whatever data the cache currently contains for a given fragment.

This architecture means Apollo Client can broadcast extremely specific fragment results to individual components that use useFragment, simply by dumping the results of all incoming queries into the cache. Relay works this way, and I'm very much coming around to it. Perhaps more importantly, Apollo Client has always been capable of this, so I don't want to leave these capabilities unused.

It's possible to implement something like this already (see #7072 (comment) for one version), but there are some remaining questions to answer around who (what code) is responsible for issuing the queries, in this new world of only/mostly fragments.

Reusing useQuery is certainly an option, but then the component gets subscribed to all changes in the query data, when it probably only cares about some small fragment of the query's data. I think a new kind of query hook will be necessary, or perhaps an additional sub-section within the useFragment options.

Let me know if/how that matches your hopes/expectations!

@smikula
Copy link

smikula commented Jun 8, 2021

@benjamn Yes, this is exactly what I was hoping for. When can I have it? :)

I'll take a look at the comment you linked — maybe something like that will work for me in the meantime.

@hwillson hwillson modified the milestones: v4.0 - Planned, June 2021, July 2021 Jun 17, 2021
@smikula
Copy link

smikula commented Jun 17, 2021

@benjamn, I'm still working through this. You mentioned:

There are some remaining questions to answer around who (what code) is responsible for issuing the queries, in this new world of only/mostly fragments.

Reusing useQuery is certainly an option, but then the component gets subscribed to all changes in the query data, when it probably only cares about some small fragment of the query's data. I think a new kind of query hook will be necessary, or perhaps an additional sub-section within the useFragment options.

Is using useQuery with a fetch policy of standby appropriate to this case? From the brief description, it sounds like "standby" means "fetch the data, but don't observe it unless I tell you to refetch". I think that's what you'd want, but I've dug into the PRs that introduced standby and it seems like it was intended to solve a different problem, so I'm a little wary of relying on it.

I'm not saying this would be the right way to do it in your v4 — you probably want an API that is more explicitly paired with useFragment. But for the short term, if I'm trying to implement a useFragment-like pattern, would that be a good way to go? If not, would you be open to introducing an option to useQuery that would tell it to fetch the date but not observe it?

@sebakerckhof
Copy link
Contributor

Really like the idea of this useFragment / useBackgroundQuery combo. Reminds me of a framework I used to use where the backgoundQuery was called a subscription and the cache acted as a client-side mongo db and the fragments where basically mongo queries on this cache that updated as the cache changed. Worked well for me.

@hwillson
Copy link
Member Author

This work was completed (#8782) and will be released in Apollo Client 3.7.

@jpvajda
Copy link
Contributor

jpvajda commented Sep 14, 2022

👋 The useFragment hook is now available as experimental in Apollo Client 3.7 beta You can review the documentation on this new hook here

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants