I’m trying to implement @nonreactive in my codebase but I really can’t get it to work.
The only problem that I think might be happening is that the fragment that needs to be nonreactive is deeply nested Apollo can’t target it. Also the updates to the data item happen via subscriptions but I think that’s expected?
I’ve added @nonreactive from the query all the way to the fragment and that still hasn’t worked. I’ve also registered all of the fragments via createFragmentRegistry and nothing.
There’s not a lot of info out there about @nonreactive so just wondering if there’s something that needs to be done to get it working properly that isn’t well documented.
Some ideas is if the subscription also needs to have @nonreactive, that this only works well on shallow queries, or does it not play well with variables on the query (which the top level query has)? Is there maybe something that has to be done on the server?
Sure. I’m going to just replace specifics but hopefully it still gets the point across.
These are my queries and fragments, I’m going to write them as I would expect would be needed to use @nonreactive:
const QUERY = gql`
${PAGE_CHILDREN_FRAGMENT}
query MyQuery(
$url: String!
$filters: Filter # objects of arrays of strings
$filterInput: FilterInput
$selectedFilterId: ID
$offset: Int!
$limit: Int!
) {
page(canonicalUrl: $url) {
id
pageChildren {
id
...PageChildrenFragment @nonreactive
}
}
}
`
export const PAGE_CHILDREN_FRAGMENT = gql`
${FILTER}
${SHELF_CHILDREN_FRAGMENT}
fragment PageChildrenFragment on PageChildren {
id
filters(filterInput: $filterInput) {
...Filter
}
shelfChildren (
filters: $filterInput
limit: $limit
offset: $offset
) {
...ShelfChildrenFragment @nonreactive
}
}
`
const SHELF_CHILDREN_FRAGMENT = gql`
${ITEM_FRAGMENT}
fragment ShelfChildrenFragment on ShelfChildren {
nextOffset
shelfSectionChildren {
id
...ItemFragment @nonreactive
}
}
`
const { data } = useQuery(QUERY, variables: { ... })
I have a subscription that’s updating the Item but that’s all.
Whenever there’s an update to that Item, but nothing else, the data query is still returning data on update. To my understanding the QUERY should not be reacting to the update, just the Item which I’m using useFragment within a component to retrieve.
What is the behaviour you expect here and the behaviour you see? I’m not 100% sure what you mean by
Whenever there’s an update to that Item, but nothing else, the data query is still returning data on update.
Do you mean that the component is forced to rerender when it shouldn’t, or that the value of data changes?
From the back of my head (I’d had to verify), @nonreactive would only prevent your component from rerendering as a result of data change, but if it were updated due to something else, it would still return up-to-date data.
Typically there’s a relationship between useQuery and useSubscription via the cache. When there’s an update via a subscription to an Item then MyQuery resends the updated data of the entire query, which includes the updated nested item.
Adding @nonreactive to Item would prevent the resending of data from the top level MyQuery when a subscription updates an Item, which is not what I’m seeing.
When I add @nonreactive then MyQuery continues to resend data on every update of Item.
I have to admit that I am a bit confused by the term “resend” - I’ve never head that used in the context of React, that’s why I’m asking for clarification here.
There are two different concepts you could possibly mean by that:
the component using useQuery rerenders actively when the @nonreactive item changes in the cache
if the component using useQuery renders for another reason (maybe because a parent componetn rerenders), useQuery returns up-to-date data
And just to make sure, the useSubscription hook is not at the top, it’s in a nested component, preferrably one without children?
Just want to make sure, because that one could also cause rerenders