Store vuex Cannot read property 'store' of undefined" - javascript

I tried to create a first simple App but I have a problem with store.
I have in mainJS
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App'
import router from './router'
Vue.use(Vuex);
import {store} from './Store.js';
store.commit('increment')
new Vue({
el: '#app',
router,
store,
template: '<div><App></App></div>',
components: { App }
});
So in my store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
});
So I would create a child component of App Component that use a event increment, so I have created a Component Counter
<template>
<div>{{ count }}</div>
</template>
<script>
export default {
name: "Counter",
computed: {
count () {
return this.$.store.state.count
}
}
}
</script>
And I call this component from my App component that it is:
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view/>
<Counter></Counter>
</div>
</template>
<script>
import Counter from './components/Counter.vue'
export default {
name: 'app',
components:{
Counter
}
}
</script>
But I have this error in my Counter component:
[Vue warn]: Error in render: "TypeError: Cannot read property 'store'
of undefined"
found in
---> at src\components\Counter.vue
at src\App.vue

You only made a small mistake: It has to be $store, not $.store:
<template>
<div>{{ count }}</div>
</template>
<script>
export default {
name: "Counter",
computed: {
count () {
return this.$store.state.count
}
}
}
</script>

I had the same problem and changing from Vue to vue and Vuex to vuex in all lines of .js store file I got it working.

Related

Call Vue store action through browser console

I'm trying to create a webapp using VUE Vite with a router and store. The getter function in the vue file works fine. I have access to the chatMessages stored in the store.js file.
My problem is that I need to call the addMessage Action from the store.js file in the dev console using the browser.
Question: How could I archive this?
On older vue versions it would be done the following way using the main.js file:
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import './registerServiceWorker';
import { mapGetters, mapMutations, mapActions } from 'vuex';
Vue.config.productionTip = false;
const app = new Vue({
router,
store,
render: function (h) { return h(App) },
methods: {
...mapMutations([
'showLoading',
]),
...mapActions([
'addNotification',
]),
},
}).$mount('#app');
export default app;
Current vue3 chat.vue file:
<template>
<div></div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'Chat',
data: function() {
return {
}
},
methods: {
},
computed: {
...mapGetters({
chatMessages: 'chatMessageList',
}),
}
}
</script>
Current vue3 store.js file:
import { createStore } from 'vuex'
export default createStore({
state: {
chatMessages: {
list: [
{ type: "a", message: "test" }
]
}
},
mutations: {
addMessage(state, { type, message }) {
state.chatMessages.list.push({ type: type, message: message });
}
},
actions: {
addMessage({ commit }, { type, message }) {
commit('addMessage', { type, message });
}
},
getters: {
chatMessageList(state, getters) {
return state.chatMessages.list;
}
}
})
Current vue3 main.js file:
import App from "./App.vue";
import {createApp} from "vue";
import router from "./router/index.js";
import store from "./store/store";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.js";
window.app = createApp(App).use(router).use(store).mount('#app');
EDIT: I tested it the following way and I can call app.addMessage from the dev console but now the router wont work.
import App from "./App.vue";
import {createApp} from "vue";
import router from "./router/index.js";
import store from "./store/store";
import { mapGetters, mapMutations, mapActions } from 'vuex';
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap.js";
window.app = createApp({
methods: {
...mapActions([
'addMessage',
]),
}
}).use(router).use(store).mount('#app');
Assigning the store to the window object seems like a great approach, where you can easily then call it like in domiatorov's answer.
Another approach is:
var store = Array.from(document.querySelectorAll('*')).find(e => e.__vue_app__).__vue_app__.config.globalProperties.$store;
var actions = store._actions;
actions.addMessage[0]('mytype', 'mymessage');
The first part queries the body for an element containing __vue_app__ and will return your instance. In there, you can access config.globalProperties.$store to return your store object.
store is already available in this scope and can be exposed the same way as app:
window.store = store;
It can be used in console the same way as in an app:
store.dispatch(...)
I believe you can simply assign the store to the window object.
But do it from a top level single file component, the very first that is using the store and not in the setup to make sure the store got everything loaded.
Providing you have something like App.vue:
In setup() you would assign:
window.vueStore = store;
and use it from the console calling window.vueStore.

Vuejs register component and getting did you register the component correctly? error

