Retrieving data from Vuex store module within router.ts

I recently utilized a tutorial found here to establish a Vuex store with modules using TypeScript.

Here's what I have accomplished so far:

vuex/types.ts:

export interface RootState {
    version: string;
}

vuex/user-profile.ts:

import { ActionTree, Module, MutationTree } from 'vuex';
import { RootState } from './types';

interface User {
    firstName: string;
    uid: string;
}

interface ProfileState {
    user?: User;
    authed: boolean;
}

const state: ProfileState = {
    user: undefined,
    authed: false,
};

const namespaced: boolean = true;

export const UserProfile: Module<ProfileState, RootState> = {
    namespaced,
    state,
};

store.ts:

import Vue from 'vue';
import Vuex, { StoreOptions } from 'vuex';
import { UserProfile } from '@/vuex/user-profile';
import { RootState } from '@/vuex/types';

Vue.use(Vuex);

const store: StoreOptions<RootState> = {
  state: {
      version: '1.0.0',
  },
  modules: {
      UserProfile,
  },
};

export default new Vuex.Store<RootState>(store);

In my router.ts, I intended to access the authed state of the store in this manner:

import store from './store';
//...other imports...

const router = new Router({
//... route definitions...
});

router.beforeEach((to, from, next) => {
  const isAuthed = store.state.UserProfile.authed;
  if (to.name !== 'login' && !isAuthed) {
    next({ name: 'login' });
  } else {
    next();
  }
});

The code functions correctly (the app redirects as expected), HOWEVER, I am encountering compiler errors stating that

Property 'UserProfile' does not exist on type 'RootState'
. This error seems logical since it's not defined explicitly, but shouldn't it search within the modules too, or did I define the module improperly?

Answer №1

To ensure proper definition of all stores in the RootState interface, follow this format:

export default interface RootState {
  version: string,
  UserProfile: any
}

You can also import the interface from the UserProfile and use it instead of using 'any'. This approach is recommended especially if your file naming convention does not follow pascal casing.

This setup instructs rootState to anticipate a vuex store named UserProfile with either any type or UserProfile interface.

In my case, the rootstate interface for vuex store looks like this:

export default interface RootState {
  version: string,
  config: any,
  cart: any,
  checkout: any,
  cms: any,
  product: any,
  shipping: any,
  user: any,
  wishlist: any,
  attribute: any,
  ui: any,
  newsletter: any,
  category: {
    current_path: string,
    current_product_query: any,
    current: {
      slug: string,
      name: string
    },
    filters: any
  }
}

Answer №2

UPDATE: The issue appears to stem from direct access to the state. Line

const isAuthenticated = store.state.UserProfile.authed;

My belief is that this is happening due to it being namespaced. To solve this, consider creating a getter.

const getters: GetterTree<ProfileState, RootState> = {

    user(state): User {
        return state.user
    }

};

You can then access it like

store.getters['UserProfile/user']

Furthermore, I recommend using getters when accessing your state data. Check out Getters for more information.

Answer №3

1

     const isLoggedIn = store.state["UserProfile"].authed; // false

2

    const currentState:any|State = store.state
    const isLoggedIn = currentState.UserProfile.authed; // false

3

    const isLoggedIn = (<any|State>store.state).UserProfile.authed; // false

Answer №4

Here is a functional solution with dependencies

"vuex": "^4.0.2"
,
"vue-router": "^4.0.10"
and
"vue": "^3.1.4"
.

To access your state in the module, import the store into your router file:

import store from "@/store/store";

In this example, I have a module named authModule where I can retrieve the token stored as a JWT:

let loggedIn = store.state.authModule.token;

Answer №5

To achieve the desired result, I suggest using a double cast method. One for general access and one specifically for accessing your intended data. It's important to note that in the code snippet from the last router.ts file, the variable "store" represents an instance of the Store, while the other imports are simply type definitions.

For the sake of brevity, I have omitted the detailed code related to namespaced, state, getters, actions, and mutations as they are essentially object structures.

Within store/myModule/types.ts:

export default interface State {
    testValue
}

In store/myModule/index.ts:

import RootState from '../types'

const module: Module<State, RootState> = {
    namespaced,
    state,
    getters,
    actions,
    mutations,
}

export default module

Defined in store/types.ts:

interface RootState {
  myOtherTestValue: string
}

export default RootState
export { RootState }

Inside store/index.ts:

import RootState from './types'
import myModule from './myModule'

export const cmStore: StoreOptions<RootState> = {
    actions,
    mutations,
    state,
    modules: {
        myModule,
    },
    plugins,

}

export default new Vuex.Store<RootState>(cmStore)

Implemented in router.ts:

import store from './store'
import RootState from './store/types'
import MyModuleState from './store/myModule/types'

// To properly access the desired data:
const myState = ((store.state as any).myModule as MyModuleState)

console.log(myState.testValue)

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

Leverage asyncData method in your NuxtJS layout or component

Is there a way to incorporate asyncData into a layout or component even though it seems to be forbidden? The reason I'm asking is because my sidebar component is used in the default layout, and I want to utilize asyncData to display data fetched from ...

