Vuex, manejador de estados en Vue, como Redux en ReactJS

Vuex es un patrón de gestión de estado para aplicaciones Vue.js. Sirve como una tienda centralizada para todos los componentes de una aplicación, con reglas que aseguran que el estado solo pueda mutarse de manera predecible

¿Qué es un “patrón de gestión del estado”?

La administración del estado puede verse como la capacidad de administrar datos compartidos entre componentes múltiples y a menudo no relacionados.

Esta es la idea básica detrás de Vuex, inspirada en Flux, Redux y The Elm Architecture. A diferencia de los otros patrones, Vuex también es una implementación de biblioteca diseñada específicamente para Vue.js para aprovechar su sistema de reactividad granular para actualizaciones eficientes.

Esquema donde Vuex aplica el patrón de gestión de estados

En el centro de cada aplicación Vuex está el store. Un “store” es básicamente un contenedor que contiene el estado de su aplicación. Hay dos cosas que hacen que una store Vuex sea diferente de un objeto global simple:

Los store Vuex son reactivas. Cuando los componentes de Vue recuperan el estado, se actualizarán de manera reactiva y eficiente si cambia el estado de el store.

No puede mutar directamente el estado del store. La única forma de cambiar el estado del store es mediante la confirmación explícita de mutaciones. Esto garantiza que cada cambio de estado deje un registro rastreable y habilite herramientas que nos ayuden a comprender mejor nuestras aplicaciones.

Aplicación del patrón de gestión de estados en el desarrollo de un Login

//Contiene los métodos de loguin
import  UserService from '@/core/services/user.service';
import  router  from '@/core/router';
//Obtener el usuario guardado en el local storage
//Significa que se tiene la información de la sessión existente
//(userID, token de acceso, etc.)
const user = JSON.parse(localStorage.getItem('user'));
//Definición del estado inicial
const initialState = user
    ? { status: { loggedIn: true }, user }
    : { status: {}, user: null };
//Definición del store
export const authentication = {
    //Esta opción es para poder diferencia este store del resto
    //y hacer referencia a este en los componentes a través de su nombre
    namespaced: true,
    //Inicializar estado iniciar
    state: initialState,
    //Definir las acciones
    //Estas son invocadas desde los componentes para cambiar el estado de las variables definidas
    //en el initialState
    actions: {
        login({ dispatch, commit }, { username, password }) {
            //La llamada del metodo commit ejecuta una mutación
            //Donde se le pasa el identificador de la mutación
            //y los nuevos valores de los state (si son requeridos)
            commit('loginRequest', { username });
            let userService = new UserService()
            //Llamada al servicio de login
            userService.login(username, password)
                .then(
                    user => {
                        commit('loginSuccess', user);
                        router.history.push('/');
                    },
                    error => {
                        commit('loginFailure', error);
                    }
                );
        },
        logout({ commit }) {
            let userService = new UserService()
            userService.logout();
            commit('logout');
        }
    },
    //Mutaciones son las encargadas de cambiar el valor a los state
    mutations: {
        loginRequest(state, user) {
            state.status = { loggingIn: true };
            state.user = user;
        },
        loginSuccess(state, user) {
            state.status = { loggedIn: true };
            state.user = user;
        },
        loginFailure(state) {
            state.status = {};
            state.user = null;
        },
        logout(state) {
            state.status = {};
            state.user = null;
        }
    }
}

Este sería el servicio de login

import Service from './base.service'
export default class UserService {
    constructor() {
        this.service = new Service()
    }
    login(username, password) {
        return this.service.post(`account/signin`, { username: username, password: password, remember: true })
            .then(response => {
                if (response.data.access_token) {
                    localStorage.setItem('user', JSON.stringify(response.data));
                }
               return response.data
            });
    }
    logout() {
        let user = JSON.parse(localStorage.getItem('user'))
        return this.service.post(`account/signout?r=${user.access_token}`,{})
            .then(response => {
                if (response.data.access_token) {
                    localStorage.removeItem('user');
                }
               return response.data
            });
    }
}

A continuación el componente Login

<template>
  <v-app id="inspire">
    <v-content>
      <v-container class="fill-height" fluid>
        <v-row align="center" justify="center">
          <v-col cols="12" sm="8" md="4">
            <v-card class="elevation-12">
              <v-toolbar color="primary" dark flat>
                <v-toolbar-title>Login form</v-toolbar-title>
                <v-spacer></v-spacer>
              </v-toolbar>
              <v-card-text>
                <v-form>
                  <v-text-field
                    label="Login"
                    name="email"
                    v-model="email"
                    prepend-icon="person"
                    type="text"
                  ></v-text-field>
                  <v-text-field
                    id="password"
                    label="Password"
                    name="password"
                    v-model="password"
                    prepend-icon="lock"
                    type="password"
                  ></v-text-field>
                </v-form>
              </v-card-text>
              <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn v-on:click="login" color="primary">Login</v-btn>
              </v-card-actions>
            </v-card>
          </v-col>
        </v-row>
      </v-container>
    </v-content>
  </v-app>
</template>
<script>
export default {
  data() {
    return {
      email: "",
      password: ""
    };
  },
  computed: {
    loggingIn() {
      //Accesso global a los state de la aplicación
      return this.$store.state.authentication.status.loggingIn;
    }
  },
  methods: {
    login: function() {
      const email = this.email;
      const password = this.password;
      this.$store
        .dispatch("authentication/login", { username: email, password })
        .then(() => {
          //this.$router.push('/')
        });
    }
  }
};
</script>

En fin primero se define el store del módulo dentro de la aplicación con los estados iniciales que responden a las variables que se usan dentro de un componente y que mediante la interacción del usuario pueden cambiar de valor, dentro del store se definen las actions con son las que se invocan desde el componente para cambiar el valor a un state parandole los valores requeridos:

this.$store
.dispatch(“authentication/login”, { username: email, password })

y finalmente mediante el método commit se ejecuta una mutations para hacer efectivo el cambio de estado.

Espero te sea útil, si crees que así fue puedes invitarme un café y/o dejar tus comentarios.

1 thought on “Vuex, manejador de estados en Vue, como Redux en ReactJS

Leave a Reply

Your email address will not be published. Required fields are marked *