Chupachar
@Chupachar
front-end dev

Почему не удается получить актуальное значение переменной из Pinia в компоненте?

Не удается получить search.value из pinia.
Имеется 2 компонента поиска:

Родительский - TheSearch.vue
<template>
    <div :class="searchBlockClasses">
        <div class="relative flex w-full">
            <TheSearchInput @searchData="updateSearchQuery"/>
            <BaseButton >Search</BaseButton>
        </div>
        <TheSearchResults :results="search.searchQuery"/>
    </div>
</template>
<script setup>
import { styles } from '../styles.js';
import { defineEmits } from 'vue';
import TheSearchInput from './TheSearchInput.vue';
import BaseButton from '../components/BaseButton.vue';
import TheSearchResults from './TheSearchResults.vue';
import { useSearchStore } from '../stores/search.js';

const { search, updateSearchQuery } = useSearchStore();

const emit = defineEmits(['searchData'])

const { searchBlockClasses } = styles;

</script>

Дочерний - TheSearchInput.vue
<template>
        <BaseInput 
            class="w-100"
            label="Search..."
            type="text"
            v-model.trim="search"
            @input="updateSearch"
            search/>
            <span class="absolute top-0 right-20 h-full px-3 focus:outline-none">X</span>
</template>
<script setup>
import { styles } from '../styles.js';
import { defineEmits } from 'vue';
import BaseInput from '../components/BaseInput.vue';
import { useSearchStore } from '../stores/search.js';

const { search } = useSearchStore();

const emit = defineEmits(['searchData'])

const updateSearch = () => {
  emit('searchData', search.value);
};

const { searchBlockClasses } = styles;
</script>

Также имеется pinia такого вида
import { ref } from 'vue';

export const useSearchStore = () => {
    const search = ref('')

    const setSearch = (value) => {
        search.value = value
    }
    
    const updateSearchQuery = (value) => {
        setSearch(value)
    };
    return {
        search,
        updateSearchQuery,
    }
}

Всё работает хорошо и я в vue devtools получаю на всех компонентах актуальное значение search, далее я хочу из стора вытащить search в компонент TheMain.vue для того, чтобы я мог сделать поиск по товарам, вот приблизительный код:

TheMain.vue
<template>
  <div class="flex mt-10">
      <div class="relative">
  <TheMainFilter 
    @checkValue="applyFilter" 
    @selectValue="selectedSort" 
    @updatePriceRange="handleUpdatePriceRange"
  />
  </div>
    <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
      <TransitionGroup name="product-list">
        <BaseProductCard 
          v-for="(product, index) in sortedAndFilteredData" 
          :key="index" 
          :product="product" 
          @productAdded="addToBasket"
        />
      </TransitionGroup>
    </div>
</div>
</template>
<script setup>
import TheMainFilter from './TheMainFilter.vue';
import BaseProductCard from './BaseProductCard.vue';
import { useAllMainFiltersStore } from '../stores/allMainFilters.js';
import { useSearchStore } from '../stores/search.js';
import { ref, watch, nextTick, computed } from 'vue';

const { 
  handleUpdatePriceRange, 
  applyFilter, 
  selectedSort, 
  addToBasket, 
  sortedAndFilteredData 
} = useAllMainFiltersStore()

const { 
  search, 
  updateSearchQuery 
} = useSearchStore(); 

console.log(search.value) // единоразово выводится search из pinia

watch(
  () => search.value,
  (newSearchValue) => {
    nextTick(() => {
      console.log(newSearchValue); // не работает, вообще не выводит в консоль
    });
  },
  { deep: true }
);
</script>


Я не могу добраться до search из Pinia почему-то даже с помощью watch, в чем может быть проблема?
В девтулзах компонента TheMain.vue search: "" вообще пустой при вводе чего-либо в input, ну или выводит единоразово то, что я статично ввел в pinia search: "test", как будто реактивность растерялась по дороге.
  • Вопрос задан
  • 217 просмотров
Решения вопроса 2
@iljaGolubev
и так же имеется pinia такого вида:

где там pinia? - у вас просто composeable.
каждый раз когда вы вызываете const {search} useSearchStore () выполняется const search = ref(''). т.е. это новый search.
А в первых двух компонентах вы это не заметили

потому что @searchData = "updateSearchQuery" - обновляете свой отдельный инстанс search.
И вообще неработающий код показали... или неполностью (search.searchQuery - что такое?)


// вот pinia
export const useSearchStore = defineStore('search', () => {
  const search= ref('')
 function updateSearch(v) {
    search.value=v
  }

  return { search, updateSearch }
})
Ответ написан
Комментировать
0xD34F
@0xD34F Куратор тега Vue.js
имеется pinia такого вида
<...>
export const useSearchStore = () => {

Ну и где тут Pinia? Где вызов defineStore?

const { search, updateSearchQuery } = useSearchStore();

Так нельзя:

Note that store is an object wrapped with reactive, meaning there is no need to write .value after getters but, like props in setup, we cannot destructure it

Вы вообще как, документацию пробовали открывать?

Исправляем:

Стор:

const useSearchStore = defineStore('search', () => {
  const search = ref('');
  const setSearch = val => search.value = val;
  return { search, setSearch };
});

Компонент search input:

const searchStore = useSearchStore();
const search = computed({
  get: () => searchStore.search,
  set: searchStore.setSearch,
});

<input v-model.trim="search">

Компонент search:

Не надо слушать никаких событий из search input, не надо трогать стор, уберите это всё отсюда.

Корневой компонент:

const searchStore = useSearchStore(); 
watch(() => searchStore.search, val => console.log(val));
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы