You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt4+BetterAuth导航栏无法动态更新,仅刷新后生效求助

问题:Nuxt4 + BetterAuth 导航栏session状态无法实时更新

我用Nuxt4搭配BetterAuth和Supabase开发,默认布局里的导航栏组件无法动态更新session状态,只有手动刷新页面(F5)后才会显示正确状态。

项目目录结构

app/
├─ components/
│  ├─ AddTask.vue
│  ├─ LoginUser.vue
│  ├─ RegisterUser.vue
│  └─ TheNavbar.vue
├─ composables/
│  └─ useAuth.ts
├─ layouts/
│  └─ default.vue
├─ middleware/
│  └─ auth.global.ts
├─ pages/
├─ schemas/
├─ ui/
├─ utils/
├─ app.vue
├─ better-auth_migrations/
├─ node_modules/
├─ public/
├─ server/
└─ .env

相关代码

useAuth.ts

import { authClient } from "../utils/auth-client";
import { useFetch } from "#app";
import { ref } from "vue";

export const useAuth = () => {
    const session = ref(null);

    const init = async () => {
        const { data } = await authClient.useSession(useFetch);
        session.value = data.value;
    };

    init(); 

    const logout = async () => {
        await authClient.signOut();
        session.value = null;
        return navigateTo("/login");
    };

    return { session, logout };
};

TheNavbar.vue

<script lang="ts" setup>
import { useAuth } from "../composables/useAuth";
const { session, logout } = useAuth();

import BaseButton from "~/ui/BaseButton.vue";
</script>

<template>
    <nav class="bg-gray-800 p-4 text-white">
        <div class="container mx-auto flex justify-between items-center">
            <div class="text-lg font-semibold">
                <NuxtLink to="/" class="mr-4 hover:underline">MAIN</NuxtLink>
            </div>
            <div>
                <NuxtLink to="/login" class="mr-4 hover:underline">LOGIN</NuxtLink>
                <NuxtLink to="/register" class="mr-4 hover:underline"
                    >REGISTER</NuxtLink
                >

                <NuxtLink to="/add" class="mr-4 hover:underline">ADD</NuxtLink>
                <NuxtLink to="/view" class="hover:underline">VIEW TASKS</NuxtLink>
                <BaseButton @click="logout" color="blue" label="LOGOUT" type="button" />
            </div>
        </div>

        <p>{{ session }}</p>
    </nav>
</template>

解决思路

1. 监听BetterAuth的session变化事件

BetterAuth客户端提供了session变更的监听机制,在useAuth中订阅session的实时更新,替代仅初始化时获取一次的逻辑:

修改useAuth.ts:

import { authClient } from "../utils/auth-client";
import { useFetch } from "#app";
import { ref, onMounted, onUnmounted } from "vue";

export const useAuth = () => {
    const session = ref(null);

    const init = async () => {
        const { data } = await authClient.useSession(useFetch);
        session.value = data.value;
    };

    let unsubscribe: (() => void) | undefined;
    onMounted(async () => {
        await init();
        // 订阅session更新,自动同步状态
        unsubscribe = authClient.onSessionChange((newSession) => {
            session.value = newSession;
        });
    });

    onUnmounted(() => {
        unsubscribe?.();
    });

    const logout = async () => {
        await authClient.signOut();
        return navigateTo("/login");
    };

    return { session, logout };
};

2. 改用Nuxt全局共享状态

组件级ref无法跨组件共享状态,多次调用useAuth会创建独立的session实例。改用Nuxt的useState实现全局状态共享:

修改useAuth.ts:

import { authClient } from "../utils/auth-client";
import { useFetch, useState } from "#app";
import { onMounted, onUnmounted } from "vue";

export const useAuth = () => {
    // 创建全局共享的session状态
    const session = useState("auth-session", () => null);

    const init = async () => {
        const { data } = await authClient.useSession(useFetch);
        session.value = data.value;
    };

    let unsubscribe: (() => void) | undefined;
    onMounted(async () => {
        await init();
        unsubscribe = authClient.onSessionChange((newSession) => {
            session.value = newSession;
        });
    });

    onUnmounted(() => {
        unsubscribe?.();
    });

    const logout = async () => {
        await authClient.signOut();
        return navigateTo("/login");
    };

    return { session, logout };
};

3. 同步响应式数据引用

如果BetterAuth的useSession返回的data本身是响应式对象,可直接让session ref指向该响应式数据,替代单次赋值:

修改useAuth.ts中的init函数:

import { toRef } from "vue";

// ...

const init = async () => {
    const { data } = await authClient.useSession(useFetch);
    // 同步响应式数据引用,确保状态实时更新
    session.value = toRef(data, 'value').value;
};

4. 检查全局中间件逻辑

查看auth.global.ts中间件,确保它没有维护独立状态,而是通过调用useAuth来同步最新的session状态,避免路由跳转时状态不同步。


内容的提问来源于stack exchange,提问作者Kacper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 10:43:17