sanity-io / next-sanity

Sanity.io toolkit for Next.js
https://www.sanity.io/
MIT License
771 stars 92 forks source link

defineQuery with multiple requests only retrieves the first request #1765

Open cmolisee opened 2 weeks ago

cmolisee commented 2 weeks ago

In my project I have content from 4 documents I need to retrieve on a single page. When using the vision tool I can correctly retrieve all the documents. When using defineQuery() and actually running the query I am only ever getting results for the first query and none of the others.

query: export const multipleQueries = defineQuery({ 'a': *[_type == "aDocument"][0], 'b': *[_type == "bDocument"][0..4], 'c': *[_type == "cDocument"][0..4], 'd: *[_type == "dDocument"][0..4], });

when running the above I get results for 'a' but everything else is an empty array. when i remove 'a' i get results for 'b' but everything else is an empty array. likewise for the remainder.

To Reproduce

  1. create 4 different documents
  2. using next-sanity defineQuery() create a query for those documents as above
  3. using client.fetch(multipleQueries).catch(..) in a server side next page observe the behavior

Expected behavior

I should receive content for ALL the queries as I do in when using the vision tool and not just the first query

Which versions of Sanity are you using?

using react 18, sanity 3.44, next-sanity 9.3.10

What operating system are you using?

MacOS sonoma 14.5

Which versions of Node.js / npm are you running?

npm -v && node -v 10.2.0 v21.7.1

stipsan commented 2 weeks ago

Can you try setting the Perspective in Vision to Published?

image

Vision uses your Studio auth and have access to draft content. When you fetch data from next.js, then unless you give your createClient() a token, it'll only have access to the data that's published.

cmolisee commented 2 weeks ago

Can you try setting the Perspective in Vision to Published? image

Vision uses your Studio auth and have access to draft content. When you fetch data from next.js, then unless you give your createClient() a token, it'll only have access to the data that's published.

I changed the Perpective to published as described and I am getting all the results as expected.

I am making the request on a server side rendered page in an async function following recommended practice of Next. I tried moving the request into a client component to see what would happen and the request inside of the client component is actually returning all the results as expected.

I'm thinking there is something going on with SSR and the readablestream that sanity query returns. I don't understand why but I am looking into possible solution like suspense, swr, changing the request strategy to be done in a client component, or otherwise.

EDIT: SWR has a lot of restriction in Next with app router so I won't be using that.

If my theory is correct then the next question would be is this expected behavior?

cmolisee commented 2 weeks ago

Alright. So I did a test using suspense and on the ssr page and i got the expected results.

My best guess is that sanity takes the each of the queries individually and doesn't wait for the all to resolve before sending back data. Thus, when the first one resolves it gets sent back and then ssr proceeds thinking it has everything it needs - which is why the remaining query result aren't included.

throwing in suspense it will actually give me all the results as they come through the readablestream returned by sanity query. still not sure if thats expected behavior or not. as far as a solution goes it seems suspense makes the most sense.