Quiero usar vuex para almacenar algunos datos obtenidos del servidor que mi aplicación SPA Vue necesitará en diferentes páginas, esto para evitar que se realice una nueva solicitud de ajax cada vez que el usuario cambie la página del producto (es un comercio electrónico sin cabeza).
Mi pregunta es simple, ¿cómo puedo enviar los datos obtenidos a una matriz definida en mi tienda? ¿Cómo obtendré los datos en mis componentes? Estoy escribiendo el código pero no estoy seguro si lo he hecho bien.
import { createStore } from 'vuex' import axios from 'axios' export default createStore({ state: { products: [] }, mutations: { updateProductsData(state, products){ // not sure how to proceed here } }, actions: { fetchProducts(){ const baseURL = 'https://www.example.com/app/index.php/wp-json/shop/v1/products'; let productsData = []; axios.get(baseURL).then( response => { response.data.forEach( el => { console.log(el); let details = { id: el.id, slug: el.slug, name: el.name, price: el.price, description: el.description, short_description: el.short_description } productsData.push(details); }); store.commit('updateProductsData', productsData); }).catch( e => console.log(e) ); } } })En mis componentes donde necesito cargar los datos tengo este código
export default { name: 'Home', data(){ return { loaded: false, offers: [], } }, created(){ }, mounted(){ this.$store.dispatch('fetchProducts').then( res => this.offers.push(res) ) }, }Actualice la acción de su tienda para devolver la matriz de datos de productos.
fetchProducts() { const baseURL = "https://www.example.com/app/index.php/wp-json/shop/v1/products"; const productsData = []; axios .get(baseURL) .then(response => { response.data.forEach(el => { console.log(el); const details = { id: el.id, slug: el.slug, name: el.name, price: el.price, description: el.description, short_description: el.short_description }; productsData.push(details); }); }) .catch(e => { console.log(e); }); return productsData; }Ahora, cuando envíe la acción desde su componente, los resultados se devolverán.
Mejor manera
Una mejor manera de hacer esto sería simplemente devolver la llamada de Axios, que es una Promesa, que puede await en su componente.
Como alternativa, puede envolver la llamada de Axios en su propia Promesa y resolverla solo con los datos, manejando errores y objetos en su componente para obtener mejores comentarios al usuario, de la siguiente manera:
fetchProducts() { const baseURL = "https://www.example.com/app/index.php/wp-json/shop/v1/products"; return new Promise((resolve, reject) => { axios .get(baseURL) .then(response => { resolve(response.data); }) .catch(e => { reject(e); }); }); }Forma apropiada
Para usar la tienda correctamente, debe implementar su acción VueX como:
fetchProducts({ commit }) { const baseURL = "https://www.example.com/app/index.php/wp-json/shop/v1/products"; axios .get(baseURL) .then(response => { commit("setProductData", res.data); }) .catch(e => { console.log(e); }); }); }Añade la siguiente mutación:
setProductData(state, productData) { state.products = productData.map(product => { return { id: product.id, slug: product.slug, name: product.name, price: product.price, description: product.description, short_description: product.short_description }; }); }Actualice su componente para que sea:
export default { name: "Home", data() { return { loaded: false, offers: [] }; }, computed: { products() { return this.$store.state.products; } }, mounted() { this.$store.dispatch("fetchProducts"); } };Para obtener por ID, agregue una propiedad calculada como:
findProductById(id) { return this.products.find(product => product.id === id); }Dentro de su mutación updateProductsData use state.products = [...products] para agregar sus productos cargados a su estado
Consulte https://www.vuemastery.com/courses/vuex-fundamentals/vuex4-intro-to-vuex para obtener una breve introducción a Vuex
Puede consultar el documento de Vuex sobre el uso de acciones y mutaciones https://vuex.vuejs.org/guide/actions.html . esta detallado...
Como sugiere Vuex, debe poner operaciones asíncronas en acciones (como obtener datos del servidor en su ejemplo). Luego, debe cometer una "mutación" para usar los datos obtenidos para establecer su estado como el código que se proporciona a continuación.
import { createStore } from 'vuex' import axios from 'axios' export default createStore({ state: { products: [] }, mutations: { updateProductsData(state, products){ // here set your state state.products = products } }, actions: { fetchProducts({commit}){ const baseURL = 'https://www.example.com/app/index.php/wp-json/shop/v1/products'; let productsData = []; axios.get(baseURL).then( response => { response.data.forEach( el => { console.log(el); let details = { id: el.id, slug: el.slug, name: el.name, price: el.price, description: el.description, short_description: el.short_description } productsData.push(details); }); store.commit('updateProductsData', productsData); }).catch( e => console.log(e) ); } } })Si desea utilizar el estado en sus componentes, puede ponerlo en el atributo calculado.
export default { name: 'Home', data(){ return { loaded: false, } }, computed:{ // map this.offers to store.state.products offers(){ return this.$store.state.products } }, created(){ }, mounted(){ // dispatch 'fetchProducts' to fetch data this.$store.dispatch('fetchProducts') }, }