In one of our project i try to use vuejs-countdown-timer component, but i get this error
Unknown custom element: - did you register the component
correctly? For recursive components, make sure to provide the "name"
option.
in this package documentation we have:
//Installation
npm i vuejs-countdown-timer -S Import component
// global register at main.js import VueCountdownTimer from
'vuejs-countdown-timer';
Vue.use(VueCountdownTimer);
and basic usage of that:
<template>
<vue-countdown-timer
#start_callback="startCallBack('event started')"
#end_callback="endCallBack('event ended')"
:start-time="'2018-10-10 00:00:00'"
:end-time="1481450115"
:interval="1000"
:start-label="'Until start:'"
:end-label="'Until end:'"
label-position="begin"
:end-text="'Event ended!'"
:day-txt="'days'"
:hour-txt="'hours'"
:minutes-txt="'minutes'"
:seconds-txt="'seconds'">
</vue-countdown-timer>
</template>
<script >
export default {
name: 'Timer',
methods: {
startCallBack: function(x) {
console.log(x);
},
endCallBack: function(x) {
console.log(x);
},
},
};
</script>
now after installing the package i imported into my app.js:
import Vue from 'vue'
import VueCountdownTimer from 'vuejs-countdown-timer';
Vue.use(Vuelidate)
Vue.use(VueCountdownTimer)
window.Vue = require('vue').default
import Timer from './components/partials/timer.vue'
new Vue({
store,
components: {
Timer,
//
}, computed: {}, mount: {}
}).$mount('#app')
and after that i try to use into html template as:
<login inline-template>
<div class="page-content">
<div class="content-wrapper">
...
</div>
<Timer></Timer>
</div>
</login>
my login.js content:
import {required, minLength, maxLength} from 'vuelidate/lib/validators'
import axios from "axios";
import {route} from "../../routes";
export default {
data() {
return {
//
}
}
}
Register vue-countdown-timer globally in app.js and your custom component timer locally in login.js
app.js
import Vue from 'vue'
import VueCountdownTimer from 'vuejs-countdown-timer';
Vue.use(Vuelidate)
Vue.use(VueCountdownTimer)
window.Vue = require('vue').default
new Vue({
store,
computed: {}, mount: {}
}).$mount('#app')
Login.js
import {required, minLength, maxLength} from 'vuelidate/lib/validators'
import axios from "axios";
import {route} from "../../routes";
import Timer from '../partials/timer.vue'
export default {
data() {
return {
//
}
},
components: {
Timer
},
}

How can I send slots to a component in render function in VueJs 3

I have a component like this
<template>
<div class="my-hello">
Hello {{ man }}
<slot name="test"></slot>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'HelloWorld',
props: {
man: String
}
})
</script>
I want to render this component with render function. My attempt is this, but it is not working.
import { createApp, h } from 'vue'
const app = createApp({
render () {
return h(component, { man: 'David' }, { test: () => h('p', {}, 'SLOT DATA') })
}
})
app.mount(element)
In here component is my imported single file vue component (HelloWorld). element is some element on the main html.
What's wrong here?

Unknown action type: change

I've read a lot of posts here and none of them worked for me. I have a very basic VueJS app but I have an error when I write something in my first component. Here's my code :
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
item: ''
},
mutations: {
change(state, item) {
state.item = item
}
},
actions: {
change({ commit }, newValue) {
commit('change', newValue);
}
},
getters: {
item: item => state.item
}
})
App.vue
<template>
<div id="app">
<AddItem/>
<DisplayItem/>
</div>
</template>
<script>
import AddItem from './components/AddItemComponent'
import DisplayItem from './components/DisplayItemComponent'
export default {
name: 'App',
components: {
AddItem,
DisplayItem
}
}
</script>
AddItemComponent.vue
<template>
<div>
<label for="item">Nom de l'objet</label><br/>
<input type="text" name="item" #input="changed">
</div>
</template>
<script>
export default {
methods: {
changed: function (event) {
this.$store.dispatch('change', event.target.value)
}
}
}
</script>
DisplayItemComponent.vue
<template>
<div>
<p>Nom de l'objet : {{ $store.getters.item }}</p>
</div>
</template>
...and finally my error
As I said, I tried a lot of things but none of them worked... Maybe I forget something ?
Thanks in advance for your help.
You need to dispatch to an action, then in the action, commit the value which will run your mutation. Also your state should be an object and not a function.
Here is a basic example:
export const store = new Vuex.Store({
state: {
item: ''
},
mutations: {
change(state, item) {
state.item = item
}
},
actions: {
change({ commit }, modifiedValue) {
// do some stuff
commit('change', modifiedValue)
}
},
getters: {
item: item => state.item
}
})
You should then be able to run your dispatch now:
this.$store.dispatch('change', event.target.value)
Finally I found my problem... I was importing the wrong store. Here's my final code and it's working !
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store/store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Thanks for any help !

Passing props to single-file components in Vue

I'm trying to pass data from my existing app to a single-file component in Vue. However, the component doesn't seem to be receiving the prop from the parent.
Sandbox here
Code:
// index.js
import Vue from "vue";
import App from "./App";
Vue.config.productionTip = false;
/* eslint-disable no-new */
new Vue({
el: "#app",
template: "<App/>",
propsData: {
someProp: "this is a prop test!!"
},
components: { App }
});
And the component:
// App.js
<template>
<div id="app">
<h1>My Todo App! the prop: {{ someProp }}</h1>
<TodoList/>
</div>
</template>
<script>
import TodoList from "./components/TodoList.vue";
export default {
props: ["someProp"],
components: {
TodoList
}
};
</script>
The result doesn't show the prop at all, as if it's not passing anything. What gives?

Categories

Resources