Vue JS State Management with Pinia/Vuex 1 — Questions and Answers
Question 1: What is the recommended state management library for Vue 3?
- Pinia (Correct answer)
- Vuex 4
- Redux
- MobX
Correct answer: Pinia
Pinia is the official state management library recommended by the Vue team for Vue 3. It offers a simpler API, better TypeScript support, and Devtools integration.
Pinia was created by a Vue core team member and became the official recommended state management solution for Vue 3, effectively replacing Vuex. Pinia has a much simpler API: no mutations, no nested modules, direct state mutations in actions, and first-class TypeScript support. It integrates with Vue Devtools for time-travel debugging and works seamlessly with the Composition API. Vuex 4 still works with Vue 3 but is in maintenance mode only.
Question 2: How do you define a store in Pinia using the Setup Store syntax?
- defineStore('id', () => { const count = ref(0); return { count } }) (Correct answer)
- createStore({ state: () => ({ count: 0 }) })
- new Pinia({ id: 'myStore', state: { count: 0 } })
- useStore({ id: 'myStore', state: ref(0) })
Correct answer: defineStore('id', () => { const count = ref(0); return { count } })
`defineStore` with a setup function (returning reactive state, computed, and actions) is the Composition API-style store definition in Pinia.
Pinia offers two store definition styles. The Options Store mirrors Vuex: `defineStore('id', { state: () => ({}), getters: {}, actions: {} })`. The Setup Store uses a function like `<script setup>`: `defineStore('id', () => { const count = ref(0); const double = computed(() => count.value * 2); function increment() { count.value++ } return { count, double, increment } })`. In the setup function, `ref` and `reactive` become state, `computed` become getters, and plain functions become actions.
Question 3: In Vuex 4, what is the only way to synchronously change state?
- Mutations (Correct answer)
- Actions
- Getters
- Plugins
Correct answer: Mutations
In Vuex, mutations are the only mechanism for synchronous state changes. Actions can be asynchronous and must commit mutations to change state.
Vuex enforces that state mutations must be synchronous and go through a dedicated `mutations` object. This rule exists so Vuex can create snapshots of state before and after every mutation for Devtools time-travel debugging. Actions are for async operations (API calls, etc.) and must ultimately call `commit('mutationName')` to change state. In contrast, Pinia eliminated mutations entirely — Pinia actions can directly modify `this.propertyName` (Options Store) or the `ref` value (Setup Store), async or not.
Question 4: How do you access a Pinia store's state and actions inside a Vue 3 component?
- const store = useMyStore(); store.count; store.increment() (Correct answer)
- const store = new MyStore(); store.state.count
- inject('myStore').count
- this.$store.state.count
Correct answer: const store = useMyStore(); store.count; store.increment()
Pinia stores are used by calling the composable returned by `defineStore`. The result directly exposes state, getters, and actions as flat properties.
After defining a store with `export const useCounterStore = defineStore(...)`, you use it in a component by calling `const store = useCounterStore()` inside `<script setup>` or `setup()`. The store object directly exposes all state, getters, and actions: `store.count`, `store.doubleCount`, `store.increment()`. To keep reactivity when destructuring, you must use `storeToRefs(store)` for state and getters: `const { count } = storeToRefs(store)`. Actions can be destructured normally.
Question 5: What does `storeToRefs` do in Pinia?
- Destructures store state and getters while preserving their reactivity (Correct answer)
- Converts a store to a Vue ref
- Creates a copy of the store
- Syncs two stores together
Correct answer: Destructures store state and getters while preserving their reactivity
`storeToRefs` extracts reactive refs from a Pinia store so you can destructure state/getters without losing reactivity. Actions should not be included.
When you destructure a Pinia store directly — `const { count } = useCounterStore()` — the extracted value loses reactivity because it's just the raw value at that moment. `storeToRefs(store)` wraps each state property and getter in a `ref`, so destructured values stay reactive and update when the store changes. Actions are plain functions and don't need this treatment. Example: `const { count, doubleCount } = storeToRefs(store); const { increment } = store;`.
Question 6: Which Vuex 4 feature allows you to organize state into separate namespaced modules?
- Namespaced modules with `namespaced: true` (Correct answer)
- Pinia stores
- Vuex plugins
- Store composition
Correct answer: Namespaced modules with `namespaced: true`
Vuex modules with `namespaced: true` scope their mutations, actions, and getters under a namespace prefix, preventing naming conflicts in large applications.
In Vuex, you can split the store into modules: `store.registerModule('cart', cartModule)` or list them in `modules: { cart: cartModule }`. By default, module actions, mutations, and getters are registered in the global namespace. Setting `namespaced: true` in a module means they are accessed as `store.dispatch('cart/addItem')` and `store.getters['cart/totalPrice']`. Nested modules also support namespacing. In Pinia, each store is inherently namespaced by its ID, making the setup much simpler.
What is the recommended state management library for Vue 3?