Search code examples
vuejs3vue-composition-api

How to use a store initial value in a template Vue 3


I haven't worked with Vue for a while and now I am struggling with something that seems simple. I have a store where I plan to keep a state for the whole app. Currently I only have one boolean property snap with which I control move and resize of divs on a grid.

The code for the abstract and actual store:

import { reactive, readonly } from 'vue';

export abstract class Store<T extends Object> {

    protected state: T;

    constructor(data: T) {
        this.state = reactive(data) as T;
    }

    public getState(): T {
        return readonly(this.state) as T;
    }

}

import { Store } from "./Store";

interface AppState extends Object {
    snap: boolean;
}

class AppStore extends Store<AppState> {

    constructor() {
        super({
            snap: true,
        });
    }

    public setSnap(snap: boolean) {
        this.state.snap = snap;
    }

}

export const appStore: AppStore = new AppStore();

In my root component I have a computed value so it can be used in the template:

const snap = computed({
    get() {
        appStore.getState().snap;
    },
    set(newValue: boolean) {
        appStore.setSnap(newValue);
    }
});

And in the template I have a simple checkbox:
<label for="snap">Snap to grid <input type="checkbox" id="snap" v-model="snap"></label>

This works once I use it, but I set it to true in the store, but when I load the app the checkbox is not checked. What am I missing?

Edit:
I now added additional fields, but they have the same problem.

Example Code (though I get a weird error in the console): play.vuejs.org

Even more simplified (you can see the state value is true but only once you check and uncheck the checkbox the value is in sync): play.vuejs.org


Solution

  • I reproduced the situation in my machine. It seems like you forgot to add a return word in App.vue :). It works well and the checkbox is checked at first time

    const snap = computed({
     get() {
        **return** appStore.getState().snap;
     },
     set(newValue: boolean) {
        appStore.setSnap(newValue);
     }