VueJS

State Management with Apollo Client and Vue using Reactive Variable

Jerry Hogan
3 min read
State Management with Apollo Client and Vue using Reactive Variable
This article was written over 18 months ago and may contain information that is out of date. Some content may still be relevant, but please refer to official documentation for the latest information.

State Management is an integral part of Software development with tools like VueX, Pinia which is like VueX 5, Redux, Context API, and others.

In our example, we will be using Vue3 composition API, a bit of TypeScript.

This article will assume that you already have a project setup with Apollo.

State Managemnet

Before we dive into what state management is and what it offers, lets understand few thing which are integral to it.

What is State?

State is a part of an application, such as user details, usernames, login information, and website themes(dark or light).

In simple terms, state is like a warehouse that's contents you can access when you need to from wherever you are.

What is State Management?

State Management is just simply a design pattern to help synchronize the state of the application throughout all of the components in the application. This also prevents us from passing too many props accross the application.

When to implement State Management:

  • When the application contains large number of components.
  • To prevent redundant data, knowing well some other components might need that data.
  • Prevent passing props across the application, making it messy.

For more explainations, you can check the links below:

How to implement State management?

There are so many ways to do it. But in this discussion, we will be implementing it with Vue Apollo.

Apollo Client

It is the client for Vue Apollo. It helps to easily integrate GraphQL queries and mutation in your application which, in our case, is Vue.

Reactive Variables

This is a new feature from Apollo Client 3.

Reactive variables are a useful mechanism for representing local state outside of the Apollo Client cache.

How to create a Reactive variable in Apollo?

This is quite simple since Apollo client provides us with makeVar.


import { makeVar } from '@apollo/client';

const counts = makeVar(0);
console.log(counts());
// Output: 0

/* Update the value of counts */
counts(1);
console.log(counts());
// Output: 1

const cartItemsVar = makeVar([]);
console.log(cartItemsVar());
// Output: []

/* Update the value of cartItemsVar */
cartItemsVar(['Vue', 'Apollo', 'State Management']);
console.log(cartItemsVar());
// Output: ['Vue', 'Apollo', 'State Management']

const isLoggedIn = makeVar(false);
console.log(isLoggedIn());
//  Output: false

/* Update the value of isLoggedIn */
isLoggedIn(true);
console.log(isLoggedIn());
// Output: true

What the above code means is we make use of makeVar to create a variable of any type be it boolean, number, array, or object. Also, by calling the variable that makeVar is assigned to without passing a parameter will only output its current value, but passing a parameter will update its value.

You can learn more about makeVar here.

Setup of the Project

We will be creating a state for a counter that does increment, decrement, or reset. But first, let's set up our enviroment.

Setting up the Reactive variable

Lets create our reactive variable in ./variables/counts.js:


import { makeVar } from '@apollo/client';

export const counts = makeVar(0);

Configuring the cache

Lets also update our cache config to something like this:


// Need to import the variable we reated
import { counts } from '../variables/counts';

// Cache implementation
const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        count: { //The name we will be querying
          read() {
            return counts(); //Returns the updated value of counts
          },
        },
      },
    },
  },
});

Creating a component

Let's create ./components/Counter.vue component:


<template>
  <div>
    <div class="col-3">
      <h6>
        Count: <span v-if="!loading">{{ count }}</span>
      </h6>
    </div>
    <div class="col-3">
      <button @click="increment">Increment</button>
    </div>
    <div class="col-3">
        <button @click="decrement">Decrement</button>
    </div> 
    <div class="col-3">
      <button @click="reset">Reset</button>
    </div>

  </div>
</template>

<script lang="ts">
import { computed, defineComponent } from 'vue';

export default defineComponent({
  name: 'NumberCounter',
});
</script>

<script lang="ts" setup>
import { counts } from 'src/variables/counts';
import { useQuery } from '@vue/apollo-composable';
import gql from 'graphql-tag';

// This is to fetch the count value using the query
const COUNTERS_QUERY = gql`
  query Counter {
    count @client
  }
`;

const { result, loading } = useQuery(COUNTERS_QUERY);

const count = computed(() => (result.value ? result.value.count : 0));

const increment = () => {
  let cnts = counts();
  cnts++;
  counts(cnts);
};

const decrement = () => {
  let cnts = counts();
  cnts--;
  counts(cnts);
};

const reset = () => {
  cnts= 0;
  counts(cnts);
};

</script>

Please note that you can always get the counts value even without the GraphQL query. All you need to do is call count() like the example about Reactive variables, and force a re-render using loading as a ref.

Like this:


 <template>
  <div>
    <div class="col-3">
      <h6>
        Count: <span v-if="!loading">{{ counts() }}</span>
      </h6>
    </div>
    <div class="col-3">
      <button @click="increment">Increment</button>
    </div>
    <div class="col-3">
        <button @click="decrement">Decrement</button>
    </div> 
    <div class="col-3">
      <button @click="reset">Reset</button>
    </div>

  </div>
