I am using Pinia for stores in my Vue3 app with Typescript. I want to manage the current week that is being displayed. The problem arises when I try to access the weekDisplay variable from the store. It does not update its value when currentDate is modified, even though it is wrapped inside computed(). The changeDisplay() function is called from the PageHeader component, when certain buttons are pressed.
Note that currentDate is updated properly both inside the store and the component.
This is src/stores/Activities.ts:
import { defineStore } from "pinia";
import { computed, ref } from "vue";
import { weekName } from "@/main";
... /* Types, enums etc. */
export const useActivitiesStore = defineStore("activities", () => {
const eventsMap = ref<Map<string, Activity[]>>(new Map());
const currentDate = ref<Date>(new Date());
const weekDisplay = computed(() => weekName(currentDate.value));
function changeDisplay(change: number): void {
currentDate.value.setDate(currentDate.value.getDate() + 7 * change);
}
return { eventsMap, currentDate, weekDisplay, changeDisplay };
});
This is src/components/PageHeader.vue:
<script setup lang="ts">
... /* Other imports */
import { useActivitiesStore } from "@/stores/Activities";
import { storeToRefs } from "pinia";
import { computed } from "vue";
let store = useActivitiesStore();
const { eventsMap, currentDate, weekDisplay } = storeToRefs(store);
</script>
<template>
<header id="header">
...
<section id="week-navigation-container" class="week-navigation">
<article
id="previous-week-button"
class="week-button"
@click="store.changeDisplay(-1)">
<IconLeftArrow class="left-arrow" />
<Tooltip text="Previous week" />
</article>
<article id="open-calendar-button" class="week-display">
<h1 class="font-menu-title">
{{ weekDisplay }}
</h1>
<Tooltip text="Open calendar" />
</article>
<article
id="next-week-button"
class="week-button"
@click="store.changeDisplay(1)">
<IconRightArrow class="right-arrow" />
<Tooltip text="Next week" />
</article>
</section>
</header>
</template>
This is src/main.ts:
import "./assets/main.css";
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";
const pinia = createPinia();
const app = createApp(App);
app.use(router);
app.use(pinia);
app.mount("#app");
export function datesArr(date: Date) {
...
}
export function weekName(date: Date): string {
...
}
export function dayToTop(day: number) {
...
}
export function timeToLeft(hour: number, minute: number, second: number) {
...
}
export function timeToWidth(hour: number, minute: number) {
...
}
The text inside the h1 element with the .font-menu-title class should update when the buttons are pressed to display the relevant information. (The exact value would be the result of weekName(currentDate), which should always be stored in the weekDisplay variable).
Updating the date with
setDateis an inplace replacement which Vue reactivity can't detect. It's not ideal looking code but you can alter the line to include an assignment and guarantee the reactivity response is triggered: