Vuex: unknown action type: - vue.js

I have a problem about how to dispatch action in Vuex.
Now I'm making an app and using Vuex.
I want to dispatch vuex signin action in store/user.js from Login.vue,but it's not working.I want you to give me any tips.
Now it's the app's directory constructure.
enter image description here
And the files which can contain problems are here:
index.js
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user'
Vue.use(Vuex);
const store = new Vuex.Store({
modules: {
user
}
})
export default store;
user.js
import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios'
Vue.use(Vuex);
const user = new Vuex.Store({
state: {
current: null,
name: 'John'
},
mutations: {
setCurrent(state, payload) {
state.current = payload
}
},
actions: {
signin({commit}, {name, password}) {
axios.$post('http://localhost:3000/login', {name, password})
.then((response) => {
commit('setCurrent', response.data)
})
},
signout({commit}) {
commit('setCurrent', null)
}
}
})
export default user;
Login.vue
<template>
<v-container>
<v-card>
<v-card-title>
Login
</v-card-title>
<v-card-text>
<v-form>
<v-text-field
v-model="name"
:counter="10"
label="name"
required
></v-text-field>
<v-text-field
v-model="password"
:counter="10"
label="password"
required
></v-text-field>
<v-btn
class="mr-4"
#click="submitLoginDatas()"
>
Login
</v-btn>
</v-form>
</v-card-text>
</v-card>
{{ getName }}
<v-row class="button">
<v-col>
<v-btn
style="margin-top: 4px;"
to="/signup"
>
Signup
</v-btn>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
data() {
return {
name: '',
password: ''
}
},
methods: {
async submitLoginDatas() {
console.log('HI')
console.log(this.$store.state.user.name)
// ここまでは呼ばれてる
// store自体も登録できている(下のgetNameから確認できる)
await this.$store.dispatch("signin",
{
name: this.name,
password: this.password
}
)
}
},
computed: {
getName() {
return this.$store.state.user.name
}
}
}
</script>
What I checked by now
・typo...ex.express actions as action like this
・namespace...now I don't express namespaced:true in user.js, but I tried namespaced: true in user.js with the below code. But it didn't work.
this.$store.dispatch("user/signin", {
name: this.name,
password: this.password
})
・user.js is registered correctly in index.js or not
...getName() in computed in Login.vue is working, so maybe it's ok.
・whether actions and mutations are written as object, not function
...maybe it's correct.
Thank you for reading. My question is the reason why this error
[vuex] unknown action type: signin
has been occuring and how to fix it.

You are trying to use Vuex inside another Vuex - this is not going to work. Your Vuex module(s) should export a plain object instead of Vuex instance. Please change modules/user.js to be
import axios from 'axios'
export default {
state(): {
return {
current: null,
name: 'John'
}
},
mutations: {
setCurrent(state, payload) {
state.current = payload
}
},
actions: {
signin({commit}, {name, password}) {
axios.$post('http://localhost:3000/login', {name, password})
.then((response) => {
commit('setCurrent', response.data)
})
},
signout({commit}) {
commit('setCurrent', null)
}
}
}

Related

receive 500 http error when make request from vuex store. in vue js

