Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent unnecessary refetch using Apollo Client useQuery hook?

I'm trying to implement a CRUD application using Apollo Client using nextJS and the serverless Framework as GraphQL backend. Is there any way to prevent unnecessary automatic refetch during app navigation using the cache?

For instance, I'm creating a new record with a mutation, adding refetchQueries will refresh the cache, but assuming the user is navigating to another view and then coming back to the view using useQuery hook, the data will be fetched again, but it's supposed being already in the cache.

Here's my ApolloClient configuration:

import {ApolloClient} from 'apollo-client'
import {InMemoryCache, NormalizedCacheObject} from 'apollo-cache-inmemory'
import {createHttpLink, HttpLink} from 'apollo-link-http'

import {default as fetch} from 'isomorphic-unfetch'
import {config} from '~config'
const {IS_SERVER} = config

import {getToken} from '~security'
const token = getToken()
import {setContext} from 'apollo-link-context'

const authLink = setContext((_, {headers}) => {
    return {
      headers: {
        ...headers,
        Authorization: token && `Bearer ${token}`,
      }
    }
})

const httpLink = createHttpLink({
    uri: 'http://localhost:4000/graphql',
    fetch
})

let apolloClient: ApolloClient<NormalizedCacheObject> | null = null
const create = (initialState = {}): ApolloClient<NormalizedCacheObject> => {
  const httpLinkConfig: HttpLink.Options = {
    uri: 'http://localhost:4000/graphql',
    credentials: 'same-origin'
  }
  if (!IS_SERVER) {
    httpLinkConfig.fetch = fetch;
  }
  return new ApolloClient({
    connectToDevTools: !IS_SERVER,
    ssrMode: IS_SERVER,
    link: authLink.concat(httpLink),
    cache: new InMemoryCache().restore(initialState)
  })
}

export const initApollo = (initialState = {}): ApolloClient<NormalizedCacheObject> => {
  if (!IS_SERVER) {
    return create(initialState)
  }
  if (!apolloClient) {
    apolloClient = create(initialState)
  }
  return apolloClient
}
like image 215
dbrrt Avatar asked Oct 16 '25 15:10

dbrrt


1 Answers

Actually I found the solution to this issue after reading my config file.

Here's my _app.tsx file:

I realized that I was rendering calling initApollo() in the render of App, which ended in recreating an Apollo Client every time the location was changing.

Importing directly client from the apollo definition prevents against recreating a new client at location change.

 // apollo config file
export const client = initApollo()
    import React from 'react'
    import App from 'next/app'
    import {client} from '~apollo'
    import {ApolloProvider} from '@apollo/react-hooks'

    import {Provider} from 'react-redux'
    import {ConnectedRouter} from 'connected-next-router'
    import {store} from '~store'

    interface AppProps {
      ctx: any,
      Component: any
    }

    class Application extends App<AppProps> {
        static async getInitialProps(props: AppProps) {
          const {Component, ctx} = props
          const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {}
          return {pageProps}
        }
        render = () => {
            const {Component, pageProps} = this.props
            return (
                <ApolloProvider client={client}>
                  <Provider store={store}>
                    <ConnectedRouter>
                      <Component {...pageProps} />
                    </ConnectedRouter>
                  </Provider>
                </ApolloProvider>
            )
        }
    }

    export default Application
like image 114
dbrrt Avatar answered Oct 18 '25 06:10

dbrrt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!