How to use Apollo Client in Vue

Using Apollo Client in Vue provides a comprehensive GraphQL solution with intelligent caching, optimistic updates, and reactive query management for enterprise-grade applications. As the creator of CoreUI with extensive Vue experience since 2014, I’ve implemented Apollo Client in numerous enterprise applications for sophisticated data management and real-time user experiences. The most effective approach involves integrating Apollo Client with Vue 3 using the official Vue Apollo plugin for reactive queries and seamless state management. This method provides advanced caching strategies while maintaining excellent developer experience through declarative query composition and automatic UI updates.

Integrate Apollo Client with Vue using @vue/apollo-composable for reactive GraphQL queries and intelligent caching.

import { createApp } from 'vue'
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client/core'
import { DefaultApolloClient, provideApolloClient } from '@vue/apollo-composable'
import { gql } from '@apollo/client/core'

// Apollo Client setup
const httpLink = createHttpLink({
    uri: 'http://localhost:4000/graphql',
    headers: {
        authorization: `Bearer ${localStorage.getItem('token')}`
    }
})

const cache = new InMemoryCache({
    typePolicies: {
        User: {
            fields: {
                posts: {
                    merge(existing = [], incoming) {
                        return [...existing, ...incoming]
                    }
                }
            }
        }
    }
})

const apolloClient = new ApolloClient({
    link: httpLink,
    cache,
    defaultOptions: {
        watchQuery: {
            errorPolicy: 'all'
        }
    }
})

// Vue app setup
const app = createApp(App)
app.provide(DefaultApolloClient, apolloClient)
provideApolloClient(apolloClient)

// GraphQL operations
const GET_USERS = gql`
    query GetUsers($first: Int!, $after: String) {
        users(first: $first, after: $after) {
            edges {
                node {
                    id
                    name
                    email
                    avatar
                    posts {
                        id
                        title
                        content
                        createdAt
                    }
                }
                cursor
            }
            pageInfo {
                hasNextPage
                endCursor
            }
        }
    }
`

const CREATE_POST = gql`
    mutation CreatePost($input: CreatePostInput!) {
        createPost(input: $input) {
            id
            title
            content
            author {
                id
                name
            }
            createdAt
        }
    }
`

// Vue component with Apollo Client
import { useQuery, useMutation } from '@vue/apollo-composable'
import { ref, computed } from 'vue'

export default {
    setup() {
        const first = ref(10)
        const after = ref(null)

        // Query with reactive variables
        const { result, loading, error, refetch, fetchMore } = useQuery(
            GET_USERS,
            () => ({
                first: first.value,
                after: after.value
            }),
            {
                errorPolicy: 'all',
                fetchPolicy: 'cache-and-network'
            }
        )

        // Computed users from query result
        const users = computed(() =>
            result.value?.users?.edges?.map(edge => edge.node) ?? []
        )

        const pageInfo = computed(() =>
            result.value?.users?.pageInfo
        )

        // Mutation for creating posts
        const { mutate: createPost, loading: createPostLoading } = useMutation(
            CREATE_POST,
            {
                update(cache, { data: { createPost } }) {
                    // Update cache after mutation
                    const query = {
                        query: GET_USERS,
                        variables: { first: first.value, after: after.value }
                    }

                    const data = cache.readQuery(query)
                    if (data?.users?.edges) {
                        const authorEdge = data.users.edges.find(
                            edge => edge.node.id === createPost.author.id
                        )
                        if (authorEdge) {
                            authorEdge.node.posts.push(createPost)
                            cache.writeQuery({ ...query, data })
                        }
                    }
                }
            }
        )

        // Load more users (pagination)
        const loadMore = async () => {
            if (pageInfo.value?.hasNextPage) {
                await fetchMore({
                    variables: {
                        after: pageInfo.value.endCursor
                    }
                })
            }
        }

        // Create new post with optimistic response
        const handleCreatePost = async (postData) => {
            try {
                await createPost({
                    input: postData
                }, {
                    optimisticResponse: {
                        createPost: {
                            __typename: 'Post',
                            id: 'temp-id',
                            title: postData.title,
                            content: postData.content,
                            author: {
                                __typename: 'User',
                                id: postData.authorId,
                                name: 'Current User'
                            },
                            createdAt: new Date().toISOString()
                        }
                    }
                })
            } catch (err) {
                console.error('Failed to create post:', err)
            }
        }

        return {
            users,
            loading,
            error,
            pageInfo,
            createPostLoading,
            loadMore,
            handleCreatePost,
            refetch
        }
    }
}

This code demonstrates comprehensive Apollo Client integration with Vue using the official Apollo Vue composition functions for reactive queries, mutations with cache updates, and pagination support. Apollo Client provides intelligent caching with automatic UI updates, optimistic responses for immediate feedback, and sophisticated cache management through update functions. The integration leverages Vue’s reactivity system for seamless data binding while maintaining Apollo’s powerful GraphQL features.

Best Practice Note:

This is the Apollo Client architecture we implement in CoreUI enterprise applications for robust GraphQL data management with advanced caching strategies. Configure cache policies appropriately for your data patterns and implement error boundaries for comprehensive error handling in production applications.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
What Does javascript:void(0) Mean?
What Does javascript:void(0) Mean?

How to Add a Tab in HTML
How to Add a Tab in HTML

How to remove a property from an object in Javascript
How to remove a property from an object in Javascript

How to Use Bootstrap Modal in Vue 3 – Clean Integration with CoreUI
How to Use Bootstrap Modal in Vue 3 – Clean Integration with CoreUI

Answers by CoreUI Core Team