to add data to the server by axios POST method, I receive 500 HTTP error.
it occurs when the request is made from vuex store.
when the request is form component there isn't any problem.
export
default {
name: 'addCategoury',
data: () => ({
name: '',
src: '',
description: '',
}),
methods: {
async AddCat() {
const newCategory = {
categoryName: this.name,
description: this.description,
imageUrl: this.src,
}
let result = await this.$store.dispatch('AddCategory', newCategory)
if (result.data) {
alert('shode');
} else {
alert('result failed')
}
}
}
}
////////////////////in store js////////////////////
import Vue from 'vue'
import Vuex from 'vuex'
import api from '../services/API'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
categories: []
},
getters: {
},
mutations: {
get_category(state, cat) {
}
},
actions: {
async AddCategory(newCategory) {
try {
let result = await api().post('/category/create',newCategory);
console.log(result)
if (result.data) {
alert('ok')
return result
}
} catch (error){
return error
}
}
},
})
////////////////////in API js////////////////////
import axios from 'axios'
export default () => {
return axios.create({
baseURL: 'https://limitless-lake-55070.herokuapp.com'
})
}
<template>
<v-container class="align-text-center">
<v-form class="form">
<v-container>
<v-row>
<v-col cols="7">
<v-text-field outlined v-model="name" label="name" required>
</v-text-field>
</v-col>
<v-col cols="7">
<v-text-field outlined v-model="src" label="image Source" required>
</v-text-field>
</v-col>
<v-col cols="7">
<v-text-field outlined v-model="description" label="description"></v-text-field>
</v-col>
<v-col cols="12">
<v-btn #click="AddCat">
ADD
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
</v-container>
</template>
to add data to the server by axios POST method, I receive 500 HTTP error.
it occurs when the request is made from vuex store.
when the request is form component there isn't any problem.
// in the component
methods:{
async AddCat() {
const newCategory = {
categoryName: this.name,
description: this.description,
imageUrl: this.src,
}
let result = await this.$store.dispatch('AddCategory', newCategory)
if(result.data){
alert('dode');
} else {
alert('result failed')
}} }
// in the store.js
import api from '../services/API'
actions: {
async AddCategory(newCategory) {
try {
let result = await api().post('/category/create',newCategory);
console.log(result)
if (result.data) {
alert('ok')
return result
}
} catch (error){
return error
}
}
},
// API
import axios from 'axios'
export default () => {
return axios.create({
baseURL: 'https://limitless-lake-55070.herokuapp.com'
})
}
So I see you're using $store.dispatch, I am assuming you want to use vue actions. I will explain my code after the solution below:
Your component file looks fine to me, please make sure to add the import file too. It plays a big role in your files too, we won't be able to debug without that.
api.js // would be your file where you're setting the default URL for Axios
import axios from "axios";
export default () => {
return axios.create({
baseURL: "https://limitless-lake-55070.herokuapp.com"
});
};
store.js // Actions object is missing from your question
import api from "../plugins/api";
export const actions = {
async AddCategory(newCat) {
try {
let res = await api().post('/category/create',newCat)
let result = res.status;
if (result == 200 || result == 201) {
alert('ok')
}
} catch(error) {
console.log('dd')
}
},
}

Vuex sync : Cannot read property of undefined

Im trying to use vuex to make things easier, overall it's fine, but Im stuck when using a getter with param from an other getter.
main code :
<template>
<v-container>
<v-card v-for="(order,i) in getOrders" :key="i" class="cart-cards text-left">
<v-card-title>
{{getMealById(order.meal_id).name}}
</v-card-title>
<v-btn v-on:click="addQuantity(order)">
+
</v-btn>
<h1>
{{order.quantity}}
</h1>
<v-btn #click="reduceQuantity(order)">
-
</v-btn>
</v-card>
</v-container>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
data: () => ({
}),
created() {
this.fetchOrders();
},
mounted() {
},
methods: {
...mapActions(["fetchOrders"]),
addQuantity(order) {
order.quantity += 1;
this.updateOrders(order);
},
reduceQuantity(order) {
if (order.quantity > 0) {
order.quantity -= 1;
this.updateOrders(order);
}
},
},
computed: {
...mapGetters(["getOrders", "getMealById"]),
},
};
order.js :
import axios from 'axios'
import url from '../../config.js'
const state = {
all_orders: [],
}
const getters = {
getOrders : (state)=>state.all_orders,
}
const actions = {
async fetchOrders({commit}) {
const response = await axios.get("http://" + url + "/orders")
commit('setOrders',response.data)
},
async updateOrders({commit},payload) {
const response = await axios.put("http://" + url + "/orders/"+payload.id,payload)
commit('setOrders',response.data)
},
}
const mutations = {
setOrders: (state,orders)=>{
state.all_orders = orders
},
}
export default {
state,
getters,
actions,
mutations
}
meal.js
import axios from 'axios'
import url from '../../config.js'
const state = {
all_meals: [],
}
const getters = {
getMeals: (state) => state.all_meals,
getMealById: (state) => (id) => {
return state.all_meals.find(todo => todo.id === id)
}
}
const actions = {
async fetchMeals({ commit }) {
const response = await axios.get("http://" + url + "/meals")
commit('setMeals', response.data)
},
}
const mutations = {
setMeals: (state, meals) => {
state.all_meals = meals
},
}
export default {
state,
getters,
actions,
mutations
}
So when iam accessing the vue from a link, no error, but when I load the url by itself, an error occur and the getMealById dont trigger
overall Is their a good practice for "waiting" for response on state/actions call ?
Thanks in advance !!!
In component, you can check if getMeals returns a non-empty array, then render the v-for loop:
<template>
<v-container v-if="getMeals().length > 0">
<v-card v-for="(order,i) in getOrders" :key="i" class="cart-cards text-left">
<v-card-title>
{{getMealById(order.meal_id).name}}
</v-card-title>
</v-card>
</v-container>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
data: () => ({
}),
created() {
this.fetchOrders();
},
mounted() {
},
methods: {
...mapActions(["fetchOrders"]),
},
computed: {
...mapGetters(["getMeals", "getOrders", "getMealById"]),
},
};

nuxtServerInit data not show in page

I try to use nuxtServerInit method.
index.js
import productsService from "../services/productsService";
export const state = () => ({
hotDeals: [],
specialities: []
})
export const mutations = {
SET_SPECIALITIES(state, payload) {
state.specialities = payload;
}
}
export const actions = {
async nuxtServerInit({ dispatch}, ctx) {
try {
await dispatch('fetchSpecialities');
}catch (e) {
console.log(e);
}
},
fetchSpecialities({ commit }) {
productsService.getSpecialities()
.then(response => {
commit('SET_SPECIALITIES', response.data);
});
}
}
component usage
<template>
<v-layout
justify-center
align-center
>
<div>
<v-row >
<span v-for="item in specialities">{{item.productCode}}</span>
</v-row>
</div>
</v-layout>
</template>
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState(["specialities"])
}
}
</script>
But it show nonthing on page. If I try to use console.log(state.specialities) in mutation after change state I can see data in web storm console. But in component data is not showing.
i think using watchers will solve your problem
watch: {
specialities(newValue, oldValue) {
console.log(`Updating from ${oldValue} to ${newValue}`);
},
},

vuex unknown action type: ADD_ARTICLE

I'm trying to insert a title to my database using vuex but encountered an error.
As far as I know I am calling the action correctly but idk why it gives me error, from what I've read it is something about namespacing
[vuex] unknown action type: ADD_ARTICLE
<template>
<section>
<v-container fluid>
<v-card raised></v-card>
<v-card raised style="margin-top:10px">
<v-card-text class="headline font-weight-black">
<v-layout>
<v-row align-content="center">
<v-col>
TITLE
{{title}}
<v-text-field
v-model="title"
filled
placeholder="Provide a Title for the article"
prepend-icon="title"
></v-text-field>
</v-col>
</v-row>
</v-layout>
<v-layout align-end justify-end>
<v-btn color="red white--text" style="margin:10px" #click="passToDB">SUBMIT</v-btn>
</v-layout>
</v-card-text>
</v-card>
</v-container>
</section>
</template>
<script>
import { mapActions } from "vuex";
export default {
data() {
return {
title: ""
};
},
methods: {
...mapActions(["ADD_ARTICLE"]),
passToDB() {
this.ADD_ARTICLE(this.title);
}
}
};
</script>
and this is article module where I will export to store.js
import axios from 'axios';
//state
const state = {
articles: []
};
//getters
const getters = {
allArticles: (state) => state.articles
}
//mutations
const mutations = {
RETRIEVE_ARTICLES: (state, articles) => (state.articles = articles),
ADD_ARTICLE: (state, article) => state.articles.push(article)
};
//actions
const actions = {
//retrieve articles in server
async loadArticles({ commit }) {
const response = await axios.get('http://localhost:9001/article/articles');
commit('RETRIEVE_ARTICLES', response.data);
},
async addArticle({ commit }, TITLE) {
const response = await axios.post('http://localhost:9001/article/add', {
TITLE: TITLE
});
commit('ADD_ARTICLE', response.data)
}
};
//export
export default {
state,
getters,
actions,
mutations
};
here is my store.js
import Vue from 'vue';
import Vuex from 'vuex';
import login from './modules/login';
import article from './modules/article';
Vue.use(Vuex)
export default new Vuex.Store({
//import modules
modules: {
login,
article
}
});
In your store you declared an addArticle action but you are importing ADD_ARTICLE.
You just need to change it like that :
import { mapActions } from "vuex";
export default {
data() {
return {
title: ""
};
},
methods: {
...mapActions(["addArticle"]),
passToDB() {
this.addArticle(this.title);
}
}
};
As pointed by #Eugen Govorun by default namespacing is turned off.
If you turned it on by doing :
export default {
state,
getters,
actions,
mutations,
namespaced: true
};
You would have used your Action by doing so :
import { mapActions } from "vuex";
export default {
data() {
return {
title: ""
};
},
methods: {
...mapActions("article", ["addArticle"]),
passToDB() {
this.addArticle(this.title);
}
}
};
Because you are importing your module with the name article.
By default namespacing is turned off. There is no ADD_ARTICLE action in your article module. Just mutation with such a name. Your action name actually is addArticle.

Getting Error in render: "TypeError: Cannot read property 'title' of undefined" when rendering CourseDescriptionPageComponent

Here is how CourseDescriptionPage.vue looks
import CourseCover from './CourseDescription/CourseCover.vue'
import WhyJoin from './CourseDescription/WhyJoin.vue'
import CourseStructure from './CourseDescription/CourseStructure.vue'
export default {
props: ['id'],
data () {
return {
hasDetails: false
}
},
created () {
this.$store.dispatch('loadCourseDetails', this.id).then(() => {
this.hasDetails = true
})
},
computed: {
course () {
return this.$store.state.courseDetails[this.id]
}
},
components: {
CourseCover,
WhyJoin,
CourseStructure
},
name: 'CourseDescriptionPage'
}
<template>
<div v-if="hasDetails">
<course-cover :courseTitle="course.title" :courseDuration="course.duration"></course-cover>
<why-join :courseTitle="course.title" :courseJobs="course.jobs"></why-join>
<course-structure :lectureList="course.lectureList"></course-structure>
</div>
</template>
Here is how my store looks
import Vuex from 'vuex'
import * as firebase from 'firebase'
Vue.use(Vuex)
export const store = new Vuex.Store({
state: {
courseDetails: {},
loading: false
},
mutations: {
setCourseDetails (state, payload) {
const { id, data } = payload
state.courseDetails[id] = data
},
setLoading (state, payload) {
state.loading = payload
}
},
actions: {
loadCourseDetails ({commit}, payload) {
commit('setLoading', true)
firebase.database().ref(`/courseStructure/${payload}`).once('value')
.then((data) => {
commit('setCourseDetails', {
id: payload,
data: data.val()
})
commit('setLoading', false)
})
.catch(
(error) => {
console.log(error)
commit('setLoading', false)
}
)
}
}
Here is how my CourseCover.vue looks
export default {
props: {
courseTitle: {
type: String,
required: true
},
courseDuration: {
type: String,
required: true
}
},
name: 'CourseCover'
}
<template>
<v-jumbotron
src="./../../../static/img/course_cover_background.png">
<v-container fill-height>
<v-layout align-center>
<v-flex>
<h3>{{ courseTitle }}</h3>
<span>{{ courseDuration }}</span>
<v-divider class="my-3"></v-divider>
<v-btn large color="primary" class="mx-0" #click="">Enroll</v-btn>
</v-flex>
</v-layout>
</v-container>
</v-jumbotron>
</template>
I think there is something wrong with the way I am using props here but I couldn't figure out.
The data is loaded in store by the firebase that I know for sure because it shows in Vue dev tools but I just couldn't understand why Vue is complaining about that.
Thanks in advance.
course is undefined on component initialize ,so then you should return an empty object:
computed: {
course () {
return this.$store.state.courseDetails[this.id] || {}
}
},