Bird
Raised Fist0
Vueframework~10 mins

Creating a Pinia store in Vue - Visual Walkthrough

Choose your learning style10 modes available
Concept Flow - Creating a Pinia store
Import createPinia
↓
Create Pinia instance
↓
Define store with defineStore
↓
Use store in component
↓
Access state, actions
↓
Update state via actions
↓
Component reacts to state changes
This flow shows how to create a Pinia store, use it in a Vue component, and update state reactively.
Execution Sample
Vue
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: { increment() { this.count++ } }
})
Defines a Pinia store named 'counter' with a count state and an increment action.
Execution Table
StepActionState BeforeState AfterOutput/Effect
1Call defineStore to create 'counter' storeNo storeStore created with count=0Store ready to use
2Component calls useCounterStore()Store exists with count=0Store instance with count=0Component gets store instance
3Call increment() actioncount=0count=1State updated, component re-renders
4Call increment() action againcount=1count=2State updated, component re-renders
5Component reads countcount=2count=2Component shows count=2
💡 Execution stops after state updates and component reflects latest count
Variable Tracker
VariableStartAfter Step 3After Step 4Final
count0122
Key Moments - 3 Insights
Why does the component update when count changes?
Because Pinia makes the state reactive, so when increment() changes count, the component automatically re-renders (see steps 3 and 4 in execution_table).
What does defineStore('counter', {...}) do?
It creates a reusable store definition named 'counter' that holds state and actions, ready to be used in components (step 1).
Why do we call useCounterStore() inside the component?
To get the store instance with its reactive state and actions, so the component can read and update the store (step 2).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the value of count after step 3?
A0
B2
C1
DUndefined
💡 Hint
Check the 'State After' column for step 3 in the execution_table.
At which step does the component get the store instance?
AStep 1
BStep 2
CStep 3
DStep 5
💡 Hint
Look for when useCounterStore() is called in the execution_table.
If increment() was never called, what would count be at step 5?
A0
B1
C2
DUndefined
💡 Hint
Refer to variable_tracker to see count changes after increment calls.
Concept Snapshot
Creating a Pinia store:
- Import defineStore from 'pinia'
- Use defineStore('name', { state, actions }) to define store
- Call useStore() in components to access store
- State is reactive; updating state triggers component updates
- Actions modify state safely and clearly
Full Transcript
This visual execution shows how to create a Pinia store in Vue. First, defineStore creates a store named 'counter' with a count state starting at 0 and an increment action. When a component calls useCounterStore(), it gets the store instance. Calling increment() increases count by 1 each time, and the component updates automatically because Pinia makes state reactive. The execution table tracks each step, showing state before and after actions. The variable tracker shows how count changes from 0 to 2 after two increments. Key moments clarify why components update and how the store is used. The quiz tests understanding of state changes and store usage. This helps beginners see how Pinia manages state simply and reactively.

Practice

(1/5)
1. What is the main purpose of creating a Pinia store in a Vue application?
easy
A. To handle routing between pages
B. To style components with CSS
C. To hold and manage shared state across components
D. To write HTML templates

Solution

  1. Step 1: Understand what Pinia stores do

    Pinia stores are designed to hold shared data (state) that multiple components can access and update.
  2. Step 2: Identify the correct purpose

    Styling, routing, and HTML templates are handled by other parts of Vue or related libraries, not Pinia stores.
  3. Final Answer:

    To hold and manage shared state across components -> Option C
  4. Quick Check:

    Pinia stores = shared state management [OK]
Hint: Pinia stores manage shared data, not styles or routes [OK]
Common Mistakes:
  • Confusing Pinia with CSS or routing libraries
  • Thinking Pinia handles templates
  • Assuming Pinia is for styling
2. Which of the following is the correct way to define a Pinia store named 'user' using defineStore?
easy
A. const userStore = createStore('user', { state: () => ({ name: '' }) })
B. const userStore = defineStore('user', { data: () => ({ name: '' }) })
C. const useUserStore = defineStore({ name: 'user', state: () => ({ name: '' }) })
D. const useUserStore = defineStore('user', { state: () => ({ name: '' }) })

Solution

  1. Step 1: Recall the correct syntax for defineStore

    The correct syntax is defineStore('storeId', { state: () => ({ ... }) }) and assign it to a function named useStoreId.
  2. Step 2: Check each option

    const useUserStore = defineStore('user', { state: () => ({ name: '' }) }) uses defineStore with correct parameters and naming. const userStore = createStore('user', { state: () => ({ name: '' }) }) uses createStore which is incorrect. const useUserStore = defineStore({ name: 'user', state: () => ({ name: '' }) }) passes an object without storeId string first. const userStore = defineStore('user', { data: () => ({ name: '' }) }) uses 'data' instead of 'state'.
  3. Final Answer:

    const useUserStore = defineStore('user', { state: () => ({ name: '' }) }) -> Option D
  4. Quick Check:

    defineStore('id', { state }) syntax = const useUserStore = defineStore('user', { state: () => ({ name: '' }) }) [OK]
Hint: Use defineStore('id', { state: () => ({}) }) with useId naming [OK]
Common Mistakes:
  • Using createStore instead of defineStore
  • Passing object without store id string
  • Using 'data' instead of 'state' key
3. Given this Pinia store definition:
const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  actions: {
    increment() { this.count++ }
  }
})

What will be the value of count after calling increment() twice?
medium
A. 0
B. 2
C. undefined
D. 1

Solution

  1. Step 1: Understand initial state and action

    The initial count is 0. The increment action increases count by 1 each time it is called.
  2. Step 2: Calculate count after two increments

    Calling increment() twice adds 1 + 1 to count, so count becomes 2.
  3. Final Answer:

    2 -> Option B
  4. Quick Check:

    0 + 1 + 1 = 2 [OK]
Hint: Each increment adds 1; two calls add 2 total [OK]
Common Mistakes:
  • Forgetting to call increment twice
  • Assuming count resets each call
  • Confusing initial value with updated value
4. Identify the error in this Pinia store code:
const useTodoStore = defineStore('todo', {
  state: () => ({ todos: [] }),
  actions: {
    addTodo(todo) {
      this.todos.push(todo)
    }
  }
})

// Usage
const todoStore = useTodoStore()
todoStore.addTodo('Learn Pinia')
medium
A. Missing import of defineStore from 'pinia'
B. State should be an object, not a function
C. Actions cannot modify state directly
D. Store id must be an object, not a string

Solution

  1. Step 1: Check the store definition syntax

    The store is correctly defined with state as a function returning an object, and actions modifying state properly.
  2. Step 2: Identify missing parts

    The code snippet does not show importing defineStore from 'pinia', which is required to use defineStore.
  3. Final Answer:

    Missing import of defineStore from 'pinia' -> Option A
  4. Quick Check:

    Always import defineStore before use [OK]
Hint: Always import defineStore from 'pinia' before defining stores [OK]
Common Mistakes:
  • Forgetting to import defineStore
  • Thinking state must be an object, not a function
  • Believing actions cannot modify state
5. You want to create a Pinia store that keeps track of a user's profile with a name and age, and includes a getter to check if the user is an adult (age >= 18). Which of the following is the correct way to define this store?
hard
A. const useUserStore = defineStore('user', { state: () => ({ name: '', age: 0 }), getters: { isAdult() { return this.age >= 18 } } })
B. const useUserStore = defineStore('user', { state: { name: '', age: 0 }, getters: { isAdult() { return this.age >= 18 } } })
C. const useUserStore = defineStore('user', { state: { name: '', age: 0 }, getters: { isAdult: (state) => state.age >= 18 } })
D. const useUserStore = defineStore('user', { state: () => ({ name: '', age: 0 }), actions: { isAdult() { return this.age >= 18 } } })

Solution

  1. Step 1: Check state definition

    State must be a function returning an object. Options C and D do this correctly; A and B do not.
  2. Step 2: Check getter syntax

    Getters can be defined as functions using 'this' to access state. const useUserStore = defineStore('user', { state: () => ({ name: '', age: 0 }), getters: { isAdult() { return this.age >= 18 } } }) uses this correctly. const useUserStore = defineStore('user', { state: { name: '', age: 0 }, getters: { isAdult: (state) => state.age >= 18 } }) has incorrect state. const useUserStore = defineStore('user', { state: { name: '', age: 0 }, getters: { isAdult() { return this.age >= 18 } } }) has incorrect state. const useUserStore = defineStore('user', { state: () => ({ name: '', age: 0 }), actions: { isAdult() { return this.age >= 18 } } }) puts isAdult in actions, which is wrong because isAdult is a computed property, not an action.
  3. Final Answer:

    const useUserStore = defineStore('user', { state: () => ({ name: '', age: 0 }), getters: { isAdult() { return this.age >= 18 } } }) -> Option A
  4. Quick Check:

    State as function + getter with this = const useUserStore = defineStore('user', { state: () => ({ name: '', age: 0 }), getters: { isAdult() { return this.age >= 18 } } }) [OK]
Hint: State is function; getters use this for reactive access [OK]
Common Mistakes:
  • Defining state as object instead of function
  • Putting computed logic inside actions
  • Using arrow function getters with state parameter incorrectly
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard