Laravel Türkiye Discord Kanalı Forumda kod paylaşılırken dikkat edilmesi gerekenler!Birlikte proje geliştirmek ister misiniz?
watch(() => authStore.user, (newValue, oldValue) => {
  console.log('Eski değer:', oldValue);
  console.log('Yeni değer:', newValue);
}, {
  immediate: true
});

watch ile değeri izleyim dedim ve tam sayfayı yenilediğimde

Eski değer: null
Yeni değer:
{
    "_id": "66cdd905d9107b59c9eb221e",
    "username": "aghabala2024",
    "email": "aghabala.guluzade@gmail.com",
    "password": "$2a$10$Ta.BX/kfmCIVf0VyPQaeF.P0wuW2uxQ9MqMzolHGt.EtIr27M.xwW",
    "admin": false,
    "createdAt": "2024-08-27T13:47:49.371Z",
    "updatedAt": "2024-08-27T13:47:49.371Z",
    "__v": 0
} 

geliyor yani hata store da fakat çözümü ne hm

pinia persistedstate pluginini yukleyip,

store/authStore.ts u aşağıdaki gibi gücelleyin ( persist: true, ekleyin ve initialize kaldırın) sorununuz cözülecektir.

import { defineStore } from 'pinia'

export const useAuthStore = defineStore({
  id: 'AuthStore',
  state: () => ({
    user: null,
    isLoggedIn: false,
  }),
  actions: {
    async register(newUser) {
      try {
        const data = await $fetch('/api/auth/register', {
          method: 'POST',
          body: JSON.stringify(newUser),
          headers: {
            'Content-Type': 'application/json'
          }
        });

        this.user = data;
      } catch (error) {
        throw error.data;
      }
    },
    async login(newUser) {
      try {
        const data = await $fetch('/api/auth/login', {
          method: 'POST',
          body: JSON.stringify(newUser),
          headers: {
            'Content-Type': 'application/json'
          }
        });
    
        this.user = data.user;
        this.isLoggedIn = true;
        localStorage.setItem('user', JSON.stringify(data.user));
      } catch (error) {
        throw error.data;
      }
    },
    logout() {
      this.user = null;
      this.isLoggedIn = false;
      localStorage.removeItem('user');
    },
  }
  persist: true,
});

cunku initialize() yi sureklı manuel cagırmanz ve kullanıcı verileriniz hala var mı diye kontrol etmeniz gerekir. Bu plugin pinia'nın otomatik kalıcılık (persistence) işlevini kullanır. Bu yöntem, mağaza durumunu otomatik olarak localStorage veya sessionStorage içine kaydeder ve sayfa yenilendiğinde bu durumu geri yükler.

    aeneas teşekkürler yaptım fakat urlden login yazıp girmeye çalştığımda hala bi anlık logini göstreip sonra dashboarda atıyor ve console da hatalar oluyor. Bunu nasıl orda diye:

    import { useAuthStore } from "~/store/authStore";
    
    export default defineNuxtRouteMiddleware((to, from) => {
       if (process.client) {
          const authStore = useAuthStore();
    
          if (!authStore.user) {
             if (to.path === '/dashboard') {
                return navigateTo('/login');
             }
          }
    
          if (authStore.user) {
             if (to.path === '/login' || to.path === '/register') {
                return navigateTo('/dashboard');
             }
          }
       }
    });

    store/authStore.ts

    import { defineStore } from 'pinia'
    
    export const useAuthStore = defineStore({
      id: 'AuthStore',
      state: () => ({
        user: null,
      }),
      getters: {
        _isLoggedIn: (state) => !!state.user
      },
      actions: {
        async register(newUser) {
          try {
            const data = await $fetch('/api/auth/register', {
              method: 'POST',
              body: JSON.stringify(newUser),
              headers: {
                'Content-Type': 'application/json'
              }
            });
    
            this.user = data;
          } catch (error) {
            throw error.data;
          }
        },
        async login(newUser) {
          try {
            const data = await $fetch('/api/auth/login', {
              method: 'POST',
              body: JSON.stringify(newUser),
              headers: {
                'Content-Type': 'application/json'
              }
            });
        
            this.user = data.user;
            localStorage.setItem('user', JSON.stringify(data.user));
          } catch (error) {
            throw error.data;
          }
        },
        logout() {
          this.user = null;
          localStorage.removeItem('user');
        },
      },
      persist: true
    });

    NavBar.vue

    <script lang="ts" setup>
    import { useAuthStore } from '~/store/authStore';
    
    const authStore = useAuthStore();
    
    const isLoggedIn = computed(() => authStore._isLoggedIn);
    
    console.log(isLoggedIn);
    
    const logout = () => {
      authStore.logout();
    };
    
    </script>
    
    <template>
      <nav class="navbar navbar-expand-md custom-nav">
        <div class="container">
          <NuxtLink class="navbar-brand" :to="`/`">Bostorek</NuxtLink>
          <ul class="navbar-nav">
            <li class="nav-item active">
              <NuxtLink class="nav-link pl-lg-0" :to="`/`">Home <span class="sr-only">(current)</span></NuxtLink>
            </li>
            <li class="nav-item">
              <NuxtLink class="nav-link" :to="`/books`">Books</NuxtLink>
            </li>
            <li v-if="isLoggedIn" class="nav-item">
              <NuxtLink class="nav-link" :to="`/dashboard`">Dashboard</NuxtLink>
            </li>
            <li v-if="!isLoggedIn" class="nav-item">
              <NuxtLink class="nav-link" :to="`/login`">Login</NuxtLink>
            </li>
            <li v-if="!isLoggedIn" class="nav-item">
              <NuxtLink class="nav-link" :to="`/register`">Register</NuxtLink>
            </li>
            <li v-if="isLoggedIn" class="nav-item">
              <button class="nav-link" @click="logout">Logout</button>
            </li>
          </ul>
        </div>
      </nav>
    </template>

    kodlarım böyle fakat diyelim url kısmından login yazıpta entere tıkladığımda bir anlık login sayfası gözüküyor sonra beni ana sayfaya atyıor ve console da şöyle hatalar oluyor

    [Vue warn]: Hydration class mismatch on <a href=​"/​dashboard" class=​"nav-link" data-v-2202255b>​Dashboard​</a>​ 
      - rendered on server: class="nav-link"
      - expected on client: class="router-link-active router-link-exact-active nav-link"
      Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead.
      You should fix the source of the mismatch. 
      at <RouterLink ref=fn to="/dashboard" activeClass=undefined  ... > 
      at <NuxtLink class="nav-link" to="/dashboard" > 
      at <NavBar> 
      at <Default ref=Ref< undefined > > 
      at <LayoutLoader key="default" layoutProps= {ref: RefImpl} name="default" > 
      at <NuxtLayoutProvider layoutProps= {ref: RefImpl} key="default" name="default"  ... > 
      at <NuxtLayout> 
      at <App key=4 > 
      at <NuxtRoot>

    Hydration completed but contains mismatches.

    ve

    runtime-core.esm-bundler.js?v=df5f42f9? [sm]:51 [Vue warn]: Hydration node mismatch:
    - rendered on server: <section class=​"full-section-height" data-v-inspector=​"pages/​login.vue:​25:​3">​…​</section>​  
    - expected on client: div 
      at <Dashboard onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
      at <Anonymous key="/dashboard" vnode= {__v_isVNode: true, __v_skip: true, type: {…}, props: {…}, key: null, …} route= {fullPath: '/dashboard', hash: '', query: {…}, name: 'dashboard', path: '/dashboard', …}  ... > 
      at <RouterView name=undefined route=undefined > 
      at <NuxtPage> 
      at <Default ref=Ref< undefined > > 
      at <LayoutLoader key="default" layoutProps= {ref: RefImpl} name="default" > 
      at <NuxtLayoutProvider layoutProps= {ref: RefImpl} key="default" name="default"  ... > 
      at <NuxtLayout> 
      at <App key=4 > 
      at <NuxtRoot>

      aghabalaguluzade

      <script lang="ts" setup>
      import { useAuthStore } from '~/store/authStore';
      
      const authStore = useAuthStore();
      
      // Computed
      const isLoggedIn = computed(() => authStore._isLoggedIn);
      
      watch(() => isLoggedIn.value, (newValue, oldValue) => {
        console.log('Eski değer:', oldValue);
        console.log('Yeni değer:', newValue);
      }, {
        immediate: true
      });
      
      // Methods
      const logout = () => {
        authStore.logout();
      };
      
      </script>

      hala sayfanı yenilediğimde

      Eski değer: undefined
      Yeni değer: true

      böyle oluyor yani başlanğıcta undefined oluyor sonra data ekleniyor

      store'da persist:true dediğiniz de cookie ye set ediyorsa cookieler server da erişebilir olması lazım.
      plugin'inde if (process.client) koşulu kaldırıp bu şekilde denermisin.

        ben daha öncesinde şöyle yapmıştım authStore a fetchUser() methodu yapmıştım. burada user i alıyorum sonrasında

        plugin/loadUser.js

        import { useAuthStore } from '~/store/auth';
        export default defineNuxtPlugin(async () => {
            const auth = useAuthStore();
            await auth.fetchUser();
        });

        burada plugin sayfa yüklenirken serverde loadUser la store u dolduracak.
        https://www.youtube.com/watch?v=ev206pOjRos
        belki bu sana bir fikir verir.

        NavBar.vue ni aşagıdaki kod ile değiştirirmisin.
        navbarda koşullu (isLoggedIn) aktif link uyguluyorsun buda hidrasyona neden oluyor.
        hidrasyonu engellemenin en basit ve etkili yolu kodu client side rendering etmektir.
        navbar ı <ClientOnly> tagı içine alarak client tarafında olusturulmasını sağlamış olacağız, bununda sorunu cözeceğini umuyorum.

        <script lang="ts" setup>
        import { useAuthStore } from '~/store/authStore';
        
        const authStore = useAuthStore();
        
        const isLoggedIn = computed(() => authStore._isLoggedIn);
        
        console.log(isLoggedIn);
        
        const logout = () => {
          authStore.logout();
        };
        
        </script>
        
        <template>
        <ClientOnly>
          <nav class="navbar navbar-expand-md custom-nav">
            <div class="container">
              <NuxtLink class="navbar-brand" :to="`/`">Bostorek</NuxtLink>
              <ul class="navbar-nav">
                <li class="nav-item active">
                  <NuxtLink class="nav-link pl-lg-0" :to="`/`">Home <span class="sr-only">(current)</span></NuxtLink>
                </li>
                <li class="nav-item">
                  <NuxtLink class="nav-link" :to="`/books`">Books</NuxtLink>
                </li>
                <li v-if="isLoggedIn" class="nav-item">
                  <NuxtLink class="nav-link" :to="`/dashboard`">Dashboard</NuxtLink>
                </li>
                <li v-if="!isLoggedIn" class="nav-item">
                  <NuxtLink class="nav-link" :to="`/login`">Login</NuxtLink>
                </li>
                <li v-if="!isLoggedIn" class="nav-item">
                  <NuxtLink class="nav-link" :to="`/register`">Register</NuxtLink>
                </li>
                <li v-if="isLoggedIn" class="nav-item">
                  <button class="nav-link" @click="logout">Logout</button>
                </li>
              </ul>
            </div>
          </nav>
        </ClientOnly>
        </template>

          aeneas bunu yaptım fakat yine hata veriyordu bende bir tek NavBar.vue den başka dashboard.vue, login.vue ve register.vue de <ClientOnly> ekledim ve hata çözüldü fakat bu yöntemin doğru olmadığını düşünüyorum yani hepsinde tanımladığımda çözülmesi ama bilemiyorum. Ayrıca <ClientOnly> eklediğimde sayfayı yenilediğimde <ClientOnly> olan yerler yenileme bitene kadar kayboluyorlar sayfa yenilendiğinde (1 saniyede kısa sürede) gözüküyorlar.

          kodlarımı bir kez daha paylaşayım tümüyle

          store/authStore.ts

          import { defineStore } from 'pinia'
          
          export const useAuthStore = defineStore({
            id: 'AuthStore',
            state: () => ({
              user: null, 
            }),
            getters: {
              _isLoggedIn: (state) => !!state.user
            },
            actions: {
              async register(newUser) {
                try {
                  const data = await $fetch('/api/auth/register', {
                    method: 'POST',
                    body: JSON.stringify(newUser),
                    headers: {
                      'Content-Type': 'application/json'
                    }
                  });
          
                  this.user = data;
                } catch (error) {
                  throw error.data;
                }
              },
              async login(newUser) {
                try {
                  const data = await $fetch('/api/auth/login', {
                    method: 'POST',
                    body: JSON.stringify(newUser),
                    headers: {
                      'Content-Type': 'application/json'
                    }
                  });
              
                  this.user = data.user;
                  localStorage.setItem('user', JSON.stringify(data.user));
                } catch (error) {
                  throw error.data;
                }
              },
              logout() {
                this.user = null;
                localStorage.removeItem('user');
              },
            },
            persist: true
          });

          NavBar.vue

          <script setup>
          import { useAuthStore } from "~/store/authStore";
          
          const authStore = useAuthStore();
          
          // Computed
          const isLoggedIn = computed(() => authStore._isLoggedIn);
          
          watch(() => isLoggedIn.value, (newValue, oldValue) => {
           console.log('Eski değer:', oldValue);
           console.log('Yeni değer:', newValue);
          }, {
           immediate: true
          });
          
          // Methods
          const logout = () => {
            authStore.logout();
            return navigateTo("/");
          };
          </script>
          
          <template>
            <nav class="navbar navbar-expand-md custom-nav">
              <div class="container">
                <NuxtLink class="navbar-brand" :to="`/`">Bostorek</NuxtLink>
                <ul class="navbar-nav">
                  <li class="nav-item active">
                    <NuxtLink class="nav-link pl-lg-0" :to="`/`"
                      >Home <span class="sr-only">(current)</span></NuxtLink
                    >
                  </li>
                  <li class="nav-item">
                    <NuxtLink class="nav-link" to="/books">Books</NuxtLink>
                  </li>
                  <li v-if="isLoggedIn" class="nav-item">
                    <NuxtLink class="nav-link" to="/dashboard">Dashboard</NuxtLink>
                  </li>
                  <li v-if="!isLoggedIn" class="nav-item">
                    <NuxtLink class="nav-link" to="/login">Login</NuxtLink>
                  </li>
                  <li v-if="!isLoggedIn" class="nav-item">
                    <NuxtLink class="nav-link" to="/register">Register</NuxtLink>
                  </li>
                  <li v-if="isLoggedIn" class="nav-item">
                    <button class="nav-link" @click="logout">Logout</button>
                  </li>
                </ul>
              </div>
            </nav>
          </template>

          dashboard.vue

          <script setup>
          import { useAuthStore } from "~/store/authStore";
          
          const userStore = useAuthStore();
          
          const activeTab = ref("general");
          const editMode = ref(false);
          const userInfo = reactive({
            username: "",
            email: "",
            password: "",
          });
          
          const toggleEditMode = () => {
            editMode.value = !editMode.value;
          };
          
          const cancelEditMode = () => {
            editMode.value = false;
            userInfo.username = userStore.user.username;
            userInfo.email = userStore.user.email;
            userInfo.password = userStore.user.password;
          };
          
          onMounted(() => {
            userInfo.username = userStore.user.username;
            userInfo.email = userStore.user.email;
          });
          </script>
          
          <template>
            <section style="min-height: calc(100vh - 130px)">
              <div class="container py-5">
                <ul class="nav nav-tabs" id="dashboardTab" role="tablist">
                  <li class="nav-item" role="presentation" @click="activeTab = 'general'">
                    <button
                      class="nav-link"
                      :class="{ active: activeTab === 'general' }"
                      id="general-tab"
                      data-bs-toggle="tab"
                      data-bs-target="#general-tab-pane"
                      type="button"
                      role="tab"
                      aria-controls="general-tab-pane"
                      aria-selected="true"
                    >
                      General
                    </button>
                  </li>
                  <li class="nav-item" role="presentation" @click="activeTab = 'books'">
                    <button
                      class="nav-link"
                      :class="{ active: activeTab === 'books' }"
                      id="books-tab"
                      data-bs-toggle="tab"
                      data-bs-target="#books-tab-pane"
                      type="button"
                      role="tab"
                      aria-controls="books-tab-pane"
                      aria-selected="false"
                    >
                      Books
                    </button>
                  </li>
                </ul>
                <div class="tab-content py-4" id="dashboardContent">
                  <div
                    class="tab-pane fade"
                    :class="{ 'active show': activeTab === 'general' }"
                    id="general-tab-pane"
                    role="tabpanel"
                    aria-labelledby="general-tab"
                    tabindex="0"
                  >
                    <div class="row">
                      <div class="col-lg-6">
                        <h2 class="mb-4">User Information</h2>
                        <form>
                          <div class="mb-3">
                            <label for="username">Username</label>
                            <input
                              v-model="userInfo.username"
                              type="text"
                              id="username"
                              class="form-control"
                              :disabled="!editMode"
                            />
                          </div>
                          <div class="mb-3">
                            <label for="email">Email</label>
                            <input
                              v-model="userInfo.email"
                              type="email"
                              id="email"
                              class="form-control"
                              :disabled="!editMode"
                            />
                          </div>
                          <div class="mb-3">
                            <label for="password">Password</label>
                            <input
                              v-model="userInfo.password"
                              type="password"
                              id="password"
                              class="form-control"
                              :disabled="!editMode"
                            />
                          </div>
                          <button
                            @click="!editMode ? toggleEditMode() : saveUserInfo()"
                            type="button"
                            class="btn btn-primary"
                          >
                            {{ editMode ? "Save" : "Edit" }}
                          </button>
                          <button
                            v-if="editMode"
                            style="
                              background-color: #ecc73c !important;
                              border-color: #ecc73c !important;
                            "
                            @click="cancelEditMode"
                            type="button"
                            class="btn btn-primary ms-3"
                          >
                            Cancel
                          </button>
                        </form>
                      </div>
                      <div class="col-lg-6"></div>
                    </div>
                  </div>
                  <div
                    class="tab-pane fade"
                    :class="{ 'active show': activeTab === 'books' }"
                    id="books-tab-pane"
                    role="tabpanel"
                    aria-labelledby="books-tab"
                    tabindex="0"
                  >
                    {{ userStore.user.username }} books
                  </div>
                </div>
              </div>
            </section>
          </template>

          login.vue

          <script setup>
          import { useAuthStore } from "~/store/authStore";
          import { useToast } from "vue-toastification";
          
          const authStore = useAuthStore();
          const router = useRouter();
          
          const formData = reactive({
            email: "",
            password: "",
          });
          const showEmailWarningMessage = ref(false);
          const showPasswordWarningMessage = ref(false);
          const notFoundEmail = ref(null);
          const isPasswordMatch = ref(true);
          const toast = useToast();
          
          const isEmailValid = computed(() => {
            return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email);
          });
          
          const isPasswordValid = computed(() => {
            return formData.password.length >= 4 && formData.password.length <= 10;
          });
          
          const isFormValid = computed(() => {
            return isEmailValid.value && isPasswordValid.value;
          });
          
          const submitForm = async () => {
            try {
              await authStore.login(formData);
              toast.success("You will be redirected to the dashboard page", {
                position: "top-right",
                timeout: 3500,
                closeButton: "button",
                icon: true,
                rtl: false,
              });
              setTimeout(() => {
                router.push("/dashboard");
              }, 4000);
            } catch (errors) {
              const { error } = errors;
          
              if (error === "User not found!") {
                notFoundEmail.value = this.formData.email;
              } else if (error === "Your password is not true") {
                isPasswordMatch.value = false;
              }
            }
          };
          </script>
          
          <template>
            <section class="full-section-height">
              <Head>
                <Title>Login</Title>
                <Meta name="description" content="Login" />
              </Head>
              <div class="container">
                <div class="row justify-content-center mb-2 text-center">
                  <div class="d-flex justify-content-center">
                    <h1 class="display-3">Login</h1>
                  </div>
                </div>
                <form @submit.prevent="submitForm">
                  <div class="row justify-content-center">
                    <!-- Email Field (Medium and Larger Screens) -->
                    <div class="col-md-6 col-8 mb-3">
                      <label for="email" class="form-label">Email</label>
                      <input
                        type="email"
                        class="form-control"
                        id="email"
                        name="email"
                        v-model.trim="formData.email"
                        autocomplete="on"
                        :class="{
                          'is-valid': isEmailValid,
                          'is-invalid':
                            (!isEmailValid && showEmailWarningMessage) ||
                            notFoundEmail === formData.email,
                        }"
                        @focus="showEmailWarningMessage = true"
                        @blur="showEmailWarningMessage = false"
                        required
                      />
                      <span
                        v-if="showEmailWarningMessage && !isEmailValid"
                        class="text-danger small"
                        >Please provide a valid email!</span
                      >
                      <span
                        v-if="notFoundEmail === formData.email"
                        class="text-danger small"
                        >{{ `${notFoundEmail} is not found!` }}</span
                      >
                    </div>
                  </div>
          
                  <!-- Password Field -->
                  <div class="row justify-content-center">
                    <div class="col-md-6 col-8 mb-3">
                      <label for="password" class="form-label">Password</label>
                      <input
                        type="password"
                        class="form-control"
                        id="password"
                        name="password"
                        v-model.trim="formData.password"
                        :class="{
                          'is-valid': isPasswordValid,
                          'is-invalid':
                            (!isPasswordValid && showPasswordWarningMessage) ||
                            !isPasswordMatch,
                        }"
                        @focus="showPasswordWarningMessage = true"
                        @blur="showPasswordWarningMessage = false"
                        @input="isPasswordMatch = true"
                        required
                      />
                      <span
                        v-if="showPasswordWarningMessage && !isPasswordValid"
                        class="text-danger small"
                        >Password must be between 4 and 10 characters!</span
                      >
                      <span v-if="!isPasswordMatch" class="text-danger small"
                        >Your password is not true!</span
                      >
                    </div>
                  </div>
          
                  <!-- Submit Button -->
                  <div class="row justify-content-center">
                    <div class="col-md-6 col-8 mb-3">
                      <button type="submit" class="btn btn-primary w-100">Login</button>
                    </div>
                  </div>
                </form>
              </div>
            </section>
          </template>

          register.vue

          <script setup>
          import { useAuthStore } from "~/store/authStore";
          import { useToast } from "vue-toastification";
          
          const authStore = useAuthStore();
          const router = useRouter();
          
          const formData = reactive({
            username: "",
            email: "",
            password: "",
          });
          
          const showUsernameWarningMessage = ref(false);
          const showEmailWarningMessage = ref(false);
          const showPasswordWarningMessage = ref(false);
          const existingEmail = ref(null);
          const showGenericWarningMessage = ref(false);
          
          const isUsernameValid = computed(() => {
            return formData.username.length >= 5 && formData.username.length <= 20;
          });
          
          const isEmailValid = computed(() => {
            return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email);
          });
          
          const isPasswordValid = computed(() => {
            return formData.password.length >= 4 && formData.password.length <= 10;
          });
          
          const isFormValid = computed(() => {
            return isUsernameValid.value && isEmailValid.value && isPasswordValid.value;
          });
          
          const submitForm = async () => {
            try {
              await authStore.register(formData);
              const toast = useToast();
              toast.success("You will be redirected to the login page", {
                position: "top-right",
                timeout: 3500,
                closeButton: "button",
                icon: true,
                rtl: false,
              });
              setTimeout(() => {
                router.push("/login");
              }, 4000);
            } catch (errors) {
              const { error } = errors;
          
              if (error == "The Email is already exists!") {
                existingEmail.value = formData.email;
              } else {
                showGenericWarningMessage.value = true;
                formData.username = "";
                formData.email = "";
                formData.password = "";
              }
            }
          };
          </script>
          
          <template>
            <section class="full-section-height">
              <Head>
                <Title>Register</Title>
                <Meta name="description" content="Register" />
              </Head>
              <div class="container">
                <div class="row justify-content-center mb-2 text-center">
                  <div class="d-flex justify-content-center">
                    <h1 class="display-3">Register</h1>
                  </div>
                </div>
                <form @submit.prevent="submitForm">
                  <div v-if="showGenericWarningMessage" class="text-center">
                    <span class="text-danger small"
                      >Something happened, please try again later!</span
                    >
                  </div>
                  <div class="row justify-content-center">
                    <!-- Username Field (Medium and Larger Screens) -->
                    <div class="col-md-6 col-8 mb-3">
                      <label for="username" class="form-label"
                        >Username
                        <span class="text-danger">*</span>
                      </label>
                      <input
                        type="text"
                        class="form-control"
                        id="username"
                        name="username"
                        v-model.trim="formData.username"
                        autocomplete="off"
                        :class="{
                          'is-valid': isUsernameValid,
                          'is-invalid': !isUsernameValid && showUsernameWarningMessage,
                        }"
                        @focus="showUsernameWarningMessage = true"
                        @blur="showUsernameWarningMessage = false"
                        required
                      />
                      <span
                        v-if="showUsernameWarningMessage && !isUsernameValid"
                        class="text-danger small"
                        >Username must be between 5 and 20 characters!</span
                      >
                    </div>
                  </div>
          
                  <div class="row justify-content-center">
                    <!-- Email Field (Medium and Larger Screens) -->
                    <div class="col-md-6 col-8 mb-3">
                      <label for="email" class="form-label"
                        >Email
                        <span class="text-danger">*</span>
                      </label>
                      <input
                        type="email"
                        class="form-control"
                        id="email"
                        name="email"
                        v-model.trim="formData.email"
                        autocomplete="off"
                        :class="{
                          'is-valid': isEmailValid,
                          'is-invalid':
                            (!isEmailValid && showEmailWarningMessage) ||
                            existingEmail === formData.email,
                        }"
                        @focus="showEmailWarningMessage = true"
                        @blur="showEmailWarningMessage = false"
                        required
                      />
                      <span
                        v-if="showEmailWarningMessage && !isEmailValid"
                        class="text-danger small"
                        >Please provide a valid email!</span
                      >
                      <span
                        v-if="existingEmail === formData.email"
                        class="text-danger small"
                      >
                        {{ `${existingEmail} is already exist!` }}</span
                      >
                    </div>
                  </div>
          
                  <!-- Password Field -->
                  <div class="row justify-content-center">
                    <div class="col-md-6 col-8 mb-3">
                      <label for="password" class="form-label"
                        >Password
                        <span class="text-danger">*</span>
                      </label>
                      <input
                        type="password"
                        class="form-control"
                        id="password"
                        name="password"
                        v-model.trim="formData.password"
                        :class="{
                          'is-valid': isPasswordValid,
                          'is-invalid': !isPasswordValid && showPasswordWarningMessage,
                        }"
                        @focus="showPasswordWarningMessage = true"
                        @blur="showPasswordWarningMessage = false"
                        required
                      />
                      <span
                        v-if="showPasswordWarningMessage && !isPasswordValid"
                        class="text-danger small"
                        >Password must be between 4 and 10 characters!</span
                      >
                    </div>
                  </div>
          
                  <!-- Submit Button -->
                  <div class="row justify-content-center">
                    <div class="col-md-6 col-8 mb-3">
                      <button
                        :disabled="!isFormValid"
                        type="submit"
                        class="btn btn-primary w-100"
                      >
                        Register
                      </button>
                      <span v-if="!isFormValid" class="text-danger small"
                        >* Please complete all of the required fields!</span
                      >
                    </div>
                  </div>
                </form>
              </div>
            </section>
          </template>

          middleware/auth.global.ts

          import { useAuthStore } from "~/store/authStore";
          
          export default defineNuxtRouteMiddleware((to, from) => {
             if (process.client) {
                const authStore = useAuthStore();
          
                if (!authStore.user) {
                   if (to.path === '/dashboard') {
                      return navigateTo('/login');
                   }
                }
          
                if (authStore.user) {
                   if (to.path === '/login' || to.path === '/register') {
                      return navigateTo({ name: 'dashboard' });
                   }
                }
             }
          });

          Hatalar

          1 - Giriş yapmama ve middleware tanımlamama rağmen url kısmından login/register yazıpta enter dediğimde beni login sayfasına atıyor ve login sayfası 1 saniyelik gözüküyor sonra hemen dashboarda atıyor beni ve attığı zaman şöyle hatalar gözüküyor console da.

          [Vue warn]: Hydration class mismatch on <a href=​"/​dashboard" class=​"nav-link" data-v-2202255b>​Dashboard​</a>​ 
            - rendered on server: class="nav-link"
            - expected on client: class="router-link-active router-link-exact-active nav-link"
            Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead.
            You should fix the source of the mismatch. 
            at <RouterLink ref=fn to="/dashboard" activeClass=undefined  ... > 
            at <NuxtLink class="nav-link" to="/dashboard" > 
            at <NavBar> 
            at <Default ref=Ref< undefined > > 
            at <LayoutLoader key="default" layoutProps= {ref: RefImpl} name="default" > 
            at <NuxtLayoutProvider layoutProps= {ref: RefImpl} key="default" name="default"  ... > 
            at <NuxtLayout> 
            at <App key=4 > 
            at <NuxtRoot>

          runtime-core.esm-bundler.js?v=912f7bb0? [sm]:3641 Hydration completed but contains mismatches.

          runtime-core.esm-bundler.js?v=912f7bb0? [sm]:51 [Vue warn]: Hydration node mismatch:
          - rendered on server: <!--[--> (start of fragment) 
          - expected on client: div 
            at <Dashboard onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
            at <Anonymous key="/dashboard" vnode= {__v_isVNode: true, __v_skip: true, type: {…}, props: {…}, key: null, …} route= {fullPath: '/dashboard', hash: '', query: {…}, name: 'dashboard', path: '/dashboard', …}  ... > 
            at <RouterView name=undefined route=undefined > 
            at <NuxtPage> 
            at <Default ref=Ref< undefined > > 
            at <LayoutLoader key="default" layoutProps= {ref: RefImpl} name="default" > 
            at <NuxtLayoutProvider layoutProps= {ref: RefImpl} key="default" name="default"  ... > 
            at <NuxtLayout> 
            at <App key=4 > 
            at <NuxtRoot>
          [Vue warn]: Hydration children mismatch on <section class=​"full-section-height" data-v-inspector=​"pages/​login.vue:​56:​3">​…​</section>​ flex  
          Server rendered element contains more child nodes than client vdom. 
            at <Dashboard onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
            at <Anonymous key="/dashboard" vnode= {__v_isVNode: true, __v_skip: true, type: {…}, props: {…}, key: null, …} route= {fullPath: '/dashboard', hash: '', query: {…}, name: 'dashboard', path: '/dashboard', …}  ... > 
            at <RouterView name=undefined route=undefined > 
            at <NuxtPage> 
            at <Default ref=Ref< undefined > > 
            at <LayoutLoader key="default" layoutProps= {ref: RefImpl} name="default" > 
            at <NuxtLayoutProvider layoutProps= {ref: RefImpl} key="default" name="default"  ... > 
            at <NuxtLayout> 
            at <App key=4 > 
            at <NuxtRoot>
          runtime-core.esm-bundler.js?v=912f7bb0? [sm]:51 [Vue warn]: Hydration style mismatch on <section class=​"full-section-height" data-v-inspector=​"pages/​login.vue:​56:​3">​…​</section>​ flex  
            - rendered on server: style=""
            - expected on client: style="min-height:calc(100vh - 130px);"
            Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead.
            You should fix the source of the mismatch. 
            at <Dashboard onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
            at <Anonymous key="/dashboard" vnode= {__v_isVNode: true, __v_skip: true, type: {…}, props: {…}, key: null, …} route= {fullPath: '/dashboard', hash: '', query: {…}, name: 'dashboard', path: '/dashboard', …}  ... > 
            at <RouterView name=undefined route=undefined > 
            at <NuxtPage> 
            at <Default ref=Ref< undefined > > 
            at <LayoutLoader key="default" layoutProps= {ref: RefImpl} name="default" > 
            at <NuxtLayoutProvider layoutProps= {ref: RefImpl} key="default" name="default"  ... > 
            at <NuxtLayout> 
            at <App key=4 > 
            at <NuxtRoot>

          Bunun sebebinin store da userin başta null olması ve sonradan atanması olduğunu düşünüyorum. Böyle düşünmemin sebebi watch ile baktığımda

          watch(() => isLoggedIn.value, (newValue, oldValue) => {
            console.log('Eski değer:', oldValue);
            console.log('Yeni değer:', newValue);
          }, {
            immediate: true
          });

          ve sayfayı yenilediğimde

          Eski değer: undefined
          Yeni değer: true

          gözüküyor yani bence login sayfasının 1 saniye gözüküp sonra beni dashobarda atmasının nedeni userin başta undefined olup sonra true olması.

          Aşağıda process.client) diyerek altındakı sorguları client tarafında yapıyorsunuz. henuz state yuklenmedıyse yuklenene mevcut hatanıza neden olabılır. Yanı 1 sanıye logını gorup sonra dashboarda gıtmesıne sebep olabilir. if (process.client) { kodu buraya sarmayı bırakırsanız veya if (process.server) yaparsanız server tarafında calısacaktır. Çok mecbur kalmadıkca client tarafında kod calıstırmayın, nuxt SSR için tasarlanmıstır. Çok istista durumlar client tarafı kod calıstırmaya ıhtıyac duyar.

          import { useAuthStore } from "~/store/authStore";
          
          export default defineNuxtRouteMiddleware((to, from) => {
             if (process.client) {
                const authStore = useAuthStore();
          
                if (!authStore.user) {
                   if (to.path === '/dashboard') {
                      return navigateTo('/login');
                   }
                }
          
                if (authStore.user) {
                   if (to.path === '/login' || to.path === '/register') {
                      return navigateTo({ name: 'dashboard' });
                   }
                }
             }
          }); 

            aeneas teşekkür ederim çözdüm artık hatayı kodu aşağıda paylaşacağım.

            Çözüldü

            middleware.auth.global.ts

            import { useAuthStore } from '~/store/authStore';
            
            export default defineNuxtRouteMiddleware((to, from) => {
               const authStore = useAuthStore();
            
               if (!authStore.isLoggedIn && (to.path === '/dashboard' || to.path === '/profile')) {
                  return navigateTo('/login');
               }
            
               if (authStore.isLoggedIn && (to.path === '/login' || to.path === '/register')) {
                  return navigateTo('/dashboard');
               }
            });

            store/authStore.ts

            import { defineStore } from 'pinia'
            
            export const useAuthStore = defineStore({
              id: 'AuthStore',
              state: () => ({
                user: null
              }),
              getters: {
                isLoggedIn: (state) => !!state.user,
              },
              actions: {
                async register(newUser) {
                  try {
                    const data = await $fetch('/api/auth/register', {
                      method: 'POST',
                      body: JSON.stringify(newUser),
                      headers: {
                        'Content-Type': 'application/json'
                      }
                    });
            
                    this.user = data;
                    // if (process.client) {
                    //   localStorage.setItem('user', JSON.stringify(data));
                    // }
                  } catch (error) {
                    throw error.data;
                  }
                },
                async login(newUser) {
                  try {
                    const data = await $fetch('/api/auth/login', {
                      method: 'POST',
                      body: JSON.stringify(newUser),
                      headers: {
                        'Content-Type': 'application/json'
                      }
                    });
                
                    this.user = data.user;
                    if (process.client) {
                      localStorage.setItem('user', JSON.stringify(data.user));
                    }
                  } catch (error) {
                    throw error.data;
                  }
                },
                logout() {
                  this.user = null;
                  if (process.client) {
                    localStorage.removeItem('user');
                  }
                },
                async initializeUser() {
                  if (process.client) {
                    const storedUser = localStorage.getItem('user');
                    if (storedUser) {
                      this.user = JSON.parse(storedUser);
                    }
                  }
                }
              },
              persist: true,
            });

            dashboard.vue

            <script setup>
            import { useAuthStore } from "~/store/authStore";
            
            const userStore = useAuthStore();
            
            const activeTab = ref("general");
            const editMode = ref(false);
            const userInfo = reactive({
              username: "",
              email: "",
              password: "",
            });
            
            const toggleEditMode = () => {
              editMode.value = !editMode.value;
            };
            
            const cancelEditMode = () => {
              editMode.value = false;
              userInfo.username = userStore.user.username;
              userInfo.email = userStore.user.email;
              userInfo.password = userStore.user.password;
            };
            
            onMounted(() => {
              userInfo.username = userStore.user.username;
              userInfo.email = userStore.user.email;
              userStore.initializeUser();
            });
            </script>