✅ Vue 2: las propiedades calculadas se actualizan después de la mutación de la tienda vuex.
❌ Vue 3: las propiedades calculadas no se actualizan después de la mutación de la tienda vuex.
Propósito: Obtener publicaciones de Firestore. Agregar a "postsArray". Cometer mutación.
Nota: La función "getNextPosts" se llama desde un observador de intersección (en funcionamiento) que permite el desplazamiento infinito.
const postsArray: Array<string> = []; const vuexStore = createStore({ state: { posts: [] }, actions: { // See https://firebase.google.com/docs/firestore/query-data/query-cursors#paginate_a_query getFirstPosts({ commit }) { const getFirstPosts = async () => { const firstPostsQuery = firestore.collection("posts").limit(3); // Get FIRST posts. const firstPosts = await firstPostsQuery.get(); // Add to postsArray. for (const doc of firstPosts.docs) { postsArray.push(doc.id); } // Add to vuex store. commit("addFirstPostsToVuex", postsArray); // Set reference. lastPostDownloaded = firstPosts.docs[2]; // 3rd post. }; getFirstPosts(); }, getNextPosts({ commit }) { const getNextPosts = async () => { const nextPostsQuery = firestore .collection("posts") .startAfter(lastPostDownloaded) .limit(2); // Get NEXT posts. const nextPosts = await nextPostsQuery.get(); // Add to postsArray. for (const doc of nextPosts.docs) { postsArray.push(doc.id); } // Add to vuex store. commit("addNextPostsToVuex", postsArray); // Update reference. lastPostDownloaded = nextPosts.docs[1]; // 2nd post. }; getNextPosts(); } }, mutations: { addFirstPostsToVuex(state, value) { state.posts = value; }, addNextPostsToVuex(state, value) { state.posts = value; } } }); export default ({ computed: { posts() { // List rendering. return vuexStore.state.posts; } } }); <template> <div id="feed"> <article class="post" v-for="post in posts" v-bind:key="post.id"> <header class="info"> {{ post }} </header> </article> </div> </template>Esto podría solucionarse si usa la función mapState para asignar el estado de la tienda al estado del componente Vue.
En el código anterior, eso sería algo como:
import { mapState } from "vuex"; import { defineComponent } from "vue"; export default defineComponent({ computed: { ...mapState(["posts"]) } });El v-for debería funcionar bien ahora.
Referencia: https://vuex.vuejs.org/guide/state.html y https://scrimba.com/scrim/c8Pz7BSK?pl=pnyzgAP
Hay una ligera diferencia en la definición del estado dentro de Vuex entre la versión anterior y la nueva.
**In Vuex3 state was just a prop with an Object while in Vuex4 it has return an Object or a function which returns an Object.**
Al migrar de V3 a V4, es posible que al principio no note la diferencia porque el estilo V3 también funciona en V4. La diferencia se muestra cuando tienes módulos y tienes múltiples instancias de ellos. Entonces el estado tiene que ser una función que devuelva un objeto para evitar la contaminación del estado (como comenta tony19).
Módulos:
// Vuex 3.x Module const moduleVUEX3 = { export const state = { ... } } // Vuex 4.x Module const moduleVUEX4 = { export const state = () => ({ ... }) }Tienda única:
// Vuex 3.x import Vuex from 'vuex' const store = new Vuex.Store({ state: { ... } }) // Vuex 4.x import { createStore } from 'vuex' const store = createStore({ state() { return { ... } } })La solución a esta pregunta sería:
const vuexStore = createStore({ state: return { posts: [] } })Podría intentar eliminar postsArray, supongo que tiene algo que ver con la reactividad.
intente cambiar la mutación a
addFirstPostsToVuex(state, docId) { state.posts.push(docId); }y luego en la acción que haces
for (const doc of firstPosts.docs) { commit("addFirstPostsToVuex",doc.id); }Normalmente lo uso así
<script setup lang="ts"> import { computed, reactive,ComputedRef } from "vue"; import { useStore } from "vuex"; interface State { shadow: ComputedRef<boolean> } const store = useStore(); const state = reactive<State>({ shadow: computed(() => store.state.shadow), )} </script>Cuando cambie el estado en vuex, la página responderá a tiempo, espero que pueda ayudarlo