Doel van deze store

De auth store houdt bij wie er is ingelogd. Hij wordt door je hele app gebruikt:

  • De header toont "Hallo, Anna" als iemand is ingelogd
  • Een "Profiel" link verschijnt alleen voor ingelogde gebruikers
  • Beveiligde routes checken of de gebruiker mag passeren
  • De login & register pagina's zetten de gebruiker erin

Volgorde: deze pagina bouwt voort op Pinia en localStorage. Lees die eerst als je nog niet bekend bent met die concepten.

De auth store

Maak src/stores/auth.js:

// src/stores/auth.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useAuthStore = defineStore('auth', () => {
  // State
  const user = ref(null)

  // Computed
  const isLoggedIn = computed(() => user.value !== null)

  // Actions
  const login = (userData) => {
    user.value = userData
  }

  const logout = () => {
    user.value = null
  }

  return { user, isLoggedIn, login, logout }
})

Drie ingrediënten:

  • user — null = niet ingelogd, object = ingelogd
  • isLoggedIn — handige computed boolean
  • login & logout — twee acties die user aanpassen

Persisteren in localStorage

Zonder persistence wordt de gebruiker uitgelogd bij elke refresh. Voeg twee dingen toe:

  1. Bij setup: lees de gebruiker uit localStorage (als die er is)
  2. Bij login/logout: schrijf de wijziging naar localStorage
// src/stores/auth.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useAuthStore = defineStore('auth', () => {
  // 1. Lees opgeslagen user (of null)
  const stored = localStorage.getItem('user')
  const user = ref(stored ? JSON.parse(stored) : null)

  const isLoggedIn = computed(() => user.value !== null)

  const login = (userData) => {
    user.value = userData
    // 2a. Schrijf bij login
    localStorage.setItem('user', JSON.stringify(userData))
  }

  const logout = () => {
    user.value = null
    // 2b. Wis bij logout
    localStorage.removeItem('user')
  }

  return { user, isLoggedIn, login, logout }
})

Wat heb je nu? De gebruiker blijft ingelogd na een refresh. Logt uit → de localStorage wordt geleegd. Eén bron van waarheid.

Voor demo-projecten is dit prima. In productie sla je het token (niet het complete user-object) op, en bij voorkeur in een HTTP-only cookie om XSS-aanvallen te voorkomen. Maar dat is een onderwerp voor later.

Gebruiken in components

Header met conditionele content

<!-- src/components/Header.vue -->
<script setup>
import { useAuthStore } from '@/stores/auth'

const auth = useAuthStore()
</script>

<template>
  <header>
    <RouterLink to="/">Home</RouterLink>

    <!-- Niet ingelogd -->
    <template v-if="!auth.isLoggedIn">
      <RouterLink to="/login">Inloggen</RouterLink>
      <RouterLink to="/register">Registreren</RouterLink>
    </template>

    <!-- Wel ingelogd -->
    <template v-else>
      <span>Hallo, {{ auth.user.name }}</span>
      <button @click="auth.logout">Uitloggen</button>
    </template>
  </header>
</template>

Logout knop ergens anders

<script setup>
import { useAuthStore } from '@/stores/auth'
import { useRouter } from 'vue-router'

const auth = useAuthStore()
const router = useRouter()

const handleLogout = () => {
  auth.logout()
  router.push('/login')
}
</script>

<template>
  <button @click="handleLogout">Uitloggen</button>
</template>

De volgende pagina's gebruiken deze store:

Belangrijke Regels

  • Eén auth store voor de hele app — niet meerdere
  • State + actions samen in de store, niet verspreiden
  • Persisteren met localStorage in login/logout
  • Bij setup lezen in de ref-initialisatie
  • Components mogen auth.user lezen, maar muteren alleen via login/logout

Veelgemaakte Fouten

Fout — localStorage vergeten bij logout:

const logout = () => {
  user.value = null
  // ❌ localStorage blijft staan — refresh logt user weer in
}

Goed:

const logout = () => {
  user.value = null
  localStorage.removeItem('user')   // ✅
}

Fout — JSON.parse op een null-waarde zonder check:

const user = ref(JSON.parse(localStorage.getItem('user')))
// ❌ als de key niet bestaat: JSON.parse(null) → null (toevallig OK)
// Maar bij beschadigde data → crash

Goed:

const stored = localStorage.getItem('user')
const user = ref(stored ? JSON.parse(stored) : null)   // ✅