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

SSR Data are loaded only after refresh (SSR BUG related with useAsyncData - so every composable) #473

Open
Dinuz opened this issue Feb 2, 2023 · 7 comments
Labels

Comments

@Dinuz
Copy link

Dinuz commented Feb 2, 2023

Environment

  • Operating System: Darwin
  • Node Version: v18.13.0
  • Nuxt Version: 3.1.1
  • Nitro Version: 2.1.1
  • Package Manager: [email protected]
  • Builder: vite
  • User Config: debug, ssr, css, build, vite, modules, runtimeConfig
  • Runtime Modules: ()
  • Build Modules: -

Describe the bug

Fetching data from Apollo server works only after refresh.
On Page loading, the setup function doesn't fire the request to the Apollo server, but it waits until a refresh is performed.
The request then appear in the console network, and everything works fine (on page loading the request/fetch doesn't exist).

This happens only when the ssr option is set to true in nuxt.config (by default it is set to true). The behavior changes, and the fetch is performed also on page load when the ssr option is set to false (clearly).

Expected behaviour

I would expect that the first time I load a page, the request is normally performed to the apollo server, in this way I can populate the page with the data.

Reproduction

Someone in December opened an issue and tagged it as BUG, unfortunately the issue was closed just before the end of the year without a real resolution. For reference the following is the link to the issue:
https://github.com/nuxt-modules/apollo/issues/452#issue-1451729190

Additional context

I tried to investigate a bit the issue, and I noticed that under the hood, the module uses the useAsyncData (form the nuxt composable). This is amazing but it's worth probably point out that (the yellow alert in particular):

Screenshot 2023-02-02 at 6 47 46 PM

Maybe the problem is just here??

Logs

No response

@Dinuz Dinuz added the bug label Feb 2, 2023
@Dinuz Dinuz changed the title SSR Data are loaded only after refresh (SSR BUG realted with useAsyncData) SSR Data are loaded only after refresh (SSR BUG related with useAsyncData - so every composable) Feb 2, 2023
@Dinuz
Copy link
Author

Dinuz commented Feb 3, 2023

The way in which I "hacked" this is issue is the following:

<script setup>
  const query = gql`
    query getCategories {
      categories {
        data {
          id
          attributes {
            name
          }
        }
      }
    }
  `
const { data, refresh } = await useAsyncQuery(query)
if (!data.value) {
    refresh()
  }
</script>

So I am conditionally refreshing the data if they are indeed null. This trick allow me to perform the SSR :)

Maybe it's worth allowing an automatic refresh option when data are null and contemporarily we are using SSR.

@devhoangkien
Copy link

@Dinuz can you share apollo config in nuxt.config.ts and @nuxtjs/apollo version?

i used
node v18.12.1
@nuxtjs/apollo": "5.0.0-alpha.5 "
nuxt": "^3.1.1"
nuxt3": "3.1.2-rc.0-27922414.cb0860b"

export const getUsersQuery = gql`
  query users(
    $limit: Float
    $orderBy: [UserOrderByInput!]
    $page: Float
    $where: UserWhereInput
  ) {
    users(limit: $limit, orderBy: $orderBy, page: $page, where: $where) {
      pageInfo {
        page
        limit
        currentPage
        totalCount
      }
      docs {
        id
        firstName
        lastName
        email
        username
        roles
        avatar
        status
      }
    }
  }
`

/**
 * query data my user
 * if @data null return login
 */
const variables = {
  limit: 10,

  page: 1,
}

const { data } = await useAsyncQuery(getUsersQuery, variables)
if (!data.value) {
  navigateTo('/user')
}
const users = JSON.parse(JSON.stringify(data.value)).users

mine still return normal.

@Dinuz
Copy link
Author

Dinuz commented Feb 3, 2023

@devhoangkien sure (what do you mean still return normal??),

node version 18.13.0
"@nuxtjs/apollo": "^5.0.0-alpha.5"
"nuxt": "^3.1.1"

my nuxt.config is super basic:

export default defineNuxtConfig({
  debug: true,
  ssr: true, 
  modules: ['@nuxtjs/apollo',],
  apollo: {
    clients: {
      default: {
        httpEndpoint: 'http://localhost:1337/graphql',
      },
    },
  },
})

@dolbex
Copy link

dolbex commented Feb 8, 2023

I was having the exact same issues here but ensuring I was on beta-5 of nuxt apollo and nuxt 3.1.2 and everything began working as expected.

@sneakylenny
Copy link

sneakylenny commented Jun 6, 2023

Context

I use a Laravel Lighthouse backend and this only occurs to me when auth is required.

System and versions
Operating System: Windows 10 Pro
Node Version: v19.6.0
Nuxt Version: ^3.5.2
Nitro Version: 2.4.1
Package Manager: [email protected]
Builder: vite
@nuxtjs/apollo: 5.0.0-alpha.6
My nuxt.config.ts
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  modules: ["@nuxtjs/apollo"],
  apollo: {
    clients: { 
      default: {
        // Tried this too but results in same behavior.
        // httpLinkOptions: { 
        //   credentials: "include" 
        // }, 
        httpEndpoint: "http://myapp.test/graphql" 
      } 
    },
  },
});

Behavior

If I protect the query (requiring auth)
It does not load on initial load (like after refresh). Only when I manually press a button to request the data when the page has been loaded.

If I remove the protection from the query (no auth required anymore)
Everything works as intended. It does work on initial load and after refresh.

Visual example of behavior

nuxt-apollo
Removing the guard makes it work for ssr, but leaves the query unprotected.

It appears when the server is making the request it does so without auth. But I'd like to be able to protect my queries and have them loaded on initial load when authenticated.

The only way to get data is by calling the refresh method returned by the query method.

Workaround

Adding a plugin utilizing the apollo:auth hook and setting the token from the cookie seems to fix this issue for me in this case:

// plugins/apollo.ts

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('apollo:auth', ({ client, token }) => {
    // access cookie for auth
    const cookie = useCookie(`apollo:${client}.token`)

    // apply apollo client token
    token.value = cookie.value ?? null
  })
})

Other

  • I noticed useLazyAsyncQuery documentation shows useAsyncQuery instead of useLazyAsyncQuery in the example.
  • Using useQuery throws a 500 with message "Unauthenticated" which I assume is intended behavior if unauthenticated, but in this case I am authenticated.

@bask-digital
Copy link

I have a similar issue as @timyourivh, but in my case it works on refresh(SSR) and not on the client side. I am using the apollo:auth hook inside plugins/apollo.ts like so:

export default defineNuxtPlugin((nuxtApp) => {
    const { value } = useCookie("session_token");
    nuxtApp.hook("apollo:auth", ({ client, token }) => {
        token.value = `Bearer ${value}`;
    });
});

This works fine for SSR requests (like on refresh), but returns Bearer undefined for client side requests, like navigating between routes.

How can I get the cookie to work for client side requests? Any ideas?

@sneakylenny
Copy link

Saw that I replied in this thread and encountered this same thing not that long ago, again.
This time I ended up solving it with using a solution similar to a solution mentioned in this comment: #312 (comment)
Hope this helps anyone solve this.

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

No branches or pull requests

5 participants