Search code examples
javascripttypescriptvue.jsnuxt.jsvuex

Nuxt read module state inside a component


I've got a Nuxt application with a store directory that resembles this folder https://nuxtjs.org/docs/2.x/directory-structure/store#example-folder-structure.

Imagine that I have a property isComplete in my module state inside the cart folder.

I get the following error that Property 'shop' does not exist on type 'RootState'.

How could I access this property in a Vue component ?

Component.vue

<script lang="ts">
import { defineComponent, onMounted } from '@nuxtjs/composition-api'
import { useStore } from '~/store'

export default defineComponent({
  name: 'Component',
  setup() {
    const store = useStore()

    onMounted(() => {
      if (store.state.shop.cart.isComplete) {
        // Execute some code
      }
    })
  },
})
</script>

My store/index.ts has the following implementation

import { InjectionKey, useStore as baseUseStore } from '@nuxtjs/composition-api'

export interface RootState {}

export const state = () => ({})

export const injectionKey: InjectionKey<RootState> =
  Symbol('vuex-injection-key')

export const useStore = () => {
  return baseUseStore(injectionKey)
}

store/shop/cart/state.ts

export interface CartState {
  isComplete: boolean
}

export const state = (): CartState => ({
  isComplete: false,
})

Solution

  • Store state

    Store files named state should have an object-returning method as its default export, so store/shop/cart/state.ts should contain export default state (where state is the method) as its last line. Otherwise, you'll see a warning in the browser console:

    store/shop/cart/state.ts should export a method that returns an object
    

    Or you could rename store/shop/cart/state.ts to store/shop/cart/index.ts (perhaps the original intent based on the exported state constant).

    RootState type

    There's no type inference available here, so the RootState needs to be explicitly typed to include the states of modules.

    1. Import the CartState from the namespaced module.

    2. Add a key named after each namespaced module, nested as needed (i.e., shop and then cart). Apply the CartState type for the cart key.

    // store/index.ts
    import type { CartState } from './shop/cart' 1️⃣
    
    export interface RootState {
      shop: {
        cart: CartState, 2️⃣
      }
    }
    

    GitHub demo