Sending the response data from an API call to a Vue object

In the vue block below, I have successfully pushed my response data into the dateEvents return. Additionally, I am rendering events for a calendar package I am using. My goal is to map my response data to the events object where the name becomes the event ...

What is the method for retrieving data from the root component within a child template in VueJs?

How can I access this.$root from within a VueJs template? For example: <template> <v-card elevation="this.$root.$refs.foo.cardElevation"> Foo </v-card> </template> I am aware that I can create a data property and ...

Mastering universal code creation with the composition API in Quasar

The Quasar website explains that for writing universal code, the created and beforeCreate lifecycle hooks in Vue components are executed in Server Side Rendering (SSR). This raises a question: What about setup? How can I achieve SSR functionality with th ...

How can I create an inline form in Vue using Element UI with a select dropdown and submit button?

I am currently utilizing the Element library in vue () and I am looking to create a basic form with a select box and a submit button. However, I am unable to find any instructions on how to achieve this on the website. What I want is a format similar to t ...

Using requestAnimationFrame and event listeners for keyup and keydown events in TypeScript

Having trouble getting requestAnimationFrame to work with event listeners keyup/down in a TypeScript class? It works fine outside the class. Can you help me figure out why it won't work inside a class? class GameEngine { private aKey:boolean ...

When faced with the error message "Typescript property does not exist on union type" it becomes difficult to assess the variable

This question is a continuation of the previous discussion on Typescript property does not exist on union type. One solution suggested was to utilize the in operator to evaluate objects within the union. Here's an example: type Obj1 = { message: stri ...

The VueJS dynamic grid view

Currently, I am working on a project in VueJS using vue cli 3. I am facing an issue with implementing MasonryJS into my Vue project. The challenge lies in grasping how to integrate this masonry layout into my Vue application. ; (function(window) { // J ...

Check to see if the event handler is triggered and the promises are executed in sequence (syncronously)

I have a Vue button click handler that, depending on the arguments it receives, can do the following: execute request A only execute request B only execute request A and then request B sequentially (request B is only called if request A completes successf ...

VueJS/Vuetify - button fails to toggle when v-if statement is satisfied

I've encountered a puzzling issue that appears deceptively simple but proves to be quite perplexing. Within an array of objects, I utilize v-for to render each object along with two buttons; one button toggles the other and vice versa. My predicament ...

Restricting a Blob to a particular data type

As seen in the GitHub link, the definition of Blob is specified: /** A file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functional ...

What is the correct way to define the onClick event in a React component?

I have been encountering an issue while trying to implement an onClick event in React using tsx. The flexbox and button are being correctly displayed, but I am facing a problem with the onClick event in vscode. I have tried several ideas from the stack com ...

IntellJ Editor encounters Typescript error

Currently engaged in a project using Angular 1.6 and Typescript. Up until recently, there were no compilation errors to be found. However, I am now encountering some peculiar errors. The code remains unchanged and the application is functioning properly. ...

Vue.js: Resolving the "Unknown Custom Element" Issue with Hot Module Replacement

I have a good understanding of component registration, but I am encountering a challenging issue: Vue.js component Unknown custom element Unknown custom element when nesting components in Vue.js The Issue at Hand While using the development server, I ...

Switch the Follow/Following button depending on the user's current follow status with the individual

I am currently working on a functionality to toggle between the Follow and Following buttons based on whether the current user is following another individual. I have implemented an NgIF statement in my code, but I am facing challenges in properly checking ...

The data does not have a property named 'formData' according to the type 'Event'

Encountered an issue while attempting to compile my TypeScript code: typescript Property 'formData' does not exist on type 'Event'? formElem.addEventListener("submit", (e) => { // prevent default action on form submiss ...

What is the best way to exceed the capacity of a function in TypeScript by incorporating optional

I've been working on converting some code from JavaScript to TypeScript, and I have a specific requirement for the return type of a function. The function should return void if a callback parameter is provided, otherwise it should return Promise<o ...

What is the method for retrieving the marker's position in vue2-google-map after it has been dragged

I have incorporated the vue2-google-map library in my project to showcase a map with a marker. <gmap-map ref="mymap" :center="mapStartLocation" :zoom="17" style="width: 100%; height: 300px"> <gmap-marker v-on:change="updateCoordinates()" :pos ...

How to Implement a Pop-up Modal in Angular Using TypeScript

Looking to implement a popup window that activates when a specific button is clicked: <a (click)="open()" class='btn btn-primary m-r-5px'> <span class='glyphicon glyphicon-eye-open'></span> View </a> Utilize ...

Encountered a React TypeScript issue stating that the type '{ ... }' cannot be assigned to the type 'IntrinsicAttributes & IntrinsicClassAttributes<...>'

Embarking on a new journey with a react typescript project, I encountered this puzzling error: Failed to compile. /Users/simon/Code/web/react-news-col/src/MainNewsFeed.tsx TypeScript error in /Users/simon/Code/web/react-news-col/src/MainNewsFeed.tsx(27,35 ...