</template>

<script lang="ts">
import { ref, defineComponent } from 'vue';

export default defineComponent({
  name: 'NumberCounter',
});
</script>

<script lang="ts" setup>
import { counts } from 'src/variables/counts';
// loading ref to help re-render when there is a change so as to get the latest value of counts.
const loading = ref(false);

const increment = () => {
  let cnts = counts();
  loading.value = true;
  cnts++;
  counts(cnts);
  loading.value = false;
};

const decrement = () => {
  let cnts = counts();
  loading.value = true;
  cnts--;
  counts(cnts);
  loading.value = false;
};

const reset = () => {
  cnts = 0;
  loading.value = true;
  counts(cnts);
  loading.value = false;
};

</script>

loading ref to help re-render when there is a change so as to get the latest value of counts.

The manner you will prefer depends on what you want to achieve. But I will go with the example with the query as it still preserves the GraphQL feel.

Conclusion

State Management with Apollo Client saves you the stress of installing VueX, or Redux (for the React users), as long as the application makes use of Apollo. In this quick training, we learned about state and why state management is important to building and maintaining applications.

Further, we learned how to manage state by using a reactive variable in Apollo. If you need any help understanding how to use this training, or additional clarification, please feel free to reach out to me.

About the author

Jerry Hogan

Jerry Hogan

Software Engineer

Passionate developer, super fan of Vue, a singer, writer and musician.

Keep reading

View all posts →

Awesome 3D experience with VueJS and TresJS: a beginner's guide

Unleash the power of 3D in your Vue.js projects with Tres.js! The future of immersive web experiences is here. #Vuejs #3Ddevelopment...

Mattia Magi5 mins
Vue3D

3 VueJS Component Libraries Perfect for Beginners

For developers checking out VueJS for the first time, the initial steps are overwhelming, particularly when setting up projects from square one. But don’t worry! The VueJS ecosystem offers a plethora of remarkable component libraries, easing this early obstacle. These three libraries are pre built toolkits, providing beginners with the means to kickstart their VueJS projects effortlessly. Let’s take a look! Quasar Quasar is among the most popular open source component libraries for Vue.js, offering a comprehensive set of ready to use UI components and tools for building responsive web applications and websites. Designed with performance, flexibility, and ease of use in mind, Quasar provides developers with a wide range of customizable components, such as buttons, forms, dialogs, and layouts, along with built in support for themes, internationalization, and accessibility. With its extensive documentation, active community support, and seamless integration with Vue CLI and Vuex, Quasar empowers developers to rapidly prototype and develop high quality Vue.js applications for various platforms, including desktop, mobile, and PWA (Progressive Web Apps). PrimeVue PrimeVue is a popular Vue.js component library offering a wide range of customizable UI components designed for modern web applications. Developed by PrimeTek, it follows Material Design guidelines, ensuring responsiveness and accessibility across devices. With features like theming, internationalization, and advanced functionalities such as lazy loading and drag and drop, PrimeVue provides developers with the tools to create elegant and high performing Vue.js applications efficiently. Supported by clear documentation, demos, and an active community, PrimeVue is an excellent choice for developers seeking to streamline their development process and deliver polished user experiences. Vuetify Vuetify is a powerful Vue.js component library that empowers developers to create elegant and responsive user interfaces with ease. Built according to Google's Material Design guidelines, Vuetify offers a vast collection of customizable UI components, ranging from buttons and cards to navigation bars and data tables. Its comprehensive set of features includes themes, typography, layout grids, and advanced components like dialogues and sliders, enabling developers to quickly build modern web applications that look and feel polished. With extensive documentation, active community support, and ongoing development, Vuetify remains a top choice for Vue.js developers seeking to streamline their workflow and deliver visually stunning user experiences. For newcomers venturing into Vue.js, the initial setup might seem daunting. Thankfully, Vue.js offers a variety of component libraries to simplify this process. Quasar, PrimeVue, and Vuetify are standout options, each providing pre built tools to kickstart projects smoothly. Whether you prefer Quasar's extensive UI components, PrimeVue's Material Design inspired features, or Vuetify's responsive interfaces, these libraries cater to diverse preferences and project requirements. With their clear documentation and active communities, these libraries empower developers to start Vue.js projects confidently and efficiently, enabling Vue developers to create polished user experiences....

2 mins
VuetifyVueQuasar

Understanding Vue.js's <Suspense> and Async Components

In this blog post, we will delve into how <Suspense> and async components work, their benefits, and practical implementation strategies to make your Vue.js applications more efficient and user-friendly...

Jesús Padrón6 mins
VueWeb PerformanceUXJavaScript

Getting started with Vitepress

Create your static blog site using Vitepress. Setup and configure your site in minutes by following this step-by-step tutorial....

Simone Cuomo12 mins
VueViteVitepress