Как исправить проблему синхронизации id пользователя в Pinia при обновлении localStorage после аутентификации?

Ссылка скопирована
1 ответ

Суть логики:
В данном шаблоне комментария, если пользователь аутентифицирован, то его комментарии подкрасится в такой цвет: bg-indigo-100, если нет, то будет bg-white. Логика работает по принципу: comment.authorId === productCommentsStore.loginId, id пользователя из бд === id пользователя из бд записанный в локальное хранилище.
id пользователя из бд я получаю с помощью запроса handleAddComment в store комментариев, а id пользователя из локального хранилища я получаю в другом store при аутентификации в данной функции:
handleSubmit
В целом работает но после перезагрузки страницы, до перезагрузки при запросе handleAddComment я получаю актуальный loginId, но по какой то причине в store комментариев я получаю не актуальный loginId:

const loginId = localStorage.getItem('loginId') || 0; console.log('loginId: ', loginId) // выводит предыдущий id

const loginId = localStorage.getItem('loginId') || 0; console.log('loginId: ', loginId) // выводит предыдущий id

, а точнее loginId предыдущего пользователя, такое чувство будто localStorage не успел обновить данные в pinia. Где то потерялась реактивность?
Вот код:
spoiler

<template>     <div :class="{              'bg-white': comment.authorId !== productCommentsStore.loginId,             'bg-indigo-100': comment.authorId === productCommentsStore.loginId,             'mr-10': productCommentsStore.loginId && comment.authorId !== productCommentsStore.loginId,             'ml-10': productCommentsStore.loginId && comment.authorId === productCommentsStore.loginId,             'p-4': true,             'shadow-md': true,             'rounded-lg': true,             'mt-4': true,             'relative': true         }"          @click="productCommentsStore.isEditingComment(comment)              ? productCommentsStore.handleClickOutside()              : null" >     </div> </template> <script setup> import { defineProps } from 'vue'; import { useProductCommentsStore } from '../stores/productComments.js'; import { useModalStore } from '../stores/modal.js';  const modalStore = useModalStore(); const productCommentsStore = useProductCommentsStore();  const props = defineProps({     comment: {         type: Object,          required: true,     }, }) </script>   import { ref} from 'vue'; import { defineStore } from 'pinia'; import { useRoute } from 'vue-router';  export const useProductCommentsStore = defineStore('productComments', () => {   const comments = ref([]);    const commentId = ref(null);       const login = localStorage.getItem('login') || '';    const loginId = localStorage.getItem('loginId') || 0;      console.log('loginId: ', loginId) //извлекается loginId предыдущего аккаунта    const handleAddComment = async (textarea) => {     const comment = {         authorId: loginId,          author: login,         productId: productId.value,         content: textarea,     } 	     const requestOptions = {     method: 'POST',     headers: {       'Content-Type': 'application/json'     },       body: JSON.stringify(comment),     };      const response = await fetch('http://localhost:5000/api/comments', requestOptions);     if(response.ok) {       const createdComment = await response.json();       comments.value.push(createdComment);     }   }    return {       comments,       commentId,   } })  export const useLoginStore = defineStore('login', () => {  const handleSubmit = async () => {              const login =  ref('');     const password = ref('');              const loginData = {             login: login.value,             password: password.value,         }         try {             const resp = await loginUser(loginData);             const token = resp.token;             const login = resp.login;              const id = resp._id;             localStorage.setItem('loginId', id);  //записывается правильный loginId из бд          } catch (error) {             console.error('Error:', error);         }     }  		return {          login,         password,     } })

<template> <div :class="{ 'bg-white': comment.authorId !== productCommentsStore.loginId, 'bg-indigo-100': comment.authorId === productCommentsStore.loginId, 'mr-10': productCommentsStore.loginId && comment.authorId !== productCommentsStore.loginId, 'ml-10': productCommentsStore.loginId && comment.authorId === productCommentsStore.loginId, 'p-4': true, 'shadow-md': true, 'rounded-lg': true, 'mt-4': true, 'relative': true }" @click="productCommentsStore.isEditingComment(comment) ? productCommentsStore.handleClickOutside() : null" > </div> </template> <script setup> import { defineProps } from 'vue'; import { useProductCommentsStore } from '../stores/productComments.js'; import { useModalStore } from '../stores/modal.js'; const modalStore = useModalStore(); const productCommentsStore = useProductCommentsStore(); const props = defineProps({ comment: { type: Object, required: true, }, }) </script> import { ref} from 'vue'; import { defineStore } from 'pinia'; import { useRoute } from 'vue-router'; export const useProductCommentsStore = defineStore('productComments', () => { const comments = ref([]); const commentId = ref(null); const login = localStorage.getItem('login') || ''; const loginId = localStorage.getItem('loginId') || 0; console.log('loginId: ', loginId) //извлекается loginId предыдущего аккаунта const handleAddComment = async (textarea) => { const comment = { authorId: loginId, author: login, productId: productId.value, content: textarea, } const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(comment), }; const response = await fetch('http://localhost:5000/api/comments', requestOptions); if(response.ok) { const createdComment = await response.json(); comments.value.push(createdComment); } } return { comments, commentId, } }) export const useLoginStore = defineStore('login', () => { const handleSubmit = async () => { const login = ref(''); const password = ref(''); const loginData = { login: login.value, password: password.value, } try { const resp = await loginUser(loginData); const token = resp.token; const login = resp.login; const id = resp._id; localStorage.setItem('loginId', id); //записывается правильный loginId из бд } catch (error) { console.error('Error:', error); } } return { login, password, } })

Дополнительно:

Решил проблему, я так понял что суть была в рассинхроне данных между двумя сторами. Решил таким образом:
spoiler

export const useLoginStore = defineStore('login', () => {      const productCommentsStore = useProductCommentsStore();     const updateLoginId = (newLoginId) => {         productCommentsStore.setLoginId(newLoginId);// передача id другому стору      };          const handleSubmit = async () => {                  const loginData = {             login: login.value,             password: password.value,         }         try {             const resp = await loginUser(loginData);             const token = resp.token;             const login = resp.login;              const id = resp._id;             localStorage.setItem('loginId', id);               updateLoginId(id);                   respAuthMessage.value = resp;             updateAuthentication(token, login);                  if(isAuthenticated.value) {                 router.push('/');             }         } catch (error) {             console.error('Error:', error);         }     }     return {     	...     } })  //-------//  export const useProductCommentsStore = defineStore('productComments', () => {   const loginId = ref(localStorage.getItem('loginId') || null);       const setLoginId = (newLoginId) => {     loginId.value = newLoginId; //присваивание актуального id    }; 	   return {   	setLoginId   } })

export const useLoginStore = defineStore('login', () => { const productCommentsStore = useProductCommentsStore(); const updateLoginId = (newLoginId) => { productCommentsStore.setLoginId(newLoginId);// передача id другому стору }; const handleSubmit = async () => { const loginData = { login: login.value, password: password.value, } try { const resp = await loginUser(loginData); const token = resp.token; const login = resp.login; const id = resp._id; localStorage.setItem('loginId', id); updateLoginId(id); respAuthMessage.value = resp; updateAuthentication(token, login); if(isAuthenticated.value) { router.push('/'); } } catch (error) { console.error('Error:', error); } } return { ... } }) //-------// export const useProductCommentsStore = defineStore('productComments', () => { const loginId = ref(localStorage.getItem('loginId') || null); const setLoginId = (newLoginId) => { loginId.value = newLoginId; //присваивание актуального id }; return { setLoginId } })

Ответы:

Вы в курсе, что в localStorage можно только строки хранить? Если у комментария id числовой, то сравнивая с ID из localStorage будет всегда false.

localStorage.setItem('loginId', 123); // Записываем число localStorage.getItem('loginId'); // А получаем внезапно строку "123" ))

localStorage.setItem('loginId', 123); // Записываем число localStorage.getItem('loginId'); // А получаем внезапно строку "123" ))

  • id пользователя из запроса приходит как string, и при getItem я получаю тоже string. Я даже перепроверил.
Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Артём Dev Ответ

Для решения проблемы синхронизации id пользователя в Pinia при обновлении localStorage после аутентификации, вам следует использовать слушатели событий в Pinia.

Прежде всего, убедитесь, что вы импортировали Pinia и создали экземпляр хранилища. Затем вы можете добавить слушателя событий, который будет обновлять id пользователя в хранилище Pinia при изменении localStorage.

Пример кода:

import { defineStore } from 'pinia';
 
const store = defineStore({
  id: 'user',
  state: () => ({
    userId: localStorage.getItem('userId') || null,
  }),
  actions: {
    setUserId(userId) {
      this.userId = userId;
      localStorage.setItem('userId', userId);
    },
    syncUserId() {
      const userId = localStorage.getItem('userId');
      if (userId !== this.userId) {
        this.setUserId(userId);
      }
    },
  },
});
 
// Добавляем слушателя событий для обновления id пользователя
window.addEventListener('storage', () => {
  store.syncUserId();
});

import { defineStore } from 'pinia'; const store = defineStore({ id: 'user', state: () => ({ userId: localStorage.getItem('userId') || null, }), actions: { setUserId(userId) { this.userId = userId; localStorage.setItem('userId', userId); }, syncUserId() { const userId = localStorage.getItem('userId'); if (userId !== this.userId) { this.setUserId(userId); } }, }, }); // Добавляем слушателя событий для обновления id пользователя window.addEventListener('storage', () => { store.syncUserId(); });

Этот код создаст хранилище Pinia с состоянием userId, которое будет автоматически синхронизироваться с localStorage. Слушатель событий будет отслеживать изменения в localStorage и обновлять id пользователя в хранилище Pinia.

Таким образом, при каждом обновлении localStorage после аутентификации, id пользователя будет автоматически синхронизироваться с вашим хранилищем Pinia.

Надеюсь, это поможет вам решить проблему синхронизации id пользователя в Pinia после обновления localStorage. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно