The Vue component fails to refresh after modifications to the state in the Pinia store

I'm currently immersed in my inaugural vue application, focusing on constructing the login functionalities. To handle State management, I've implemented pinia. I've set up a Pinia Store to globally manage the "isLoggedIn" state.

import { defineStore } from "pinia";

export const useLoginStatusStore = defineStore('loginStatus', {
    id: 'loginStatus',
    state: () => ({
        isLoggedIn: false
    }),
    actions: {
        logIn() {
            this.isLoggedIn = true
            console.log("Login", this.isLoggedIn)
        },
        logOut() {
            this.isLoggedIn = false
            console.log("Logout", this.isLoggedIn)
        }
    }
})

Everything seems to be functioning smoothly so far; I'm able to access the state and actions in both components and the router file.

**<roouter.js>**

import { createRouter, createWebHistory } from 'vue-router'
import { createPinia } from 'pinia'
import { createApp, ref } from 'vue'
import { useLoginStatusStore } from '../stores/loginStatus.js'

import App from '../App.vue'
import WelcomeView from '../views/public/WelcomeView.vue'
import SplashView from '../views/public/SplashView.vue'

const pinia = createPinia()
const app = createApp(App)
app.use(pinia)

const loginStatusStore = useLoginStatusStore()
let isLoggedIn = ref(loginStatusStore.isLoggedIn)

console.log("isLoggedIn", loginStatusStore.isLoggedIn)


const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    ... // List of routes omitted for brevity
  ]
})

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth) {
    console.log("Router", isLoggedIn.value)
    if (!isLoggedIn.value) {
      next({
        name: 'welcome'
      })
    } else {
      next()
    }
  } else{
    next()
  }
})

export default router

The state updating issue arises when the state changes do not reflect in the components, and the components themselves fail to update. I attempted using the $subscribe method in pinia without success. It's evident that reactivity is essential here, but I'm unsure how to implement it. Any assistance on resolving this would be greatly appreciated :)

Thank you for taking the time to address this concern.

**App.vue**

<script setup>
import { RouterView } from 'vue-router';
import DevNavItem from '@/components/header/DevNavItem.vue'
import HeaderItem from '@/components/header/HeaderItem.vue'
import FooterItem from '@/components/footer/FooterItem.vue'
import { useLoginStatusStore } from './stores/loginStatus.js';

const loginStatusStore = useLoginStatusStore()
const isLoggedIn = loginStatusStore.isLoggedIn

console.log("App.vue", loginStatusStore.isLoggedIn)

</script>

<template>
  <DevNavItem />
  <HeaderItem v-if="isLoggedIn" />
  <RouterView :class="isLoggedIn ? 'mainProtected' : 'mainPublic'" />
  <FooterItem v-if="isLoggedIn" />
</template>

<style>
/* CSS styles omitted for brevity */
</style>

I tried utilizing $subscribe for state subscription, however, encountered obstacles along the way.

Answer №1

Utilizing storeToRefs()

To maintain reactivity while extracting properties from the store, it is essential to employ storeToRefs().

import { storeToRefs } from 'pinia'
const themeStore = useThemeStore();
const { isDark } = storeToRefs(themeStore);

Using Computed Property

Credit goes to @Fennec for suggesting the utilization of computed to access reactive state. However, I advocate for utilizing the specific storeToRefs() method.

import { computed } from 'vue'
const themeStore = useThemeStore();
const isDark = computed(() => themeStore.isDark);

Incorrect Approaches for Retrieving Reactive State from Pinia Store:

The following methods of obtaining the state (properties, getters) from the Pinia store are considered INCORRECT:

import { useThemeStore } from "./stores/theme.js";
const themeStore = useThemeStore();

// Incorrect ways of accessing state from store
let isDark = themeStore.isDark; // not reactive
let isDark = ref(themeStore.isDark); // reactive but won't update with store
let { isDark } = themeStore; // not reactive, cannot destructure

Directly Destructuring actions from the Store

It is important to highlight that "you can destructure actions directly from the store as they are bound to the store itself." (docs)

If there is an action named "increment" in your store, you can effortlessly extract it directly from the store within your component:

...
const { increment } = store // actions can be destructured directly
...

Additionally, in accordance with Pinia documentation, the first argument represents the unique ID, eliminating the need to redefine the id within the options object. You may choose to ignore the first argument and solely specify the id as an option, both approaches are acceptable.

Answer №2

An effective approach involves incorporating a custom method within the store to retrieve the target state.

function fetchTargetState() {
 return targetState;
}

This methodology maintains reactivity without relying on storeToRefs.

Answer №3

                                    PiniaVuePlugin

Make sure to include the PiniaVuePlugin and utilize it in your main.js file:

import { createPinia, PiniaVuePlugin } from 'pinia'

Vue.use(PiniaVuePlugin)
const pinia = createPinia();

new Vue({
render: (h) => h(App),
pinia,
}).$mount("#app");

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can we export data to excel using react-export-excel while ensuring certain columns are hidden?

Greetings! I believe the title gives you a clear idea of my dilemma. When exporting data, there are no errors - my goal is to hide the Excel column when the checkbox is unchecked or false, and display it when the checkbox is checked or true during export. ...

MongoDB: Issue updating the 'role' field of a document

Recently, I've run into an issue where I am unable to update the 'role' of a specific document. The document in question is a 'user' object within the MEANjs User schema, and it has a pre-defined property for roles. Here is the sec ...

The variable is unable to be accessed within the PHP function query

After passing a variable through ajax to a function within my php file "Cart_code.php", I encountered an issue where the variable was not accessible inside the function. Can you help me figure out why? Javascript $.ajax({ type: "POST", url: "incl ...

Display Vue components in VuePress

Is there a way to showcase personalized Vue.js elements like a <b-button> on a VuePress markdown page? Can this be achieved? ...

Encountering a type mismatch error in Typescript while working with Redux state in a store file

It appears that I have correctly identified all the types, but could there be a different type of Reducer missing? 'IinitialAssetsState' is not assignable to type 'Reducer' The complete error message: Type '(state: { assets: n ...

Setting session expiration for an HTML page in MVC with JavaScript - A step-by-step guide

I'm working on a HTML page within an MVC framework that includes a button click function. I'm trying to figure out how to redirect the user to the login page if the page remains idle for 30 minutes. I've attempted using the code snippet belo ...

Unable to display the string following a space in the value attribute of an hbs file

<input type="text" class="form-control" id="exampleInputEmail2" name="productName" value={{product.productName}} > When I input 'Smart Phones' into product.produc ...

The color of the progress bar in JS is not displaying properly

My work involves using jQuery to manipulate progress bars. The issue I am facing is defining standard colors that should be displayed on the progress bar based on the value received. Here is my code: var defaultSegmentColors = ['#FF6363', &ap ...

What is the proper way to address the issue of nesting ternary expressions when it comes to conditionally rendering components?

When using the code below, eslint detects errors: {authModal.mode === 'login' ? <Login /> : authModal.mode === 'register' ? <SignUp /> : <ForgotPassword />} Error: Avoid nesting ternary expressions. eslint(no-nested-t ...

Is it possible to initiate an animation in a child component using an input variable?

I have a specific animation that I would like to trigger once an *ngFor loop completes ngAfterViewInit(): void { this.items.changes.subscribe(() =>{ Promise.resolve().then(() => { this.everythingLoaded(); }) }) } After the loop fini ...

When attempting to execute a promise within a test, encountering a 400 error in a NodeJS environment

I recently started using Contentful, a new JavaScript library for creating static websites. My goal is to incorporate it into my Node.js project. To achieve this, I developed an app file called getContent.js: 'use strict'; var contentful = req ...

Leveraging the power of the 'var' keyword in JavaScript when

I have a javascript code snippet that looks like this: var grade_type = document.getElementById("grade_type").value; gradesRef.set({ grade_type: firebase.firestore.FieldValue.arrayUnion(grade) }); However, when the data is stored i ...

Utilize moment.js to insert a gap between the date and time

Trying to improve the readability of my datetimes retrieved from the database in ISO format (e.g. 2015-11-03T10:06:50.000Z) using moment.js. After parsing, I get a more readable format like 11-03-2015 10:06:50 AM. But now, I want to have an additional spac ...

Instructions for creating a po file from a js file using poedit

Utilizing the Gettext.js library for localizing content created from a JS file has been my approach. The current challenge lies in the manual creation and writing of each po file. It is known that php files can be scanned for gettext strings using PoEdit ...

Despite element being a grandchild, the function this.wrapperRef.current.contains(element) will return false

The issue arises when using the EditModal component with an onClickOutside event. This component includes a child element, a Material-UI Select, where clicking on a MenuItem triggers the onClickOutside event, causing the modal to close without selecting th ...

Encountering a "Element is not defined" error in Nuxt when trying to render Editor.js and receiving

I've been working on creating an editor using Editor.js within my Nuxt project, but it seems like the editor isn't initializing properly when I render the page. import EditorJS from '@editorjs/editorjs'; interface IEditor { editor: E ...

Error: An uncaught exception occurred when trying to access a seekable HTML5 audio element, resulting in an IndexSize

While trying to utilize the HTML5 API along with SoundManager2, I encountered an issue. My goal was to determine the duration of a song in order to create a progress bar that would update as the song played. However, every time I attempted to retrieve the ...

Is it possible to automatically access the most recent Beta build through package.json and npm?

We are currently working on a project that has a specific dependency requirement for the latest beta build from an npm library. However, there are also -dev builds within the library. For instance, in the "x-library" there might be versions like: "1.2.3- ...

In React-router-dom version 5, match.params.id functions properly, but it experiences issues in version 6

Can anyone help me figure out the proper way to achieve this functionality in react-router version 6? When I use console.log with match, it returns undefined, even though it works fine in v5. import React from 'react' const NotePage = ({ match } ...

The python-pyinstrument is in need of a javascript dependency that seems to

As I attempt to profile my Python program using pyinstrument, I encounter an error when trying to view the profile in HTML format. Traceback (most recent call last): File "/home/ananda/projects/product_pred/025200812_cpall_ai_ordering_model_v2/.venv ...