Vuex is a great state management library. It is simple and integrates well with Vue. Why would anyone leave Vuex? The reason may be that the upcoming Vue 3 release exposes the underlying reactive system and introduces new ways of building applications. The new response system is very powerful and can be used for centralized state management.

Do you need to share state?

In some cases, the flow of data between multiple components is so difficult that you need centralized state management. These include:

Deep nesting of multiple root components that use the same data and have data access if none of the above is true, the answer is simple whether you need it or not. A: no, no

But what if you have one of the following? The most straightforward answer is to use Vuex. It’s a tried and tested solution, and it works well.

But what if you don’t want to add additional dependencies or find the Settings too complex? The new Vue 3 version and Composition API address these issues with built-in methods.

New solutions

The shared state must meet two conditions:

Reactivity: As states change, the components that use them should also update their availability: State reactivity can be accessed from any component. Vue 3 exposes its reactive system through a number of features. You can use reactive functions to create reaction variables (the ref function is the alternative).

import { reactive } from 'vue';



export const state = reactive({ counter0 });

Copy the code

Proxy objects returned from reactive functions are objects that can track changes in their properties. When used in a component template, the component rerenders itself whenever the reactive power value changes.

<template>

  <div>{{ state.counter }}</div>

  <button type="button" @click="state.counter++">Increment</button>

</template>



<script>

  import { reactive } from 'vue';



  export default {

    setup() {

      const state = reactive({ counter0 });

      return { state };

    }

  };

</script>


Copy the code

availability

The example above is useful for individual components, but other components cannot access state. To overcome this problem, you can use the provide and Inject methods to provide any available values in your Vue 3 application.

import { reactive, provide, inject } from 'vue';



export const stateSymbol = Symbol('state');

export const createState = (a)= > reactive({ counter0 });



export const useState = (a)= > inject(stateSymbol);

export const provideState = (a)= > provide(

  stateSymbol, 

  createState()

);

Copy the code

When you pass the Symbolas key and a value to the provide method, any child component in the method can use that value Inject. Symbol provides and retrieves values using the same name for the key.


This way, if you provide a value on the topmost component, it will be available in all components. Alternatively, you can call provide the main application instance.

import { createApp, reactive } from 'vue';

import App from './App.vue';

import { stateSymbol, createState } from './store';



const app = createApp(App);

app.provide(stateSymbol, createState());

app.mount('#app');

Copy the code
<script>

  import { useState } from './state';



  export default {

    setup() {

      return { state: useState() };

    }

  };

</script>

Copy the code

To make it strong

The above solution works, but there is a drawback: you don’t know who modified what. The status can be changed directly without limitation.

You can protect the state by wrapping it with the readonly function. It overrides the passed variables in objects that Proxy prevents from changing (warning when trying). Mutations can be handled through separate features that have access to writable storage.

import { reactive, readonly } from 'vue';



export const createStore = (a)= > {

  const state = reactive({ counter0 });

  const increment = (a)= > state.counter++;



  return { increment, state: readonly(state) };

}

Copy the code

The outside world will only be able to access read-only states, and only exported functions will be able to modify writable states.

The new solution is relatively close to Vuex by protecting the state from unnecessary modification.

Abstract

By using Vue 3’s reactive system and dependency injection mechanism, we have moved from local state to centralized state management that can replace Vuex in smaller applications.

We have a state object that is read-only and responds to changes to the template. State can only be modified by specific methods such as actions/mutations in Vuex. You can define additional fetchers using computed functions.

Vuex has more features, such as module handling, but sometimes we don’t need them.

If you want to learn about Vue 3 and try this state management approach, check out my Vue 3 playground.