How can I access a method or variable defined in the Vuex 4 store in my Blade file?
I am using a compiled app.js from vite. Obviously in the components of Vue js I can access the store, I wonder if it is also possible to do it in a blade file.
Vue js #app instance must be one of course.
If at the end of my blade file I write this
<script>
import {useStore} from "vuex";
import {onMounted, watch, ref, defineComponent} from 'vue'
export default {
setup() {
const click = () => {
store.commit('mutazione');
};
onMounted(() => {
alert('test');
})
const store = useStore();
return {
store,
click
}
},
}
</script>
the console gives me this type of error
Unexpected token '{'. import call expects exactly one argument.
First Leave laravel out of it.
It is purely vuex5.0 / Pinia https://pinia.vuejs.org job to do.
Best practice is Create the store of every type of data you need like
https://github.com/puneetxp/the check test directly in it totally in JavaScript you can see like create Store assume it is for Product data.
import { defineStore, acceptHMRUpdate } from "/js/vue/pinia.js";
export const useProductStore = defineStore({
id: "Product",
state: () => ({
rawItems: [],
}),
getters: {
items: (state) => state.rawItems
},
actions: {
addItem(product) {
this.rawItems.push(product)
},
removeItem(id) {
this.rawItems = this.rawItems.filter(i => i.id != id);
},
editItem(product) {
this.rawItems = this.rawItems.filter(i => i.id != product.id);
this.rawItems.push(product);
},
upsertItem(products) {
products.forEach(product => {
this.rawItems = this.rawItems.filter(i => i.id != product.id);
this.rawItems.push(product);
});
}
},
})
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useActive_roleStore, import.meta.hot))
}
then we can use in your component
import { useProductStore } from "/js/vue/Store/Model/Product.js";
export default {
template: ``,
data() {
return {
useProductStore,
}
}
}
for use use it on useProductStore().items as my design you can make your own if you want.
Related
What I want to come true
I use this.$axios many times, so I tried to put it in a constant, but it doesn't work.
I read the official docs but didn't understand.
Is it because this isn't available in the Nuxt.js lifecycle?
Code
url.js
export const AXIOS_POST = this.$axios.$post
export const POST_API = '/api/v1/'
export const POST_ITEMS_API = '/api/v1/post_items/'
Vuex
import * as api from './constants/url.js' // url.js in this.
export const state = () => ({
list: [],
hidden: false
})
export const mutations = {
add (state, response) {
state.list.push({
content: response.content,
status: response.status
})
},
remove (state, todo) {
state.list.splice(state.list.indexOf(todo), 1)
},
edit (state, { todo, text }) {
state.list.splice(state.list.indexOf(todo), 1, { text })
},
toggle (state, todo) {
todo.status = !todo.status
},
cancel (state, todo) {
todo.status = false
},
// アクション登録パネルフラグ
switching (state) {
state.hidden = !state.hidden
}
}
export const actions = {
post ({ commit }, text) {
//I want to use it here
this.$axios.$post(api.POST_ITEMS_API + 'posts', {
post_items: {
content: text,
status: false
}
})
.then((response) => {
commit('add', response)
})
}
}
Error
Uncaught TypeError: Cannot read property '$axios' of undefined
Since your file is located into a constants directory, you should probably use some .env file.
Here is a guide on how to achieve this in Nuxt: https://stackoverflow.com/a/67705541/8816585
If you really want to have access to it into a non .vue file, you can import it as usual with something like this
/constants/url.js
import store from '~/store/index'
export const test = () => {
// the line below depends of your store of course
return store.modules['#me'].state.email
}
PS: getters, dispatch and everything alike is available here.
Then call it in a page or .vue component like this
<script>
import { test } from '~/constants/url'
export default {
mounted() {
console.log('call the store here', test())
},
}
</script>
As for the lifecyle question, since the url.js file is not in a .vue file but a regular JS one, it has no idea about any Vue/Nuxt lifecycles.
I'm trying to call an action in my vue from my store.
This is my file aliments.js in my store:
import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios';
Vue.use(Vuex, axios);
export const state = () => ({
aliments: {},
})
export const mutations = () => ({
SET_ALIMENTS(state, aliments) {
state.aliments = aliments
}
})
export const actions = () => ({
async getListAliments(commit) {
await Vue.axios.get(`http://localhost:3080/aliments`).then((response) => {
console.log(response);
commit('SET_ALIMENTS', response);
}).catch(error => {
throw new Error(`${error}`);
})
// const data = await this.$axios.get(`http://localhost:3080/aliments`)
// commit('setUser', user)
// state.user = data;
// return state.user;
}
})
export const getters = () => ({
aliments (state) {
return state.aliments
}
})
I want to diplay a list of aliments in my vue with :
{{ this.$store.state.aliments }}
I call my action like this :
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
computed: {
...mapGetters(['loggedInUser', 'aliments']),
...mapActions(['getListAliments']),
getListAliments() {
return this.$state.aliments
}
}
}
</script>
I don't understand where is my mistake :/
NB: I also tried with a onclick method on a button with a dispatch('aliments/getListAliments')... but doesn't work...
The problem is that you're mapping your actions in the "computed" section of the component, you should map it in the "methods" section !
Hi and Welcome to StackOverflow
to quickly answer to your question, you would call an action as:
this.$store.dispatch('<NAME_OF_ACTION>', payload)
or though a mapActions as
...mapActions(['getListAliments']), // and you call `this.getListAliments(payload)`
or yet
...mapActions({
the_name_you_prefer: 'getListAliments' // and you call `this.the_name_you_prefer(payload)`
}),
for getters, it's the same process, as you already have 2 definitions ['loggedInUser', 'aliments'] you simply call the getter like if it was a computed value <pre>{{ aliments }}</pre>
or when we need to do a bit more (like filtering)
getListAliments() {
return this.$store.getters['aliments']
}
But I can see your store is as we call, one-to-rule-them-all, and because you are using Nuxt, you can actually leverage the module store very easy
as your application grows, you will start store everything in just one store file (the ~/store/index.js file), but you can easily have different stores and instead of what you wrote in index.js it can be easier if you had a file called, taken your example
~/store/food.js with
import axios from 'axios'
export const state = () => ({
aliments: {},
})
export const getters = {
aliments (state) {
return state.aliments
}
}
export const mutations = {
SET_ALIMENTS(state, aliments) {
state.aliments = aliments
}
}
export const actions = {
async getListAliments(commit) {
await axios.get('http://localhost:3080/aliments')
.then((response) => {
console.log(response);
commit('SET_ALIMENTS', response.data);
}).catch(error => {
throw new Error(`${error}`);
})
}
}
BTW, remember that, if you're using Nuxt serverMiddleware, this line
axios.get('http://localhost:3080/aliments')...
would simply be
axios.get('/aliments')...
and to call this store, all you need is to prefix with the filename, like:
...mapActions(['food/getListAliments'])
// or
...mapActions({ getListAliments: 'food/getListAliments' })
// or
this.$store.commit('food/getListAliments', payload)
another naming that could help you along the way:
on your action getListAliments you're actually fetching data from the server, I would change the name to fetchAliments
on your getter aliments you're actually returning the list, I would name it getAllAliments
have fun, Nuxt is amazing and you have a great community on Discord as well for the small things :o)
EDIT
also remember that actions are set in methods
so you can do:
...
export default {
methods: {
...mapActions(['getListAliments]),
},
created() {
this.getListAliments()
}
}
and in your Store action, please make sure you write
async getListAliments({ commit }) { ... }
with curly braces as that's a deconstruction of the property passed
async getListAliments(context) {
...
context.commit(...)
}
I want to implement a feature that can register and unregister some modules when components created/destroyed, and my test like this:
// ../store/DMRTest.ts
const DMRTest = {
state: { name: 'DMR test ' },
mutations: {
getName(state) {
state.name += state.name;
}
},
actions: {},
getters: { NN(state) { return state.name; } },
};
export default DMRTest;
// App.vue
import DMRTest from '../store/DMRTest.ts';
// ...
async created() {
// Not works!
this.$store.registerModule('DMRTest', await import('../store/DMRTest.ts'));
// Works
this.$store.registerModule('DMRTest', DMRTest);
console.log(this.$store);
console.log(this.$store.state);
}
When I import the module statically, it will be registered correctly:
But when I use import function, the store registered the module like this:
How could I import the module dynamically?
I should append the default after the dynamic imported, question closed
Just so it is written with an example:
const store = new createStore(rootStoreModule);
const modules = ['moduleA', 'moduleB']
for(const module of modules) {
import(`./components/${ module.toLowerCase() }/store.js`)
.then( (obj) => { store.registerModule(module, obj.default); } )
}
I created a store action that fetch api. When I'm trying to dispatch it from component in created lifecycle hook. I'm getting Cannot read property 'dispatch' of undefined error. I know there are several similar questions but none of them solved this issue.
I tried to dispatch it also in normal method and still get this error.
store.js
import Vue from "vue";
import Vuex from "Vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
categories: []
},
mutations: {
SET_CATEGORIES(state, categories) {
state.categories = categories;
}
},
actions: {
getCategories({ commit }) {
return fetch("https://api.chucknorris.io/jokes/categories")
.then(response => {
return response.json();
})
.then(jsonObj => {
commit("SET_CATEGORIES", jsonObj);
})
.catch(error => {
console.log(error);
});
}
}
});
And this is the component which I try to dispatch in -
<script>
export default {
data() {
return {
joke: "",
categories: [],
selectedCat: ""
};
},
computed: {
disabled() {
if (this.joke) {
return false;
} else {
return true;
}
}
},
methods: {
addToFavs: function() {
this.$emit("pushJoke", this.joke);
this.fetchJoke();
}
},
created() {
this.$store.dispatch('getCategories');
}
};
</script>
What am I doing wrong?
Start by adding
import { mapActions } from 'vuex'
in your script
then add to methods
methods: {
...mapActions([
'getCategories'
])
.
.
}
and alter your created method to
created() {
this.getCategories()
}
Furthermore, you might want to create a vuex action to replace that this.$emit("pushJoke", this.joke); line that you have, and map that in a similar way that you have mapped getCategories
That's because you missed to add your vuex store option to the root instance of Vue. To solve that import your store and attach it to your vue instance.
import { store } from '.store'
const app = new Vue({
store
})
sorry about my english, How can i in other js files use vuex.store in nuxt project
in store
export const state = () => ({
token: 'test',
name: '',
avatar: ''
}),
export const mutations = {
SET_TOKEN: (state, token) => {
state.token = token
}
},
export const getters = {
token: state => {
return state.token
}
}
in test.js
export function() => {
//how can i updata vuex token?
}
export function() => {
//how can i getter vuex token?
}
export default ({ app, store, route, redirect }) => {
some code
}
it can't work
Wanted to know if it's good practice to do that and what would be the best way to do that?
A basic implementation would look like this
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
computed: {
// you only need State OR Getter here not both!!! You don't need a
// getter for just returning a simple state
...mapState('yourStoreName', ['token'])
...mapGetters('yourStoreName', ['token']),
},
methods: {
methodThatNeedsToChangeState (){
this.setToken('newToken')
},
...mapActions('yourStoreName', ['setToken']),
}
}
In your store you need actions though, you don't call mutations directly! Because Mutations can't be asynchronous.
export const actions = {
setToken: (context, token) => {
context.commit(SET_TOKEN, token)
}
},
I would highly recommend you to study the Vuex documentation in more detail.
https://vuex.vuejs.org/guide/