apollo-feature-requests icon indicating copy to clipboard operation
apollo-feature-requests copied to clipboard

Better Cache Behavior With Read Only Fields

Open david-morris opened this issue 3 years ago • 2 comments

When one has a read function for a client directive field, at least with the MockedProvider, the query hook will always return undefined once before returning the values.

This is difficult behavior to work with because I use react-hook-form and need to have initial values ready to feed into another hook as default parameters. So I use one unified system to choose between showing a skeleton or rendering my page, and I don't want to reach into that system to grab the default values I want.

Additionally, this will prevent a needless re-render.

In the meantime, @client is nearly useless to me. I won't use local only fields.

david-morris avatar Mar 18 '22 13:03 david-morris

Hey @david-morris 👋

This is an interesting request. I'd be curious if you could go into more detail or present a code sample to better explain what you're looking for.

When one has a read function for a client directive field, at least with the MockedProvider, the query hook will always return undefined once before returning the values.

I'm curious, are you seeing this issue strictly in the testing environment? Or do you see this in your production environment as well?

The MockedProvider still uses much of Apollo's core, the big difference being that the link chain when using MockedProvider uses a MockLink rather than HttpLink to avoid real network requests and instead returns mocks passed to MockedProvider. read functions, caching, etc should all work like they do otherwise in a production/development environment.


It would make sense to me that the result is undefined at least once, unless you've written a fully defined cache result before your test executes. If you want to work with partial data, you'll need to set the returnPartialData option to true in order to receive a partial cache result. In all other situations, data will return as undefined until you have a fully defined result that satisfies your query. In your tests, read functions will execute, but a single read function doesn't guarantee that it satisfies a full query result, so you may still see an undefined data until the result loads.

I'd love to hear some additional ideas on what you're looking for to ensure what you're looking for isn't already possible now. Let us know how we can help!

jerelmiller avatar Apr 14 '23 00:04 jerelmiller

@jerelmiller we use storybook a lot in development, so I'm not sure, but if I remember correctly this problem also happens when using real GraphQL in our dev environment.

So if I remember correctly, it's a matter of if you had say, <Outer> which checked loading of useSomeQueryWithClientFields to decide whether to render <Skeleton> or <Inner>, if you tried to useSomeQueryWithClientFields the data of that would be undefined the first render.

const Outer = () => {
    const { loading } = useSomeQueryWithClientFields()
    if (loading) return <Skeleton />
    return <Inner />
}

const Inner = () => {
    // ok, since we don't render this component until the cache is populated, this should be fine
    const { data } = useSomeQueryWithClientFields()
    // oh no! Cannot access field of undefined!
    const foo = data.any.field.whatsoever
    ...
}

david-morris avatar Apr 14 '23 08:04 david-morris