Đăng nhập

BÀI 22: QUẢN LÝ TRẠNG THÁI NGƯỜI DÙNG VỚI useState() & useAuth()

Cùng tiếp tục với Bài 22 – Quản lý trạng thái người dùng với useState() và composables trong NuxtJS. Đây là phần quan trọng để làm ứng dụng có trạng thái đăng nhập rõ ràng, dễ dùng, tái sử dụng nhiều lần ở mọi nơi trong project.


1. Vấn đề: dùng useCookie() rải rác

Nếu bạn dùng useCookie() ở nhiều nơi để đọc auth_token, user, rolecode rối, khó bảo trì.

Giải pháp: Tạo một composable useAuth() để tập trung xử lý user login.


2. Sử dụng useState() – tạo state dùng lại toàn app

Trong Nuxt, useState() là cách tạo biến global, reactive và auto SSR/CSR.

Ví dụ:

const user = useState('user', () => null)
const token = useState('token', () => null)

→ Bạn có thể truy cập từ bất kỳ component nào.


3. Tạo composable useAuth()

Tạo file: composables/useAuth.ts

export const useAuth = () => {
  const user = useState('user', () => null)
  const token = useState('token', () => null)
  const role = useState('role', () => null)

  const login = async (email: string, password: string) => {
    try {
      const res = await $fetch('/api/login', {
        method: 'POST',
        body: { email, password }
      })

      token.value = res.token
      user.value = res.user
      role.value = res.user?.role || 'user'

      // Lưu vào cookie
      useCookie('auth_token').value = res.token
      useCookie('user').value = res.user
      useCookie('user_role').value = res.user.role
    } catch (err) {
      throw new Error('Đăng nhập thất bại')
    }
  }

  const logout = () => {
    token.value = null
    user.value = null
    role.value = null

    useCookie('auth_token').value = null
    useCookie('user').value = null
    useCookie('user_role').value = null
  }

  return { user, token, role, login, logout }
}

4. Dùng useAuth() trong login page

<script setup>
const email = ref('')
const password = ref('')
const error = ref('')

const { login } = useAuth()
const router = useRouter()

async function submit() {
  try {
    await login(email.value, password.value)
    router.push('/dashboard')
  } catch (e) {
    error.value = e.message
  }
}
</script>

5. Dùng useAuth() ở header, layout, component

Ví dụ trong components/Header.vue:

<script setup>
const { user, logout } = useAuth()
</script>

<template>
  <div>
    <span v-if="user">Xin chào, {{ user.name }}</span>
    <button v-if="user" @click="logout">Đăng xuất</button>
  </div>
</template>

→ Khi logout, toàn bộ giao diện tự reactive theo.


6. Đồng bộ cookie vào state khi trang load

Tạo file plugins/init-auth.ts:

export default defineNuxtPlugin(() => {
  const token = useCookie('auth_token').value
  const user = useCookie('user').value
  const role = useCookie('user_role').value

  useState('token', () => token)
  useState('user', () => user)
  useState('role', () => role)
})

→ Khi user F5, Nuxt đọc cookie và phục hồi state → không bị mất trạng thái login.


7. Gợi ý mở rộng

  • isLoggedIn = computed(() => !!token.value)
  • isAdmin = computed(() => role.value === 'admin')
  • isEditor = computed(() => ['admin', 'editor'].includes(role.value))

Bạn có thể thêm vào useAuth() để sử dụng tiện lợi.


Bạn đã học được

  • Tạo state toàn cục bằng useState()
  • Gom login/logout vào composable useAuth()
  • Dùng lại useAuth() ở bất kỳ đâu trong app
  • Tự đồng bộ cookie vào state bằng plugin
  • Tái sử dụng và mở rộng rất linh hoạt

Bài tập mở rộng

  1. Tạo nút Đăng xuất ở layout
  2. Hiển thị tên người dùng ở header nếu đã login
  3. Nếu chưa login → ẩn menu admin
  4. Gắn isLoggedIn, isAdmin, isEditor vào useAuth()

Thảo luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Đăng ký nhận tin mới

Nhận bài học, tài nguyên và cơ hội việc làm qua email hàng tuần.

Chúng tôi cam kết không spam. Bạn có thể hủy bất cứ lúc nào.