Since Vue.js 3.x, you no longer need to use Vuex to share a centralized state with all your application's components.
If you have been using Vue.js before 3.x you are probably familiar with Vuex. It allows you to have a centralized state that is shared across all your application components. If you have ever found yourself in situations where you are passing data/props between components and things are getting complicated, a centralized state is the answer.
Flux libraries are like glasses: you’ll know when you need them.
Since Vue.js 3.x reactive and computed are exported directly from the library and can be used outside of components. This is the exact same functionality that you are using when you have data or computed inside of one of your Vue.js components.
import { reactive, computed } from 'vue';This is great because it means that we can create our own reactive data, and even computed properties outside of Vue components, in plain Javascript files!
import { reactive, computed } from "vue";
const state = reactive({
hobby: "Hike",
fruit: "Apple",
fruitOptions: ["Banana", "Apple", "Pear", "Watermelon"],
description: computed(() => {
return `I like eating ${state.fruit}s & ${state.hobby}`;
}),
});
export default state;Here we have an Object with properties, which is wrapped in reactive this gives Vue the ability to trigger change, and re-render your components.
We are also wrapping a function in computed which gives us a computed property based on the the other fields in the state.
It is important to note, that we invoke the reactive function, and then export the resulting state, otherwise we would generate a new state each time we imported into a component.
Great, we have a reactive store, but how do we leverage this in our components, and will they all stay in sync?
<template>
<main class="container">
<article>
<header>
Your description: <code>{{ state.description }}</code>
</header>
<survey-form />
<footer>
<results />
</footer>
</article>
</main>
</template>
<script>
import Results from "./Results.vue";
import SurveyForm from "./SurveyForm.vue";
import state from "./state.js";
export default {
components: { SurveyForm, Results },
data() {
return { state };
},
};
</script>It's as simple as importing the state, and referencing it in your component's data method so it can be accessed in your template.
You can even v-model items in your store the same as you would with any data property in your component.
<template>
<form>
<label>
Favorite Hobby?
<input placeholder="Favorite Hobby" v-model="state.hobby" />
</label>
<label>
Favorite Fruit?
<select v-model="state.fruit">
<option v-for="fruit in state.fruitOptions" :key="fruit">{{ fruit }}</option>
</select>
</label>
</form>
</template>
<script>
import state from "./state.js";
export default {
name: "SurveyForm",
data() {
return { state };
},
};
</script>