Hola.
Me sale el siguiente error. No se que podrá ser.
Bienvenida al curso
Qué es Vue y bienvenida al curso
VueCli, configuración inicial del proyecto y consumo del API de Blizzard
Crea tu app con el Vue CLI
Blizzard Developer Portal
Comandos del Proyecto
Instalar librerías
Carpeta API
Obtener el token
Creación de los componentes y layouts de nuestro proyecto
Componente Loading
¡Limpiemos el proyecto!
Layouts y Vuex Modules
Assets
NavBar y Footer
Refactorizando
Home Page
Vue Router
Vista Profile
¡Más Componentes!
Listado de Héroes
Progreso (Actos)
Stats y Tiempo Jugado
Cerrando vista Profile
Hero View
Agregando funcionalidades avanzadas a nuestro proyecto
Componentes asíncronos
Objetos del Héroe
Custom Directives
Netlify
About y Error
En el fichero main.js
tenemos la instancia principal de Vue. Aquí es donde vamos a trabajar para obtener el token y posteriormente guardarlo en el Store con Vuex.
El proceso que hay que seguir es el siguiente:
created
, hay que llamar a la función que acabamos de crear para obtener el tokenExisten varias formas de hacer esto. Vamos a aprender a llamar a una acción (dispatch) de Vuex desde la instancia principal de Vue, que aunque no es la mejor forma de hacerlo, a efectos prácticos es muy efectivo.
Creamos una función llamada init dentro de methods y el único código que vamos a poner de momento es un console.log
. A continuación, llamamos a esta función desde el hook created.
Tu código se vería así:
// main.js
new Vue({
router,
store,
methods: {
// Nuestra función
init () {
console.log('Hola 🌝')
}
},
// Hook created
created () {
this.init()
},
render: h => h(App)
}).$mount('#app')
Ve al navegador, abre la consola y fíjate que se imprima el mensaje.
En nuestra función init vamos a llamar a otra función que estará en Vuex. Vamos a crear dicha función en el módulo correspondiente.
Para ello, abrimos la carpeta del store de nuestra app /src/store
y creamos un nuevo directorio llamado modules
. Dentro, creamos un archivo JavaScript: oauth.js
. Deberías tener algo como esto:
📂 /src
└──📂 /store
├──📂 /modules
│ └── oauth.js
└── index.js
Como buenos profesionales que somos, vamos a separar nuestro store en módulos (aunque, para este proyecto tan pequeño, no sea necesario), para tenerlo mejor ordenado, y, además, estaremos usando namespaces, para que nos sea más fácil gestionar el estado en caso de que nuestro proyecto crezca, por lo tanto, más escalable.
📗 Puedes leer más acerca de los módulos en Vuex en este enlace: https://vuex.vuejs.org/guide/modules.html
Abrimos el recién creado módulo oauth.js
y escribimos lo siguiente:
// oauth.js
// Importamos nuestra función que obtiene el token
// @ es un alias para /src
import * as oauth from '@/api/oauth'
// Creamos el objeto con "Espacio de Nombres"
export default {
namespaced: true,
state: {},
mutations: {},
actions: {}
}
Estos son los tres bloques que vamos a usar en nuestro módulo:
Necesitamos hacer varios cambios en nuestro código. Lo primero es crear una variable que guarde el token, que por defecto tendrá null
como valor. Lo creamos de la siguiente forma:
state: {
accessToken: null
},
Lo segundo es crear la función que cambie (mute) el estado que le estemos pasando. Esta función recibe 2 parámetros como argumentos: el estado de nuestro módulo y el payload (o valor que queremos guardar). Con esto podemos indicarle que cambie el accessToken
por el valor que le pasemos en el payload. Cuando lo queramos borrar, le pasamos null
.
mutations: {
SET_ACCESS_TOKEN (state, payload) {
state.accessToken = payload
}
}
Ya tienes la variable y la función que cambia el valor de dicha variable. Veamos ahora cómo se obtiene el token y cómo se guarda en el estado de nuestra aplicación. Entra en juego el bloque de actions:
actions: {
// Creamos la función getToken, que recibe como parámetro el objeto `context`
// Gracias a la asignación de desestructuración de JavaScript, recogemos `commit` como argumento
getToken ({ commit }) {
// Pasos:
// 1 - Hacer llamada HTTP para obtener el token
// 2 - Si va OK, guardar el token en 'accessToken'. Continuar el flujo normal
// 3 - Si hay errror, limpiar el token de 'accessToken', mostrar log del error
// Paso 1
oauth.getToken()
.then(({ data }) => {
// Paso 2: Guardamos el valor del token llamando a nuestra mutación
commit('SET_ACCESS_TOKEN', data.access_token)
})
.catch((err) => {
// Paso 3: En caso de error limpiamos el token
commit('SET_ACCESS_TOKEN', null)
console.log('Error OAuth: ', err)
})
.finally(() => {
// Por ahora no hacemos nada más aquí
console.log('Done!')
})
}
}
📗 Puedes ver la documentación relativa al constructor de Vuex aquí: https://vuex.vuejs.org/api/
Ya tenemos nuestra funcionalidad para obtener el token creada. Ahora solo queda llamarla desde la instancia principal de Vue y probar que todo funciona.
Las acciones en Vuex se llaman a través de dispatch. Esto es lo que vamos a hacer desde nuestro método init
en el archivo main.js
.
// main.js
methods: {
init () {
store.dispatch('oauth/getToken', null, { root: true })
}
}
Si abres la consola de tu navegador, verás que hay un error:
🚫 [vuex] unknown action type: oauth/getToken
Eso quiere decir que Vuex no sabe de que le estamos hablando. Es normal, ya que no hemos dado de alta nuestro módulo de OAuth en Vuex. ¡Vamos a ello!
Tenemos que editar el archivo /store/index.js
:
Antes teníamos esto:
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {}
})
Lo que vamos a hacer ahora es borrar todo, excepto el bloque de modules, a la vez que importamos el módulo de oauth.js
y lo damos de alta en el Store.
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
// Importar oauth
import oauth from './modules/oauth'
Vue.use(Vuex)
export default new Vuex.Store({
// Aquuí registramos todos los módulos
modules: {
oauth
}
})
Si cargas la aplicación y abres la consola del navegador, deberías ver el mensaje que pusiste en el finally()
, en este caso verías el log del Hola
y del Done!
.
Si revisas la pestaña de “Network” o “Red” en las herramientas para desarrolladores de tu navegador, deberías ver algo como esto:
Vemos que la petición se está haciendo y nos devuelve los datos. Para comprobar si están guardándose o no, tienes que ir a las DevTools de Vue y revisar la pestaña de Vuex.
Si no conoces las Vue DevTools, una extensión para el navegador, ¡instálalas ahora mismo!: https://github.com/vuejs/vue-devtools
En la parte izquierda se ve un registro (log) de las mutaciones que han ocurrido hasta el momento, y a la izquierda se ve el estado actual del Store o estado de nuestra app.
¡Perfecto! Hemos obtenido el token y lo hemos guardado. Está disponible desde cualquier parte de la aplicación. Ahora podrás usarlo cuando lo necesites.
Aportes 25
Preguntas 6
Hola.
Me sale el siguiente error. No se que podrá ser.
Hasta ahora todo bien, lo que si es que me gustaría que se explicara más a profundidad lo de los modulos de Vuex ya que ni en el curso básico ni el profesional ni el avanzado con firebase lo explicaron.
Aún así, aquí dejo lo que entiendo de las rutas con namespace:
El namespace es para que puedas llamar a los actions usando una ruta entera y no solo a la función, es útil porque así cuando veas que en el código se llama a tal acción sabrás a qué módulo pertenece, si no usas namespace es como tener un arsenal de actions dispnibles tal como los tendrías en Vuex y todas desordenadas
Aún así me gustaría que me explicaran bien la sintaxis de import * as oauth from ‘@/api/oauth’ ¿Cuál sería la diferencia si simplemente pongo import oauth from ‘@/api/oauth’?
me genera el token pero en consola me aparece:
[vuex] unknown local mutation type: SET_ACCESS_TOKEN, global type: oauth/SET_ACCESS_TOKEN
Si alguien tiene problemas con Vuex y en la consola les sale sl siguiente error:
[vuex] unknown action type: oauth/getToken
Es porque, al menos para mi me funciona si escribo la parte de ‘oauth’ así que solo escribe el nombre del metodo getToken y funcionará.
Saludos!
Una consulta, cada vez que se recarga la página se está pidiendo el token, sé que store sólo guarda en memoria y sé que se podría usar el localstorage para persistir el token hasta que caduque, mi pregunta es cómo combinar ambas cosas ya que me gusta mucho usar vuex. Saludos.
Es bueno crear una función dentro de cada módulo del Store llamada initialState, esto es útil para reiniciar el estado del store, es especialmente útil cuando se tienen muchos campos en el state
const initialState = () => ({
accessToken: null
})
Podemos tener algo como esto:
export default {
namespaced: true,
state: initialState(),
mutations: {
RESET (state) {
state = initialState()
}
},
actions: {}
}
Justo hace una semana estaba pensando en: “estaría bueno encontrar un curso donde modularicen el vuex para aprender a hacerlo”.
EXCELENTE! Gracias
Tenía algun tiempo sin reiniciar mi Ubuntu y no quería funcionar. Reinicias y trabaja perfectamente.
Ta bueno el curso!
Excelente curso. Tengo una duda. Estoy intentando refresh el servidor con crtl + c para que no me de error de babel-lint cuando hago los cambios. Tuve que reiniciar el pc para poder ver la pagina online nuevamente y los cambios. No entiendo porque con crt+c no es suficiente para actualizar.
Ese lint… un espacio, un tab, te marca error… te obliga repararlo, menos mal que no es mi ajeiv, lo mando alv.
Buenas!
No se pierdan este vídeo que está genial la explicación:
https://vuex.vuejs.org/#what-is-vuex
Tengo un “problema” que realmente no se si sea eso. Al momento de revisar en Vue DevTools los commits
hechos por Vuex, no veo reflejados los cambios en la consola.
Código
modules\oauth.js
import * as oauth from '@/api/oauth'
export default {
namespaced: true,
state: {
accessToken: null
},
mutations: {
SET_ACCESS_TOKEN(state, payload) {
state.accessToken = payload
}
},
actions: {
getToken({ commit }) {
oauth
.getToken()
.then(res => {
commit('SET_ACCESS_TOKEN', res.access_token)
})
.catch(err => {
commit('SET_ACCESS_TOKEN', null)
console.log(`Error OAuth: ${err}`)
})
.finally(() => {
console.log('Done!')
})
}
}
}
main.js
new Vue({
router,
store,
created() {
this.init()
},
methods: {
init() {
store.dispatch('oauth/getToken', null, { root: true })
}
},
render: h => h(App)
}).$mount('#app')
Hola me sale este error cuando se hace el dispatch
{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}
Recomendaciones para evitar errores en esta sección:
PROBAR EN POSTMAN el procedimiento citado en la sección #6 para traer el token y descartar que el prosible fallo esté en dicha sección.
Hola! Hay alguna forma de hacerlo como un backend for frontend? me preocupa que desde el cliente puedan llegarle a las credenciales (clientId y secretKey). Con las DevTools uno puede ver los parámetos que se envían.
Existen varias formas de hacer esto. Vamos a aprender a llamar a una acción (dispatch) de Vuex desde la instancia principal de Vue, que aunque no es la mejor forma de hacerlo, a efectos prácticos es muy efectivo. ¿Cual seria la mejor manera de hacerlo? . Me interesa las buenas practicas 👀
no entiendo casi nada de tokens como ven soy mas front end que backen es algo muy nuevo para mi seria vacano con videos
store de modules/oauth.js :
import { getToken } from '@/api/oauth'
// mutations
export const SET_ACCESS_TOKEN = 'setAccessToken'
// actions
export const GET_TOKEN = 'getToken'
const state = {
accessToken: null
}
const mutations = {
[SET_ACCESS_TOKEN] (state, payload) {
state.accessToken = payload
}
}
const actions = {
async [GET_TOKEN] ({ commit }) {
try {
const { data } = await getToken()
console.log(data)
} catch (e) {
commit(SET_ACCESS_TOKEN, null)
throw new Error('Error OAuth', e)
} finally {
console.info('Done!')
}
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
el usode {commit} no entiendo , en pinia cual serai su equivalente o no hace falta
Hice una aplicación usando firebase y los datos de usuario los guardé en una variable del store de vuex. Cuando necesitaba cambiarla solo hacía store.state.currentUser=“algo” sin usar mutations y actions. Entiendo el concepto, pero qué desventaja tiene si no las uso y solo modifico directamente el store de vuex? Aclaro que funciona sin problemas toda la aplicación.
NOTA IMPORTANTE
Para los que les sale este error:
[vuex] unknown local mutation type: SET_ACCESS_TOKEN, global type: oauth/SET_ACCESS_TOKEN
Deben cambiar en /store/modules/oauth.js la palabra mutation por mutations
Me aparece el siguiente error en consola, a pesar de que en postman sí me devuelve el valor del token, en la app me aparece vacío el objeto:
[Vue warn]: Error in created hook: “TypeError: api_oauth__WEBPACK_IMPORTED_MODULE_1_.getToken is not a function”
(found in <Root>)
warn @ vue.runtime.esm.js?2b0e:619
logError @ vue.runtime.esm.js?2b0e:1884
globalHandleError @ vue.runtime.esm.js?2b0e:1879
handleError @ vue.runtime.esm.js?2b0e:1839
invokeWithErrorHandling @ vue.runtime.esm.js?2b0e:1862
callHook @ vue.runtime.esm.js?2b0e:4219
Vue.init @ vue.runtime.esm.js?2b0e:5008
Vue @ vue.runtime.esm.js?2b0e:5085
eval @ main.js?56d7:19
./src/main.js @ app.js:1160
webpack_require @ app.js:854
fn @ app.js:151
1 @ app.js:1269
webpack_require @ app.js:854
checkDeferredModules @ app.js:46
(anónimo) @ app.js:994
(anónimo) @ app.js:997
vue.runtime.esm.js?2b0e:1888 TypeError: api_oauth__WEBPACK_IMPORTED_MODULE_1.getToken is not a function
Para los que están usando Vue3, este es el dev tools que tienen que instalar:
https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg
Aún no hay soporte para vuex pero pueden agregar este logger al store para ver que es lo que está pasando:
import { createStore, createLogger } from 'vuex'
.
.
.
export default createStore({
state,
getters,
actions,
mutations,
plugins: process.env.NODE_ENV !== 'production'
? [createLogger()]
: []
})
Hola.
A alguien le paso que le aparecio este error?:
[vuex] unknown local mutation type: SET_ACCESS_TOKEN, global type: oauth/SET_ACCESS_TOKEN
Porque no se como solucionarlo y no puedo continuar con el curso.
El error sale en la consola.
Gracias.
Lectura número siete: creo que mi ser a empezado a generar un fuerte odio hacía lint, espero que solo sea temporal.
PSDT: npm run lint ha sido mi salvador en este camino.
Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.