Как обновить несколько компонентов Vue 3 при изменении массива Pinia

Я не могу заставить несколько компонентов, обращающихся к одному и тому же хранилищу, реагировать на обновления, пока я не запутаюсь с элементом dom, чтобы вызвать новый рендеринг.

В моем магазине Pinia у меня есть массив и метод обновления:

    let MyArray: IMyItem[] = [
    { id: 1,
      name: "First Item",
    }, ....
    let SelectedItem = MyArray[0]
    const AddItem = ( n: string, ) => {       
        MyArray.push({ id: createId(), name: n, });
        };

    return { MyArray, SelectedItem, AddItem  }

В одном компоненте Vue у меня есть ввод текста и кнопка для вызова метода хранилища:

    function handle() {store.AddItem(name.value));

В другом компоненте Vue для того же родителя я использую цикл for для отображения возможности выбора элемента:

    <div v-for = "item in store.MyArray">
          <input type = "radio"...

Никаких изменений с этими усилиями:

    const { MyArray } = storeToRefs(store);
    const myArray = reactive(store.MyArray);
    // also watching from both components...
    watch(store.MyArray, (n, o) => console.dir(n));
    // also... lots of other stuff.
    const myArray = reactive(store.MyArray);
    watch(myArray, (n, o) => console.dir(n));

Я также экспериментировал с <form @submit.prevent = "handle"> запуском nextTick, добавляя возврат строки в метод хранилища.

Я предполагаю, что причина, по которой щелчок вокруг заставляет его работать, заключается в том, что я меняю магазин SelectedItem, и его реактивность требует повторного рендеринга, как это v-model для ярлыка.

В документах говорится, что Array.push должен выполнять свою работу... просто он не связан таким же образом при использовании в v-for.

Что необходимо для запуска обновления dom? Спасибо! ?

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

Nechoj 29.04.2022 18:35

не могли бы вы показать свой магазин пиния

Ifaruki 29.04.2022 18:48

Верхний блок кода — это магазин. Он предоставляет 3 вещи: функцию MyArray, SelectedItem и AddItem.

ScumSprocket 29.04.2022 19:56
let MyArray: IMyItem[] = [ - это не реактивно, это ошибка. const myArray = reactive(store.MyArray) - не имеет смысла, потому что store.MyArray уже должен быть реактивным в этот момент
Estus Flask 29.04.2022 21:45
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
129
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как указывалось в комментариях, основная проблема заключается в том, что состояние вашего магазина не объявлено с помощью API Reactivity, поэтому изменения состояния не вызовут срабатывания наблюдателей и не вызовут повторную визуализацию.

Решение состоит в том, чтобы объявить MyArray как reactive и SelectedItem как ref:

// store.js
import { defineStore } from 'pinia'
import type { IMyItem } from './types'
import { createId } from './utils'
         ?      ?
import { ref, reactive } from 'vue'

export const useItemStore = defineStore('item', () => {
                   ?
  let MyArray = reactive([{ id: createId(), name: 'First Item' }] as IMyItem[])
                     ?
  let SelectedItem = ref(MyArray[0])
  const AddItem = (n: string) => {
    MyArray.push({ id: createId(), name: n })
  }

  return { MyArray, SelectedItem, AddItem }
})

Если вы используете storeToRefs(), обязательно установите свойство ref.value при обновлении SelectedItem:

// MyComponent.vue
const store = useItemStore()
const { SelectedItem, MyArray } = storeToRefs(store)
const selectItem = (id) => {
                 ?
  SelectedItem.value = MyArray.value.find((item) => item.id === id)
}

Но в этом случае проще использовать реквизиты напрямую из store:

// MyComponent.vue
const store = useItemStore()
const selectItem = (id) => {
  store.SelectedItem = store.MyArray.find((item) => item.id === id)
}

демо

Другие вопросы по теме