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

writeFragment not working with @apollo/client@rc.9 #6495

Closed
wallzero opened this issue Jun 26, 2020 · 6 comments
Closed

writeFragment not working with @apollo/client@rc.9 #6495

wallzero opened this issue Jun 26, 2020 · 6 comments

Comments

@wallzero
Copy link

Intended outcome:

After updating from @apollo/client@3.0.0-beta.50 to @apollo/client@rc.9, updating the cache in a resolver using cache.writeFragment no longer works.

Actual outcome:

Cache does not update and no errors are thrown.

How to reproduce the issue:

These are the following fragments and query:

fragment TabSettingsSelect on TabSettingsSelect {
    index
    name
}
#import "./TabSettingsSelect.gql"

fragment TabSettings on TabSettings {
    select {
        ...TabSettingsSelect
    }
}
#import "./TabSettings.gql"

fragment TabSettingsQuery on Query {
    tabSettings @client(always: true) {
        ...TabSettings
    }
}
#import "../../fragments/TabSettings/TabSettings.gql"

query TabSettings {
    tabSettings @client(always: true) {
        ...TabSettings
    }
}

This is my resolver:

import {
	MutationResolvers,
	Query as State
} from 'src/@types/schema~';
import {TabSettingsQuery} from '../../schema/fragments';

export default {
	tabSettingsSelect (
		_root,
		{
			index,
			name
		},
		{cache}
	) {
		const {tabSettings}: State = cache.readFragment({
			fragment: TabSettingsQuery,
			fragmentName: 'TabSettingsQuery'
		});

		const select = {
			...tabSettings?.select,
			index,
			name
		};

		const data = {
			tabSettings: {
				...tabSettings,
				select
			}
		};

		cache.writeFragment({
			data,
			fragment: TabSettingsQuery,
			fragmentName: 'TabSettingsQuery'
		});

		return select;
	}
} as MutationResolvers;

Versions

I am currently using @apollo/client@rc.9 but I have the above issue with every version after @apollo/client@3.0.0-beta.50.

@wallzero
Copy link
Author

If I use cache.writeQuery in my resolver, everything works as before and my cache will update.

Here is my resolver using the above query, which is using the same fragments.

import {
	MutationResolvers,
	Query as State
} from 'src/@types/schema~';
import {TabSettings} from '../../schema/queries';

export default {
	tabSettingsSelect (
		_root,
		{
			index,
			name
		},
		{cache}
	) {
		const {tabSettings}: State = cache.readQuery({
			query: TabSettings
		});

		const select = {
			...tabSettings?.select,
			index,
			name
		};

		const data = {
			tabSettings: {
				...tabSettings,
				select
			}
		};

		cache.writeQuery({
			data,
			query: TabSettings
		});

		return select;
	}
} as MutationResolvers;

@benjamn benjamn added this to the Release 3.0 milestone Jun 26, 2020
@benjamn benjamn self-assigned this Jun 26, 2020
@benjamn
Copy link
Member

benjamn commented Jun 26, 2020

While it is now possible to call cache.writeFragment without providing the ID of the object you're trying to write (thanks to 7202b78 in #6350, released in beta.51), in this case your data is not going to be identifiable, because it doesn't have a __typename or any key fields. Of course, that's because the object you're writing to is simply the ROOT_QUERY object, which means your usage of writeFragment is essentially equivalent to cache.writeQuery (where the ID is assumed to be ROOT_QUERY).

In other words, I would guess that the following code will fix the problem:

cache.writeFragment({
	id: "ROOT_QUERY", // new
	data,
	fragment: TabSettingsQuery,
	fragmentName: 'TabSettingsQuery'
});

but that seems more complicated than cache.writeQuery({ data, query: TabSettings }) from your second comment.

@wallzero
Copy link
Author

Sure enough, that works!

However, the data does have __typename. I am not inserting it manually because the result of cache.readFragment includes it, and I spread the results into data. If I inspect data, __typename is there:

{
    "tabSettings": {
        "select": {
            "index": 2,
            "name": "home",
            "__typename": "TabSettingsSelect"
        },
        "__typename": "TabSettings"
    }
}

I tried adding __typename: 'ROOT_QUERY' to the root of data but that didn't work. I still have a lot of confusion surrounding id's. I thought they were only necessary on listed items.

@benjamn
Copy link
Member

benjamn commented Jun 26, 2020

Ahh, that needs to be __typename: "Query", since ROOT_QUERY is the ID of the root query object, but Query is the name of the type.

In general, writeFragment always requires an ID, which can be passed explicitly with options.id, or inferred from options.data, though that inference will only work if you provide options.data.__typename and any other necessary key fields (in this case, the __typename: "Query" should be enough because the root query object is a singleton). However, whenever the ID is ROOT_QUERY, that almost always means you should just use writeQuery instead of writeFragment.

@wallzero
Copy link
Author

That makes sense. __typename: 'Query' wasn't included because of how I am using the spread. However I tried adding __typename: 'Query' manually and it still doesn't work:

const data = {
	__typename: 'Query',
	tabSettings: {
		...tabSettings,
		select
	}
};

It's alright though. I think I am getting a better grasp at what is going on. cache.writeQuery is typically used for ROOT_QUERY data, like application settings and such - things without explicit id's. While cache.writeFragment is for listed items which would naturally come with id's such as tabs, posts, todo's, etc. Is that sort of the right mindset?

@benjamn
Copy link
Member

benjamn commented Jun 26, 2020

Yep! That's exactly the right mindset.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants