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.
Related
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')
}
},
}
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"]),
},
};
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}`);
},
},
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)
}
}
}
I'm trying Quasar for the first time and trying to use the Vuex with modules but I can't access the $store property nor with ...mapState. I get the following error 'Cannot read property 'logbook' of undefined' even though I can see that the promise logbook exists on Vue Devtools. Print from Devtools
Here is my store\index.js
import Vue from 'vue';
import Vuex from 'vuex';
import logbook from './logbook';
Vue.use(Vuex);
export default function (/* { ssrContext } */) {
const Store = new Vuex.Store({
modules: {
logbook,
},
strict: process.env.DEV,
});
return Store;
}
Here is the component
<template>
<div>
<div>
<h3>RFID</h3>
<q-btn #click="logData"
label="Save"
class="q-mt-md"
color="teal"
></q-btn>
<q-table
title="Logbook"
:data="data"
:columns="columns"
row-key="uid"
/>
</div>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
export default {
name: 'RFID',
mounted() {
this.getLogbookData();
},
methods: {
...mapActions('logbook', ['getLogbookData']),
...mapGetters('logbook', ['loadedLogbook']),
...mapState('logbook', ['logbookData']),
logData: () => {
console.log(this.loadedLogbook);
},
},
data() {
return {
};
},
};
</script>
<style scoped>
</style>
Here is the state.js
export default {
logbookData: [],
};
Error that I get on the console
Update: Solved the problem by refactoring the way I declared the function. I changed from:
logData: () => { console.log(this.loadedLogbook); }
to
logData () { console.log(this.loadedLogbook); }
Check the .quasar/app.js file. Is there a line similar to import createStore from 'app/src/store/index', and the store is later exported with the app in that same file?
I think you confused all the mapx functions.
...mapState and ...mapGetters provide computed properties and should be handled like this
export default {
name: 'RFID',
data() {
return {
};
},
mounted() {
this.getLogbookData();
},
computed: {
...mapGetters('logbook', ['loadedLogbook']),
...mapState('logbook', ['logbookData']),
}
methods: {
...mapActions('logbook', ['getLogbookData']),
logData: () => {
console.log(this.loadedLogbook);
},
}
};