codebot
codebot

Reputation: 697

vue2 and composition api - cannot import store, error [vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function

I am using vue 2.6.14 and composition-api 1.3.3 package to use composition api. I have

my main.js like

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI) 
import App from './App.vue'
import router from './router' 
Vue.config.productionTip = false 
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

I try to setup a store

I have a src folder / store folder / index.js

and inside the index.js

import { reactive } from '@vue/composition-api'  

const state = reactive({
    counter : 0
})

export default{ state }

inside App.vue I try to import store to use it

<script>  
import store from '@/store'  
</script>

I get the error Uncaught Error: [vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function.

I tried all solutions from here and nothing works. If I remove the import store from '@/store' the error goes away. Using vue 3 s not an option.

How can I solve this?

Thanks

Upvotes: 0

Views: 2709

Answers (1)

tony19
tony19

Reputation: 138286

imports are automatically hoisted to the top of the file, so it actually precedes the Vue.use(VueCompositionApi) at runtime.

So these lines:

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI) 
import App from './App.vue' 👈 hoisted

...become:

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'
import App from './App.vue' 👈
Vue.use(VueCompositionAPI) 

So the plugin doesn't get installed before App.vue gets imported, leading to the error you observed.

Option 1: Move plugin installation to own file

You can move the installation of @vue/composition-api into its own file that could be imported before App.vue:

// lib/composition-api.js
import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'
Vue.use(VueCompositionAPI) 

// main.js
import Vue from 'vue'
import './lib/composition-api'
import App from 'App.vue'

demo 1

Option 2: Use require() in App.vue

require the store in the component's setup(), where the @vue/composition-api would've already been installed:

// App.vue
import { defineComponent, computed } from '@vue/composition-api'

export default defineComponent({
  setup() {
    const store = require('@/store').default

    return {
      counter: computed(() => store.state.counter),
      increment: () => store.state.counter++,
    }
  },
})

demo 2

Option 3: Use import() in App.vue

Dynamically import the store with import(). This is especially needed in Vite, which does not have require().

// App.vue
import { defineComponent, computed, ref } from '@vue/composition-api'

export default defineComponent({
  setup() {
    const store = ref()
    import('@/store').then(mod => store.value = mod.default)

    return {
      counter: computed(() => store.value?.state.counter),
      increment: () => store.value && store.value.state.counter++,
    }
  },
})

demo 3

Upvotes: 5

Related Questions