Closed robhowell closed 9 months ago
Hey @robhowell 👋
Would you be able to provide a bit more info on how this is being triggered? Which hooks are you using, etc. Alternatively, a reproduction of the issue would be super helpful.
Thanks for bringing this to our attention!
Can you share which query is triggering this? Is this maybe a client-only query?
@jerelmiller @phryneas Sorry, I forgot to specify which exact hook was being used. After further investigation I have a number of extra details that limit the scope significantly and may help isolate the root cause:
useSuspenseQuery
when rendered via SSR then hydrated on the client sideOther possibly useful info:
useQuery
and this error does not occur, but then it does not load data during SSRThis is in an existing project with quite a lot of tech debt that we're working through as part of the migration to Next.js 13 & React 18. So it is very possible that one (or a combination) of these other factors could be triggering this error:
fetch
request (not using Apollo Client). As I have tried to configure it, this response should always be cached by Next but is only cached sometimes for some reason. This could introduce unexpected delays during the server render, but is not causing problems on any other pages.Sorry, but I'm not able to share the source code for this project, but here is a short snippet from where we are making the actual call:
const { data: initialData, loading } = useSuspenseQuery(query, {
fetchPolicy: 'cache-and-network',
variables: {
...variables,
limit: NUMBER_OF_PRODUCTS_TO_SHOW,
},
...otherOptions,
});
It is possible that this issue will resolve itself once some of the other issues in this app are fixed (e.g. hydration errors). I'll continue working through those issues, and will report back if any of those changes help.
@robhowell I just realized that "client-only" in the context of Next.js was very unspecific 😅
Did the query actually contain fields to be requested from the server, or did it only request fields marked with the @client
directive?
Can you show the query
in question? This is caused by that query being "special" in some way.
@jerelmiller @phryneas Thanks a lot for your quick responses btw, and thanks so much for creating this package! The project that I'm working on has been using Apollo Client for a few years so it is great to be able to still use it with React 18 & Next.js, without a lot of custom configuration. We still have a large number of components to migrate, but using Suspense & streaming SSR with Apollo should hopefully speed up many parts of the app :)
@phryneas Ah, that kind of "client-only"! No, we have used local resolvers etc in the past (still used in some other areas of the app) but not in this query.
I can't see anything especially unusual in this query. It will be okay to share this query here since this can be publicly seen in the browser dev tools for this app anyway:
export const GET_PRODUCTS_PAGE = gql`
query getProductsPage(
$limit: Int
$slug: String!
$zipCode: String
$stateCode: String
$regionId: String
$refreshCache: Boolean
) {
getProductsPage(
limit: $limit
slug: $slug
zipCode: $zipCode
stateCode: $stateCode
regionId: $regionId
refreshCache: $refreshCache
) {
filters {
id
label
options {
id
label
}
}
pageHtmlTitle
pageId
pageLongDescription
pageLongName
pageMetaDescription
pageName
products {
campaign
attributes {
id
values
}
id
name
onDisplayInShowroom
path
productFamily
productLabel
productType
quickship
rangeAttributes {
id
value
}
secondaryImage
secondaryImageCropData
slug
sortOrder {
featured
newest
popularity
}
variants {
image
label
originalPrice
path
price
quickship
isOutOfStock
sku
slug
tier
}
variantsTotal
}
totalProductCount
upholsteryOptions {
color
id
label
thumbnail
}
}
}
`;
Huh, that is very weird.
As you can see here in the sources that error should only ever appear if the query that is being transported does not contain any "server part".
Could you set a breakpoint at that error, and then execute print(options.query)
in the console and share the output? Maybe this query has been mangled in some way before it was transported to the client 🤔
Thanks @phryneas, that is really helpful!
I added a console log inside the if (!serverQuery)
conditional so I was able to see more details about the query that is throwing the error. I'm not sure how/why using useSuspenseQuery
on the same page could affect this, but the error is actually being triggered by a completely separate query that uses local fields, and makes that request via useQuery
.
Most of the global state in this app is not tightly bound to the data we load from the API via Apollo Client, so we have actually started to migrate the small number of local fields & Reactive Variables currently used over to Jotai. I'll prioritise migrating that state asap, which should resolve this issue for us.
I would rather not share the exact details of this other query publicly, but if you would like to debug this issue further (in case other users hit this in future) then I'd be happy to email it to you if that would be helpful?
I think we're onto something here, even without that email :)
Two things:
useQuery
from @apollo/client
, not from @apollo/experimental-nextjs-app-support
(please don't mix these!). Can you verify that changing that over would prevent this from occuring?useQuery
to useSuspenseQuery
, will the problem start occuring again? (I suspect yes, and that would be something we have to fix).@phryneas That totally makes sense, there are a lot of older queries in the codebase that are still importing from @apollo/client
.
I've just checked and that specific query is using an even older approach, one of the higher order components - imported like this:
import { graphql } from '@apollo/client/react/hoc';
It doesn't look like import { graphql } from '@apollo/experimental-nextjs-app-support/react/hoc';
works, so I assume that the react/hoc
exports are not available from the new package.
It is used in an old class component, so I'll need to convert it to a function component first. I'll do that this evening, then I can see if the bug still occurs when using useQuery
or useSuspenseQuery
.
Sorry if I've wasted your time with this, from a quick search online I've just found this info on the docs page:
Note: Official support for React Apollo higher order components ended in March 2020. This library is still included in the @apollo/client package, but it no longer receives feature updates or bug fixes.
So it looks like this project should have stopped using those features over 3 years ago! Given that it was deprecated such a long time ago, I don't anybody would reasonably expect that functionality to be supported in this new library, and I assume that is why we're seeing this error.
We have a number of instances of graphql
and withApollo
still being used across the codebase, so as part of this migration we'll convert them to function components where necessary, then use useSuspenseQuery
for those calls instead.
I'll at least try to explain to you what's happening here, so you can maybe find a workaround. A few puzzle pieces:
@apollo/client
s useQuery
triggers a query during render instead of during useEffect
, to also work in classic SSR scenarios (I'm pretty sure the HOC nowadays uses that internally)@apollo/experimental-nextjs-app-support
overrides that, as we are not in a classic SSR scenario and have no way of waiting for non-suspense hooks to rerender them and transport their results overSo, in your case, you'll have to avoid that query the same way we do:
https://github.com/apollographql/apollo-client-nextjs/blob/771a39fe824a344df6900d0593d465ba58631294/package/src/ssr/hooks.ts#L18-L21
We change the cache-policy
so no actual query happens and is transported over.
There might still be a few more puzzle pieces, since I've never personally had to deal with the HOCs, but I hope that's already enough to help you through this :)
@phryneas Thanks a lot, that is really helpful!
I'll report back after I've converted that component and updated it to use useSuspenseQuery
and will report back to confirm if/when it resolves the issue.
@phryneas After replacing the Higher Order Components used in that component I'm no longer seeing this error, so I'll close this issue now. Thanks for all of your help, we really appreciate it.
After upgrading
@apollo/client
from3.8.0-beta.5
to3.8.0-rc.2
and upgrading@apollo/experimental-nextjs-app-support
from0.3.1
to0.4.1
, I'm seeing the following error:Error: could not identify unique query
.In-browser stack trace shown below:
The dev console shows this:
We're using Next version
13.4.12
, using the app directory.We're in the process of upgrading a large existing app to React 18 with Next.js 13, so there are still a number of other issues that we need to fix. There are still some outstanding hydration errors that need to be resolved - including hydration errors which result in the page switching to client-side-only rendering - so it is possible that this error is only occurring because of the other outstanding issues. But this error did not show before I upgraded, so it seems to be related to recent changes in the
@apollo/experimental-nextjs-app-support
package.Has anybody else hit this issue, or has any suggestions about how I could resolve it?