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.
How to declare the optional function parameters in JavaScript?
How to declare the optional function parameters in JavaScript?

How to loop through a 2D array in JavaScript
How to loop through a 2D array in JavaScript

How to Merge Objects in JavaScript
How to Merge Objects in JavaScript

How to loop through an array in JavaScript
How to loop through an array in JavaScript

Answers by CoreUI Core Team