Infinite loop caused by Type Policy with read function
See original GitHub issueMy app has a User
type for which I’ve defined a type policy:
User: {
fields: {
createdAt: { read: (date) => date ? parseISO(date) : null },
},
},
I also have a query to fetch the currently logged in user, and a HOC is used to fetch that user and render sub components.
const GET_SELF = gql`
query me {
me {
...userFragment
prefs { ...userPrefsFragment }
}
}
${Users.userFragment}
${Users.userPrefsFragment}
`;
const UserProvider = ({ render }) => {
const { error, loading, data: { me } = {}, refetch, subscribeToMore } = useQuery(GET_SELF, { fetchPolicy: 'cache-first' });
<snip>
if (loading) return <Loading />;
return render(me);
}
Now, in a subcomponent I’m running a query which fetches a set of users:
export const GET_MISSION = gql`
query mission($id: ID!) {
mission(_id: $id) {
users { ...userDisplayFragment }
}
}
${userDisplayFragment}
`;
When that query returns the currently logged-in user as part of the users
list, the code enters into an infinite loop.
The fields returned for the currently logged in user are merged into the user object in the cache. Despite the fact that these fields have not changed the value of that user object, this causes the ‘me’ query to rerun, which reruns the ‘mission’ query above, which leads to the infinite loop.
However, if I remove the createdAt
field from the Type Policy for the User object then everything works.
I thought that I be able to work around the issue be returning the exact same parsed date object when the date doesn’t change:
class DatePolicy {
constructor() {
this.prevDate = null;
this.prevParsedDate = null;
}
read = (date) => {
if (date !== this.prevDate) {
this.prevDate = date;
this.prevParsedDate = date ? parseISO(date) : null;
}
return this.prevParsedDate;
}
}
And using this class in the Type Policy:
User: {
fields: {
createdAt: new DatePolicy(),
},
},
however that doesn’t solve the problem.
If however the read function returns the object unchanged then the loop is avoided:
read = (date) => date
So, it seems that when a read function that returns a value other than that passed in will force the query to re-run.
Versions
System: OS: macOS 10.15 Binaries: Node: 12.13.1 - ~/.nvm/versions/node/v12.13.1/bin/node Yarn: 1.19.2 - /usr/local/bin/yarn npm: 6.12.1 - ~/.nvm/versions/node/v12.13.1/bin/npm Browsers: Chrome: 85.0.4183.102 Firefox: 77.0.1 Safari: 13.0.2 npmPackages: @apollo/client: ^3.2.0 => 3.2.0 apollo-link-logger: ^1.2.3 => 1.2.3 apollo-server-express: ^2.17.0 => 2.17.0
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:6 (2 by maintainers)
Top GitHub Comments
Hey @timothyarmes
Thanks for sharing this I was having the exact same issue. I came across this issue and @theodorDiaconu has done a brilliant job creating a small package that does what we want here. I followed his example and it works beautifully.
Good luck 😃
Gentle reminder that we’re looking for reproductions. I greatly prioritize any issue which I can run, and I got a lot of issues on my plate at the moment. If not, I will get to this soon no worries 😇