Home Blog Vue 3 External Store
Using an external store in Vue 3 Published Jan 26, 2023
⋅
Updated Dec 15, 2024
⋅
1 minutes read
In this article, we will see how to use an external store in Vue 3 using the composition API. Also, will use the publish-subscribe pattern to achieve this.
I'm not a Vue wizard, so if you see something wrong, please let me know .
As I said in the Implement the publish-subscribe pattern in TypeScript article , I'm working on a refector of a personal project. To manage the state, I've decided to use the publish-subscribe pattern.
The store
export type ISubscribe < T > = {
getState : () => T ;
setState : ( value : Partial < T >) => void ;
subscribe : ( callback : () => void ) => () => void ;
};
export const subscriber = < T >( initialValue : T ) : ISubscribe < T > => {
const listeners = new Set <() => void >();
let value = initialValue;
const getState = () => value;
const setState = ( newValue : Partial < T >) => {
value = { ... value, ... newValue };
listeners. forEach (( listener ) => listener ());
};
const subscribe = ( callback : () => void ) => {
listeners. add (callback);
// Return a function to unsubscribe.
return () => listeners. delete (callback);
};
return {
getState,
setState,
subscribe,
};
};
The Vue 3 hook
import { shallowRef, watch, onUnmounted } from "vue" ;
import { subscriber } from "./subscriber" ;
const initialState = {
steps: [],
currentStep: 0 ,
};
export const useSubscriber = () => {
const subs = subscriber (initialState);
// Create a shallowRef to store the state.
const state = shallowRef (subs. getState ());
// Function to update our state.
const updater = ( state ) => {
subs. setState (state);
};
// Subscribe to the store and update the state.
const unsubscribe = subs. subscribe (() => {
state.value = subs. getState ();
});
// I don't know if this is necessary.
onUnmounted (() => {
unsubscribe ();
});
return [state, updater];
};
The component
< script setup >
import { useSubscriber } from "./useSubscriber" ;
const [ steppers , updater ] = useSubscriber ();
function nextStep () {
const currentStep = steppers.value.currentStep;
updater ({ currentStep: currentStep + 1 });
}
</ script >
< template >
< p >current step : {{ steppers.currentStep }} </ p >
< button @click = "nextStep" > next step </ button >
</ template >
Here an example on Vue playground
References