while I am trying to load page it's showing me error "TypeError: Cannot read property 'state' of undefined". As per documentation I have tried this bus not loading store.
<template>
<div>
</div>
</template>
<script>
import { store } from '#/components/tenant/store/store'
import Vue from 'vue'
export default {
store:store,
data: () => {
return {
}
}
}
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const userStore = new Vuex.Store({
state: {}
})
Maybe I have misunderstood your question, but since you're exporting the const userStore, don't you need to do the following:
import { userStore } from '#/components/tenant/store/store';
Related
So I'm experimenting with a new project created with vue cli, where I am using router and VueX
So in my HelloWorld.vue file, I've got this code in the script section:
import { mapState } from 'vuex'
export default {
name: 'hello',
computed: mapState({
msg: 'nombre'
}),
Is there a more direct way of calling values in the state?, like for example I would like to do
msg: store.nombre
My vuex store is defined in the root main.js like this:
//vuex
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
nombre: "POS vuex"
}
});
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
Actually I was looking for this way:
msg: this.$store.state.nombre
(I was missing the ".state." part)
As soon as you're using mapState as computed you can actually call these states with this in that component - in the template or script section:
Use the ... operator on your mapState and you're done:
Example:
Your store:
const store = new Vuex.Store({
state: {
nombre: "POS vuex",
otherState: "abc",
anotherState: "efg"
}
});
Your component:
<template>
<div id="test">
{{ nombre }}
{{ otherState }}
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'hello',
methods: {
logState() {
console.log(this.anotherState);
}
},
computed: {
...mapState(["nombre", "otherState", "anotherState"]),
}
}
</script>
In addition to the the mapState helper
computed: {
...mapState('moduleOne', ['keyOne', 'keyTwo'])
}
which lets you access the values via this.keyOne and this.keyTwo inside your component.
You can also add your store to the root vue instance and access your state inside your components via the global this.$store directive.
this.$store.module.keyOne
this.$store.module.keyTwo
Additionally if you need to access your store from outside your components you can also export the store and import it directly from non-component code.
If you export your store:
import Vue from 'vue'
import Vuex from 'vuex'
import moduleTwo from './modules/moduleOne'
import moduleOne from './modules/moduleTwo'
Vue.use(Vuex)
const store = new Vuex.Store({
strict: true,
modules: {
moduleOne,
moduleTwo
}
})
export default store
You can import it anywhere you need to access state, getters, actions, and mutations.
import store from '#/store'
console.log(store.state.moduleOne.keyone)
store.dispatch('moduleOne/actionOne', { keyOne: valOne })
store.getters['moduleOne/getterOne']
store.commit('moduleOne/mutationOne', data)
Call you'r state in created method of vuex.
THanks
I tried to use vue-router inside actions of vuex, which is working fine at localhost.
However, i got errors when I tried to prepare store(for mock) by importing "actions" from store file.
Could you help me out in this issue?
versions
vue-test-utils: 1.0.0-beta.16
yarn: 1.5.1
vuejs: 2.5.13
vue-jest: 1.4.0
error msg
FAIL test/components/main.test.js
● Test suite failed to run
/Users/gulliver/Desktop/test/vue-test-utils-jest-example/node_modules/vue/dist/vue.esm.js:10809
export default Vue$3;
^^^^^^
SyntaxError: Unexpected token export
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:305:17)
at Object.<anonymous> (src/router/main.js:1:203)
at Object.<anonymous> (src/store/main.js:3:13)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 2.354s
Ran all test suites matching /test\/components\/main.test.js/i.
error An unexpected error occurred: "Command failed.
Exit code: 1
app/src/main.js
import Vue from "vue/dist/vue.esm";
import App from './App.vue'
import store from './store/main.js';
import router from './router/main.js';
new Vue({
el: '#app',
render: h => h(App),
store,
router,
})
app/src/store/main.js
import Vue from "vue";
import Vuex from 'vuex';
import router from '../router/main.js'
Vue.use(Vuex)
export const actions = {
locationTo(context, url){
router.push(url)
}
}
export default new Vuex.Store({
actions,
})
app/src/router/main.js
import Vue from "vue/dist/vue.esm";
import VueRouter from 'vue-router';
import root from '../components/root.vue';
import hoge from '../components/hoge.vue';
Vue.use(VueRouter)
export const routes = [
{ path: '/', component: root},
{ path: '/hoge', component: hoge},
];
export default new VueRouter({
mode: 'history',
routes
})
app/test/components/main.test.js
import Vue from "vue";
import Vuex from "vuex";
import { shallowMount, createLocalVue } from "#vue/test-utils";
import { actions } from "#/store/main"; //NOTE: this causes error
import _ from "lodash";
const localVue = createLocalVue();
import root from '#/components/root.vue'
import hoge from '#/components/hoge.vue'
describe('increment.vue', () => {
let propsData;
let store;
let wrapper;
beforeEach(() => {
propsData = _.cloneDeep(personObject)
store = new Vuex.Store(_.cloneDeep({
actions,
}))
const $route = {
path: '/hoge', components: hoge
}
wrapper = shallowMount(root, {
localVue,
propsData,
store,
use: ['Vuex'],
stubs: ['router-view'],
mocks: {
$route
}
})
});
it('test:router in store', () => {
// check if URL changed after action executed
});
})
components
// App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
// root.vue
<template>
<div>
<p>root component</p>
</div>
</template>
<script>
export default {
mounted () {
this.$store.dispatch('locationTo', '/hoge')
},
}
</script>
// hoge.vue
<template>
<div>
<p>hoge template</p>
</div>
</template>
This error is related to the fact that Jest runs in a Node.js environment, and you are using export default, which does not work by default in Node.js (Node uses module.exports). I guess you are using webpack for your dev/production build, but not for the test environment.
Are you using Jest? If so, you will need to set up babel-jest so Jest knows how to read ES Modules syntax (import/export).
Read more here: https://vue-test-utils.vuejs.org/guides/#testing-single-file-components-with-jest
This can be annoying to set up, let me know if you need more help to get it working.
Right now, I'm trying to show the contents of state object from store.js on my App.vue.
I've tried vuex examples on Medium and other website, but I'm keep failing: non of them worked: some of them even gave me a WebPack config error.
My App.vue
<template>
<div id="app">
<img src="./assets/logo.png">
<h1>TEST</h1>
</div>
</template>
<script>
import Store from './store/index'
export default {
name: 'App',
Store
}
</script>
My store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
alpha: ['1st data']
},
mutations: {
ADD ({ alpha }) {
const beta = 'new!'
state.alpha.push(beta)
}
}
})
My main.js
import Vue from 'vue'
import App from './App'
import Vuex from 'vuex'
import store from './store/index'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
components: { App },
template: '<App/>'
})
You shouldn't be importing the store in App.vue. It only needs to be included in main.js and passed as an option when constructing the Vue instance. Within a component, the store is thereafter accessible via this.$store.
Second, your mutation should receive a context object as it's first parameter. context consists of properties such including state and commit. Those are the ways in which you access state within a mutation.
// notice context is the first parameter
mutations: {
ADD (context, { param }) {
const beta = 'new!'
context.state.alpha.push(beta)
})
}
// you can also deconstruct context like this
mutations: {
ADD ({state}, { param }) {
const beta = 'new!'
state.alpha.push(beta)
})
}
I also changed the way alpha to param. You don't receive the state's properties unless you destructure even further.
The problem is that in your main.js is missing Vue.use(veux)
you should have something like this:
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App'
import store from './store'
Vue.use(Vuex) // <-- Add this
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
template: '<App/>',
components: { App }
})
My component does not update the loaded property when Store.loaded changes:
Component
import { Vue } from 'vue-property-decorator'
import Component from 'nuxt-class-component'
import { Store } from '../repositories'
#Component
export default class Layout extends Vue {
loaded = Store.loaded
}
Store
class Root {
loaded = false
}
export let Store = new Root()
export default Store
In your example Store is just plain function (class), without any reactivity (no Vue watchers attached for Store.loaded field).
Only properties inside component's data are reactive. If you want reactive single store outside of vue components (better for big frontend applications), you should use Vuex
Simple example will be:
App.vue:
<script>
import { mapGetters, mapMutations } from 'vuex';
import store from './store';
import ChildComponent from './components/ChildComponent.vue';
export default {
store,
components: { ChildComponent },
methods: {
...mapMutations(['toggleLoaded']),
},
computed: {
...mapGetters({
isLoaded: 'isLoaded',
}),
}
}
</script>
<template>
<div id="app">
Toggle loaded
<h3>Root component: </h3>
<div>The loaded flag is: {{ isLoaded }}</div>
<ChildComponent />
</div>
</template>
components/ChildComponent.vue:
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters({
isLoaded: 'isLoaded', //accessing to same data, as root through single Vuex state
}),
}
}
</script>
<template>
<div class="hello">
<h3>Child component</h3>
<div>The loaded flag is: {{ isLoaded }}</div>
</div>
</template>
And reactive Vuex store:
store/index.js:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state = {
loaded: false
};
const getters = {
isLoaded: state => state.loaded,
};
const mutations = {
toggleLoaded: (state) => {
state.loaded = !state.loaded;
}
};
export default new Vuex.Store({
state,
mutations,
// actions,
getters,
strict: true
});
You can find full source of this example on GitHub.
I am new to Vuex and I am trying a simple test using a getter to return a data property from the state. I'm attempting to display the returned data on the page.
COMPONENT.VUE
<template>
<div class="section" >
<div class="section-content">
<p>{{test.title}}</p>
</div>
</div>
</template>
<script>
export default {
name: 'startNewSearch',
computed: {
getTest() { return this.$store.getters.getTest }
}
}
</script>
GETTERS.JS
export default {
getTest(state) {
return state.test
}
}
STORE.JS
import Vue from 'vue'
import Vuex from 'vuex'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
newSearch: {},
test: {
title: 'Test',
msg: 'This is a test message'
}
},
getters,
mutations,
actions
})
The error that I get is that test is- Property or method "test" is not defined on the instance but referenced during render. Is there another step to saving the data to the component that I missed?