I have a vue3 application and try to get vuex 4 up and running.
This is my main.js:
import { createApp } from 'vue'
import App from './App.vue'
import 'leaflet/dist/leaflet.css';
import { Icon } from 'leaflet';
import mitt from 'mitt';
import store from './store';
/* Theme variables */
import './theme/variables.css';
delete Icon.Default.prototype._getIconUrl;
Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png'),
});
export const eventHub = mitt();
const app = createApp(App)
.use(IonicVue)
.use(store);
app.mount('#app');
My store.js:
import { createStore } from 'vuex'
export const store = createStore({
state() {
return {
aantalBankjes: 0
}
},
mutations: {
vernieuwAantalBankjes(state, n) {
// mutate state
state.aantalBankjes = n;
console.log("Store: vernieuwAantalBankjes");
console.log(n);
}
},
getters: {
getAantalBankjes(state) {
return state.aantalBankjes;
}
}
})
I then want to use the vuex store in a component. The most important code of this component:
<template>
<div id="myMap" style="width: 100%; height: 100%"></div>
</template>
<script>
import L from "leaflet";
import { eventHub } from "../main";
import { Geolocation } from "#capacitor/geolocation";
import icons from "../mixins/icons.js";
const axios = require("axios");
export default {
methods: {
getBankjes() {
let vertices = this.calculateRetrievalArea(this.map.getCenter());
axios
.get(
"https://www.evenuitrusten.nl/api/area?lngLow=" +
vertices.lngLow +
"&lngHigh=" +
vertices.lngHigh +
"&latLow=" +
vertices.latLow +
"&latHigh=" +
vertices.latHigh +
"&number=200"
)
// .get("https://www.evenuitrusten.nl/api/area/test")
.then((response) => {
this.bankjes = response.data;
console.log("Bankjes: axios has returned data");
this.placeMarkers(this.bankjes);
this.aantalBankjes=this.bankjes.length;
console.log("Before commit");
this.$store.commit('vernieuwAantalBankjes',this.aantalBankjes);
console.log("After commit");
return this.bankjes;
})
.catch(function (error) {
// handle error
console.log("bankjes:" + error.response);
});
},
I run into a problem at this.$store.commit. I never reach the line " console.log("After commit");". Instead the catch-function is hit. There is no error message in the console.
What am I doing wrong?
Kind regards,
Hubert
I am new in Vue... but i read that "Mutations Must Be Synchronous"... and you call it in asynchronous code. So, create an action witch will call the mutation and you call the action.
actions: {
act_vernieuwAantalBankjes({commit}, data) {
commit('vernieuwAantalBankjes',data);
}
}
and call the action in the asynchronous code:
this.$store.dispatch('act_vernieuwAantalBankjes',this.aantalBankjes);
Related
I have a UserStore which contains some information about the current user. This store also is responsible for loggin in and out.
In order to make the getters available I map the getters to my computed attribute within my Vue component.
Unfortunately I get an error saying that it cannot access useUserStore before initilization.
This is my component:
<template>
//...
</template>
<script>
import {mapState} from "pinia"
import {useUserStore} from "../../stores/UserStore.js";
import LoginForm from "../../components/forms/LoginForm.vue";
export default {
name: "Login",
components: {LoginForm},
computed: {
...mapState(useUserStore, ["user", "isAuthenticated"]) //commenting this out makes it work
}
}
</script>
This is my store:
import { defineStore } from 'pinia'
import {gameApi} from "../plugins/gameApi.js"
import {router} from "../router.js";
export const useUserStore = defineStore("UserStore", {
persist: true,
state: () => ({
authenticated: false,
_user: null
}),
getters: {
user: (state) => state._user,
isAuthenticated: (state) => state.authenticated
},
actions: {
async checkLoginState() {
// ...
},
async loginUser(fields) {
// ...
},
async logutUser() {
// ...
}
}
})
And my main.js
import {createApp} from 'vue'
import App from './App.vue'
import gameApi from './plugins/gameApi'
import {router} from './router.js'
import store from "./stores/index.js";
createApp(App)
.use(store)
.use(router)
.use(gameApi)
.mount('#app')
And finally my store configuration:
import {createPinia} from "pinia"
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import {useUserStore} from "./UserStore.js";
const piniaStore = createPinia()
piniaStore.use(piniaPluginPersistedstate)
export default {
install: (app, options) => {
app.use(piniaStore)
const userStore = useUserStore()
const gameStore = useGameStore()
}
}
I wasn't able to initialize the store using the "old" way comparable with Vuex. Instead I had to make use of the setup() function Pinia Docu:
<script>
import {useUserStore} from "../../stores/UserStore.js";
export default {
name: "RegisterForm",
setup() {
// initialize the store
const userStore = useUserStore()
return {userStore}
},
data() {
return {
// ...
}
},
methods: {
checkLoginState() {
this.userStore.checkLoginState()
}
}
}
</script>
is it possible to use the pinia store in a component as an element?
try doing it this way but i get the following error in developer console
index.8ec3cfca.js:1 TypeError: Cannot read properties of undefined (reading '_s')
pinia store
import { UsuarioInternet } from "../../models/UsuariosInternet.model"
import { defineStore } from "pinia";
export const useFAUsuarioInternet = defineStore("useFAUsuarioInternet",{
state:() => ({
items: <UsuarioInternet[]>([])
}),
getters:{
listaUsuario(state){
return state.items;
}
},
actions:{
createNewUser(item :UsuarioInternet){
if(!item) return;
this.items.push(item);
},
findIndexById(id: number){
return this.items.findIndex((item) => item.id == id);
}
}
})
component
<template>
<p>
setsetsetestset
</p>
</template>
<script lang="ts" setup >
import { ref , onMounted, computed} from 'vue';
import { useFAUsuarioInternet } from "../stores/general/useFAUsuariosInternet";
import { UsuarioInternet } from "../models/UsuariosInternet.model";
let Usuario = ref<UsuarioInternet>(new UsuarioInternet);
//mounted
onMounted(() => {
});
const mainStore = useFAUsuarioInternet();
//call action
const saveUser = () => {
mainStore.createNewUser(Usuario.value);
}
//getters
const lista = computed(() => mainStore.listaUsuario)
</script>
Main.ts
import { createApp, defineCustomElement } from 'vue'
import UsuariosInternet from './pages/general/UsuariosInternet.ce.vue'
import homeTest from './components/homeTest.ce.vue'
const element = defineCustomElement(UsuariosInternet);
customElements.define("usuarios-internet", element);
const element2 = defineCustomElement(homeTest);
customElements.define('home-test', element2);
Here's the main.ts you want:
import { defineCustomElement } from "vue";
import { createPinia, setActivePinia } from "pinia";
import UsuariosInternet from "./pages/general/UsuariosInternet.ce.vue";
import homeTest from "./components/homeTest.ce.vue";
// Here you create a standalone pinia
setActivePinia(createPinia());
const element = defineCustomElement(UsuariosInternet);
customElements.define("usuarios-internet", element);
const element2 = defineCustomElement(homeTest);
customElements.define("home-test", element2);
This will create a global store for all your components.
See: https://github.com/vuejs/pinia/discussions/1085#discussioncomment-2219587
I am trying to get the state variable on components which is set by the nuxtServerInit Axios by get method.
store/state.js
export default () => ({
siteData: null
})
store/mutations.js
import initialState from './state'
const mutations = {
SET_SITE_DATA (state, value) {
state.siteData = {
site_title: value.site_title,
logo: value.logo
}
}
}
export default {
...mutations
}
store/getters.js
const getters = {
siteDetails: state => state.siteData
}
export default {
...getters
}
store/actions.js
const actions = {
async nuxtServerInit ({ commit, dispatch }, ctx) {
try {
const host = ctx.req.headers.host
const res = await this.$axios.post('/vendors/oauth/domain/configuration', { domain: host })
commit('SET_SITE_DATA', res.data.data.site_data)
} catch (err) {
console.error(err)
}
},
export default {
...actions
}
}
store/index.js
import Vuex from 'vuex'
import mutations from './mutations'
import getters from './getters'
import actions from './actions'
import state from './state'
const store = () => {
return new Vuex.Store({
state,
getters,
mutations,
actions
})
}
export default store
Here I set SET_SITE_DATA mutation which set siteData state.
components/Header.vue
<template>
<section class="header sticky-top">
<client-only>
{{ siteDetails }}
{{ $store.getters }}
{ logo }}
</client-only>
</section>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['siteDetails']),
logo () {
console.log(this.$store.state.siteData)
return this.$store.state.siteData
}
}
}
</script>
Console
I don't know what is happening here. You can see I have consoled the values. So when I reload the page I can get the values but after few seconds all values reset to the null. I want to set those values globally so can access them all over the site. I don't want to call API every time a page changes so I used nuxtServerInit so can set values globally when the page reloads once and can access them.
Hello developers I'm working with Ionic and Vue+Vuex in this app, but eventually, I can't access my state from my getters for some reason.
As usually the management state is settled for that purpose with actions getters, mutations, and state.
import { createStore } from "vuex";
const urlLogin = "http://localhost:3006/auth";
const urlUser = "http://localhost:3006/user";
const store = createStore({
state() {
return {
userRegisteredState: false,
allUsersState: [],
};
},
mutations: {
commit_get_all_users(state, payload) {
console.log(payload);
return (state.allUsersState = payload);
},
},
getters: {
getterGetAllUsers(state) {
console.log(state);//checking all state (See image )
console.log(state.allUsersState)//checking only the item I want to consume from state (See image )
return state.allUsersState;
},
},
actions: {
//=================================================================
//============================================================
async getAllUsers({ commit }) {
fetch(`${urlUser}/get/all/users`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "http://localhost:8100",
},
})
.then((result) => {
return result.json();
})
.then((result) => {
console.log(result);
commit("commit_get_all_users", result);
})
.catch((error) => {
console.log(error);
error;
});
},
},
});
export default store;
then on my component , in this case that one referring to get all users I set this logic:
<template>
...some tags...
</template>
<script>
import { mapActions, mapGetters } from "vuex";
export default {
name: "AllUsersComponent",
data() {
return {
allUsers: [],
};
},
methods: {
...mapActions(["getAllUsers"]),
getAllUsersFront() {
this.$store.dispatch("getAllUsers");
},
...some methods....
},
computed: {
...mapGetters(["getterGetAllUsers"]),
getterGetAllUsersFunction() {
console.log(this.$store.getters.getterGetAllUsers);
return this.$store.getters.getterGetAllUsers;
},
},
async mounted() {
this.getAllUsersFront();
},
created() {
this.getAllUsersFront();
this.getterGetAllUsersFunction;
console.log(this.getterGetAllUsersFunction);
},
watch: {},
};
</script>
<style>
</style>
On my main.js file store is imported according to IONC in this way
import { createApp } from "vue";
import './gapi.js'
import App from "./App.vue";
import router from "./router";
import store from "./store/index"; //importando vuex
import loginComponentTag from "./components/Login";
import allUsersComponentTag from "./components/all-users-component"
// import GoogleSignInButton from 'vue-google-signin-button-directive'
import { IonicVue } from "#ionic/vue";
/* Core CSS required for Ionic components to work properly */
import "#ionic/vue/css/core.css";
/* Basic CSS for apps built with Ionic */
import "#ionic/vue/css/normalize.css";
import "#ionic/vue/css/structure.css";
import "#ionic/vue/css/typography.css";
/* Optional CSS utils that can be commented out */
import "#ionic/vue/css/padding.css";
import "#ionic/vue/css/float-elements.css";
import "#ionic/vue/css/text-alignment.css";
import "#ionic/vue/css/text-transformation.css";
import "#ionic/vue/css/flex-utils.css";
import "#ionic/vue/css/display.css";
/* Theme variables */
import "./theme/variables.css";
const app = createApp(App)
.use(IonicVue)
.use(store)
.use(router)
app.component("LoginComponent", loginComponentTag);
app.component("AllUsersComponent",allUsersComponentTag)
router.isReady().then(() => {
app.mount("#app");
});
And my vue.config.js is settled in this way:
module.exports = {
devServer: {
proxy: "http://localhost:8100",
},
};
I checked my logs and eventually.
Literally, the situation is that despite having my state populated with data, unless I retrieve the whole state, I can't retrieve a particular item from it, cause the response is nothing.
Is there any configuration I'm omitting in this process I need to have in mind?
I am trying to use Vuex Store in my layout but can't figure out how to make it work.
Here is what I am doing:
store/sources.ts
import { VuexModule, Module, Mutation, Action } from 'vuex-module-decorators'
import { store } from '#/store'
import axios from 'axios'
const { sourcesEndpoint } = process.env
interface Source {
id: String
}
#Module({
name: 'sources',
namespaced: true,
stateFactory: true,
dynamic: true,
store,
})
export default class Sources extends VuexModule {
private _sources: Source[] = []
get sources(): Source[] {
return this._sources
}
#Mutation
updateSources(sources: Source[]) {
this._sources = sources
}
#Action({ commit: 'updateSources' })
async fetchSources() {
// eslint-disable-next-line no-console
console.log(`!!! ${sourcesEndpoint} !!!`)
return sourcesEndpoint ? await axios.get(sourcesEndpoint) : []
}
}
store/index.ts
import { Store } from 'vuex'
export const store = new Store({})
layouts/default.vue
<script>
import { getModule } from 'vuex-module-decorators'
import Sources from '#/store/sources'
export default {
fetch() {
const sourcesModule = getModule(Sources, this.$store)
sourcesModule.fetchSources()
},
fetchOnServer: false,
}
</script>
And the error I get:
[vuex] must call Vue.use(Vuex) before creating a store instance.
You need to add Vue.use(Vuex), also, you are not including your module in the main store
import { Store } from 'vuex'
import { Sources } from './sources'
Vue.use(Vuex)
export const store = new Store({
modules: {
Sources
}
})