This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Pues qué vamos a hacer hoy, qué vamos a hacer hoy, hoy vamos a empezar porque creo que no nos va a dar tiempo, ¿vale?
Creo que la empresa que tenemos por delante, el ejercicio, no es que sea complicado, aunque bueno, si tiene sus cositas,
sino que más bien, bueno, pues es largo, es largo, no creo que hoy nos dé tiempo, ¿vale? Con toda sinceridad,
pero creo que podemos intentar llegar al inicio de sesión y a guardar favoritos, vamos a ver cómo lo hacemos exactamente,
pero eso, iniciar sesión y guardar favoritos. Esto es de lo que va hoy y vamos a compartir nuestra pantalla,
a ver si todo funciona bien, vale. Pues nada, si es la primera vez que te estás aquí incorporando a una midu clase,
a una clase de estas que hacemos todos los viernes, pues déjame decirte que tenemos un repositorio donde,
aparte de todo el código, ¿vale? Y todas las clases súper bien separadas y ahí con mi injeto en cada una de ellas,
pues tienes todo el código, ¿no? Y puedes ver paso a paso en cada rama qué es lo que hemos ido haciendo.
Así que, si estás empezando, aquí tienes. Además, me gustaría deciros que, como siempre me encanta que colaboreéis
y que, pues, le deis una vueltecita, ¿no?, a nuestra aplicación, porque es nuestra, es mía, pero sobre todo es vuestra,
porque habéis compartido y habéis hecho cosas y con, bueno, vuestro feedback y vuestro código, pues,
ha ido cambiando y me parece que cada vez, pues, va tomando una dimensión impresionante.
Así que, me gustaría agradecerle a MarcNava13, que vamos a ver cuál es su nombre real, ¿vale?
Marcos Navarro. Marcos Navarro. Pues, Marcos Navarro, muchas gracias por participar.
Lo que ha hecho Marcos es añadir y mejorar la página 404, lo cual le agradezco,
porque ya dijimos que había quedado bastante mal.
Le ha metido un bug ahí en medio crasca y se ha cargado la app.
Bueno, no se ha cargado, es que hoy aparecía por todos los lados,
pero ha hecho el fix súper rápido y ya lo tenemos en máster.
Así que, ahora mismo, vamos a ver cómo queda este 404.
Antes de empezar a ver, pues, me gustaría recordar también que tengo un blog
donde puedes ir viendo todos los vídeos que subo, el podcast que también tengo
y, además, pues, artículos que voy poniendo.
El último, el de la mejor música para programar, tengo que empezar a volver a escribir.
Y, además, está el artículo del curso gratis de React, este que estamos haciendo,
que esta es una clase del curso gratis y, además, tienes una explicación de cada una de las clases, ¿vale?
Y es gratis, no hay que pagar absolutamente nada.
Eso es, midu.dev, la página web.
Y muchísimas gracias, sobre todo, a todos, a todos, a todos los que compartís
cuando hacemos un directo, pues, Ferdinand Alexa va diciendo
vaya iniciando sesión y guardando favoritos esta nueva Midu clase,
mi primer directo en vacaciones, vaya gusto.
Gustazo el mío.
Y Luis Ruiz, que dice, una cervecita fresquita conmigo.
Bueno, muchas gracias a todos los que vais compartiendo, dándole like y le da retweet,
porque ayuda un montón, ¿vale?
Y, nada, solo recordaros que también tengo un Instagram donde voy subiendo cositas.
Así que, nada, os invito a que os suscribáis o sigáis a esta persona que sale aquí tan contenta, ¿no?
Haciendo una grabación de un curso de Platzi.
Pues, nada, vamos a darle, vamos a darle.
Lo primero de todo, aquí ya tenemos un poquito de código, ya tenemos aquí nuestra aplicación.
Vamos a ver si os parece, primero, el 404 que ha preparado nuestro amigo Marcos.
Vamos a poner aquí cualquier cosa.
Pues, este es el 404 que nos ha hecho.
Bastante bónico, ¿verdad?
Además, va cambiando como el GIF.
Si le damos el GIF, pues, bueno, va cambiando.
Ha puesto como diferentes, no sé si tres o cuatro, ¿no?
Y van cambiando.
Este está gracioso.
Y le Windows.
Muy bien.
Y, nada, te permite volver a la Home.
Bueno, o sea, que está bien.
Ha mejorado bastante el 404.
Antes era muy espartano, muy espartano.
Entonces, vamos a hacer esto un poquito más chiquitito.
Seguramente, os tengo que decir unas cuantas cosas, ¿no?
Lo primero es que con el tema de la mudanza voy con el tiempo justo.
Además, no os asustéis si de repente alguien arriba se pone a hacer portazos o lo que sea.
O una herramienta porque están haciendo obras.
Y, bueno, aunque aquí en España son las casi nueve de la noche.
De vez en cuando, pues, tarda.
Así que si de repente se escucha un taladro, no se asusten, ¿vale?
Está todo controlado, pero, bueno, puede ser un poco molesto.
Intentaré que no se escuche.
Vale.
Pues, seguramente, aquí en API, aquí hemos hecho un nuevo directorio que lo he hecho yo, pues, probando un poquito.
Y, además, lo he hecho con Deno.
Bueno, con Dino.
Se pronuncia Dino.
Entonces, lo he hecho con Dino.
Con TypeScript y tal.
Y esta es la API que vamos a utilizar para hacer el login y para hacer el tema de añadir los favoritos, ¿vale?
Entonces, os lo voy a enseñar un poquito por encima porque no me gustaría que lo vieseis como que hay magia potagia.
Pero esto, además, me ha servido un poco, pues, para entender Dino y animarme, ¿no?
A hacer vídeos más adelante en el canal.
Así que, bueno, tenemos aquí como el punto de entrada de nuestro servidor, de nuestra API.
Que una sería para recuperar los favoritos, otro para borrar un favorito, otro para añadir un favorito al usuario.
Estos tres tienes que estar, pues, tienes que haber iniciado sesión porque necesita un token para funcionar.
Y luego, pues, tendríamos un post para hacer el login y otro para hacer el register.
Entonces, creo que si más o menos los tiempos van bien, vamos a poder ver seguramente el post del login, el post del FAPS y también el get del FAPS.
El delete y el register para la segunda parte, la semana que viene, ¿vale?
Entonces, esto por aquí.
Luego, en roots.ts, este código, aunque ahora no lo tengo deployada y no lo tengo, no está en una URL, sí que está en el repositorio ya, ¿vale?
Lo he puesto en la carpeta API y ya lo podéis probar.
Lo que no está muy bien documentado, así que seguramente este fin de semana, pues, pondré como lo podéis levantar este servidor en vuestro local para ir probándolo, ¿vale?
Entonces, en roots.ts, pues, tenemos cada ruta, lo que tiene que responder a la hora de recuperar los favoritos, a la hora de borrar los favoritos.
Bueno, me he puesto algún console log, pues, para ir debugando, ¿vale?
La idea es quitarlo más adelante para hacer un post de los favoritos, el login y tal.
Y entonces, en cada uno, pues, hay que devolver un status code y tal.
La magia seguramente está en estos dos middlewares, en uno que básicamente lo que hace es mirar si tiene el token, el JavaScript Web Token para funcionar y recuperar el usuario en el caso de que esté.
Todavía no está en base de datos, pero, bueno, para nosotros, para lo que necesitamos, no es tan importante que tenga una base de datos.
Y, al final, puede ser algo transparente, lo podemos hacer y será totalmente transparente.
Y luego, este middleware, que lo único que hace es eso, es ver si realmente tiene un usuario para permitir continuar en la siguiente, digamos, función que se tiene que cargar de esa ruta.
O sea, que vamos por pasos, ¿no?
Primero, recuperamos el token, recuperamos el usuario, luego este middleware dice, vale, tienes un usuario, porque si no tienes un usuario, no vas a seguir haciendo lo que viene después.
Y lo que viene después puede ser guardar el favorito, puede ser borrar un favorito, recuperar los favoritos, porque eso solo puede hacer un usuario.
Así que eso es importante.
Entonces, eso es la API, está hecha con Dino.
De hecho, vale, aquí lo tengo ya levantado, ¿vale?
Me la voy a jugar y voy a cerrarlo y lo voy a volver a levantar.
Estoy utilizando Dino, que es como un nodemon, pero para Dino, ¿vale?
Y, bueno, ya tengo con todos los permisos y tal.
No es importante que sepáis Dino.
Esto, al final, no es lo que venimos a ver en la clase, pero me gustaba comentaros un poquito.
Pues así, ya tenemos aquí con este...
Ay, bueno, no, no se ve, lo siento.
Bueno, a ver, es que estoy aquí en medio, aquí.
¡Bum!
Me cambio, vale.
Pues he hecho este Dino, run y con estos permisos, ¿no?
Y este sería el server que os he comentado antes.
Y ya está.
Ya se ha levantado y así, si hiciésemos cambios, pues se volvería a levantar.
O sea que está bastante bien.
Vale.
Aquí tengo un poco, pues, los diferentes endpoints y los puedo ir probando para hacer el login.
De hecho, lo voy a probar.
Hago login.
Ya tengo un usuario ahí guardado para que no se me vaya borrando, ¿no?
Y este es el midudev y suscríbete.
Username, midudev, password, suscríbete.
Seguramente diréis que es un mensaje subliminal.
No, que va.
Que va.
Vale.
Y esto lo que nos devuelve es el JavaScript Web Token.
Igual al registrarse, pues también lo que debería hacer...
Bueno, ahora nos daría aquí un conflict porque este usuario ya existe.
¿Vale?
Entonces, con otro usuario nos debería devolver otro JavaScript Web Token y guardar ese usuario en la base de datos esta.
¿Vale?
Y, pues nada, recuperamos los FAB para guardar un FAB y para borrar un FAB.
Bueno.
El caso es que ya tenemos la API, ya la tenemos preparada.
Entonces, sí, ya tenemos aquí alguien nervioso que dice, ¡Zoom al código!
¡Vamos a hacer zoom al código!
No os preocupéis.
Vale.
Pues, pues, vamos a ver por dónde empezamos.
Ya he enseñado el repositorio, ya hemos enseñado la API.
Vale.
Pues lo primero que vamos a hacer...
Voy a moverme otra vez en la cámara en algún sitio que intente no molestar mucho.
Por aquí, por ahora, creo que puede estar bien.
Lo que vamos a hacer primero es tener un nuevo componente que le vamos a llamar header.
Este header, básicamente, va a ser muy sencillo, ¿eh?
Va a ser muy sencillo.
De hecho, ya os comento que, claro, al ser una clase que tenemos que hacer muchas cosas, pues voy a ir por faena porque hay cosas que se supone que ya hemos visto y que ya sabemos de sobras.
¿Vale?
Y que me puedo quedar bloqueado en alguna cosita y tendríamos que arreglarlo y tal.
Vale.
Entonces, tenemos el header.
El header es una barra que va a ir arriba donde vamos a tener la ocasión de iniciar sesión y todo esto.
Entonces, lo que vamos a hacer aquí es añadir el header.
Vamos a tener el header con un class name que le vamos a poner un prefijo y el nombre de la clase.
Y aquí, pues, vamos a añadir un botón que será link.
Y esto lo que hará es...
Bueno, esto sería el to.
Ir a login.
Ir a login.
Y esto, pues, será login.
Ya está.
Vale.
Esto sé que es muy espartano.
Vamos a ponerlo un class name aquí.
No sé si...
Bueno, da igual.
No hace falta.
Ponemos él directamente en login.
Vale.
Ya tenemos esto.
Vamos a ponerle un poquito de estilo antes de utilizarlo.
Vamos a poner aquí esto.
Esto creo que lo he puesto así.
Esto.
Vamos a poner esto que queda a la derecha del todo.
Vale.
Vale.
Y vamos a importar estos estilos aquí.
Ahora vamos a utilizar este componente.
Vale.
El componente lo vamos a utilizar a nivel de aplicación.
A nivel de aplicación.
Así que lo vamos a importar aquí.
Aquí hay una cosa que ya me está poniendo nervioso.
Vamos a...
Voy a mover esto aquí.
Esto aquí.
Esto es el toque mío de tener las cosas ordenadas.
Vale.
Entonces, ya tenemos aquí contextos.
Así podemos poner aquí los componentes.
Ponemos el header.
Y esto lo importamos de components.
Header.
Y el header, pues, lo vamos a poner que esté encima de todo.
¿Dónde está aquí el logo?
¿Dónde está el logo?
Aquí.
Vale.
Pues, lo podemos poner justo antes del logo.
¿No?
El logo es esto.
Lo ponemos aquí justo antes.
Y ya, bueno, debería salir algo por ahí.
Bueno.
Entonces, lo que vamos a hacer ya es a esto, pues, darle algún tipo de estilo.
Tampoco nada del otro mundo.
¿Vale?
Pero al menos que se vea más interesante.
Más chiquitito.
Uy.
Fuera.
Esto.
Así.
Pum.
¡Ay!
¿Qué ha pasado?
Que no me lo está recargando.
A ver.
Ya empezamos mal, ¿no?
Porque ya he puesto aquí los estilos.
A ver si es que me he equivocado.
Header.
Header.
Class name.
Ajá.
Que ha pachado.
A ver si es que...
No sé.
No me está pillando los estilos.
Ahora me ha vuelto loco, ¿no?
¡Ay!
¡Ay!
¡Ay!
Claro que me he vuelto loco.
Si es que no me estoy importando bien.
Vale.
Ahí.
Ahora.
Ahora.
Vale.
Aquí está, ¿vale?
Aquí está el login.
Vale.
Ya decía yo que no estaba haciendo el flex.
Me estaba volviendo loco.
Digo, ¿qué ha pasado?
Vale.
Mientras aquí veo que va gente saludando, ¿eh?
Dice 186 viewers.
Están todos los vídeos en su canal.
Todos los vídeos.
Todos los vídeos están en el canal, ¿vale?
Todos los vídeos de la clase.
Y este también se guardará y está en el canal.
Vale.
Pues por ahora tenemos esto.
Ya voy a ir preparando, si os parece esto, del caso de que si aquí tuviésemos una forma
de saber si estamos logueados, pues que este login cambie, ¿no?
De forma que si estamos logueados, aquí aparezca el botón de logout y si no, pues que
aparezca el de login, ¿vale?
Un renderizado condicional, ¿eh?
Que esto ya lo tenéis que tener dominadísimo.
Y aquí vamos a hacer este.
Logout y logout.
Logout, si estamos logueados, logout y si no, login, ¿no?
Entonces así, si ponemos esto true, aquí ya saldría un logout, ¿vale?
Esto ya va pintando bien.
Por supuesto, todavía.
Esto está muy verde, ¿vale?
Pero bueno, ya tenemos ahí el login, tenemos los estilos.
Vamos a añadir aquí también un poquito para que el text decoration, text decoration, ¿no?
Para hacer over que parezca que hace alguna cosita.
Vale.
Ahora el tema es que aquí hemos utilizado un link, ¿vale?
Que nos lleva a una URL.
Entonces, claro.
Esto aquí...
Vea, esto está un poco raro, ¿no?
Bueno.
Bueno.
Da igual.
Nos lleva a una URL.
Le damos y nos sale el 404 de nuestro amigo.
Vale.
Esto no es lo que queremos.
No.
Lo que queremos es justamente ir a la aplicación app.js y aquí tenemos todas las rutas.
Que igual las deberíamos separar, ¿eh?
Algún día.
Igual ahí os dejo un ejercicio.
Yo lo dejo.
Yo lo dejo por ahí.
Vale.
Pues vamos a añadir una nueva ruta y vamos a cargar un nuevo componente.
Y el path donde se va a cargar esta ruta es login, justamente.
Y el componente va a ser login.
Así que vamos a importar login desde la página login y ahora lo utilizamos.
Por cierto, mira.
Aquí tenemos esto con el punto barra, punto barra, punto barra, punto barra.
Todo esto sobra, ¿eh?
Que ya en uno de los vídeos hicimos esta maravilla de poder importar más fácilmente
los paquetes de nuestra aplicación.
Vale.
Lo que sí que si ahora guardo esto va a petar.
Seguramente.
Sí, claro.
¿Por qué?
Porque no existe la página de login.
La tenemos que hacer.
Así que vamos a ir aquí a las páginas y vamos a cargar el login.
Vamos a hacerle un index.js.
Ah, por cierto, hay veces que la gente me dice, guau, qué rápido haces un componente
en React.
No, es que tengo un shortcut de estos, ¿vale?
Es un snippet.
Que yo pongo React, le doy al enter, ¡pum!
Y ya me dice, vale, pues solo tengo que escribir la función, el nombre de la función,
que en este caso sería login.
Le doy a tabulador y ya pasaría dentro de las props, que en este caso no tiene props.
Y si lo hubiera dado otra vez al tabulador, pues ya me devuelve aquí al return, lo cual
está bastante bien.
Entonces, ¿qué es lo que tiene que hacer esto?
Vamos a ir por faena, porque esto también ya lo sabemos.
Esto seguramente lo podríamos mejorar, ¿eh?
Mucho mejor de como lo voy a hacer.
Pero lo voy a hacer a piñón, porque lo que nos interesa no es tanto ver ahora formularios.
Pues igual la semana que viene me gustaría que veamos Formic.
Y puede ser una oportunidad, ¿vale?
Así que ahí lo dejo.
Por ahora lo vamos a hacer así, ¿no?
A grano, al grano.
Y más adelante veremos cómo lo podemos arreglar, hacer de otra forma.
Entonces, aquí lo que vamos a necesitar también es tener un estado, ¿no?
Uno para el username, así que hacemos useState, y aquí le hacemos esto, y otro pues para el password.
Esto es el típico formulario en React de toda la vida.
Vale, este, el password, lo vamos a hacer de, ay, no sé si se veía o lo queríais más grande el código, ¿eh?
Pero bueno, voy a intentar hacerlo todavía más grande, a ver si así no hay ningún problema.
Así que al final he dicho mucha broma y con esto se me ha olvidado.
Vale, esto vamos a poner que es del type password y vamos a importar aquí el useState.
Vale, bueno, no es el mejor formulario que hemos hecho, pero creo que va a servir.
Este formulario va a servir.
Así que vamos a poner ahí un botón que es login, el botón, el último botón del formulario sirve como submit de forma totalmente automática, ¿vale?
Aquí en value lo vamos como a linkar al estado, así que aquí vamos a poner que esto, el valor de esto es el username y esto es el password.
¿Y qué pasa? Que cada vez que cambiemos esto, lo que queremos es actualizar, en este caso, el username con e-target.value
y aquí justamente lo que vamos a querer es cambiar el password, ¿no?
Con e-set-password-target.value.
¿Target.value? Sí, ¿vale?
Voy a formatear esto para que quede un poquito más legible, ¿vale?
Muy bien.
Entonces ahora, bueno, aquí es porque se ve muy chiquitito la cosa esta, ¿no?
Validación la haremos, ¿vale?
Pero a lo mejor la hacemos con formic, que es un poquito más interesante.
También podríamos hacer que fuese el mismo estado, podríamos hacer un reducer.
Por ahora lo quiero hacer sencillo, ¿vale?
No quiero perder mucho tiempo en esto, porque si no estaríamos aquí un buen rato dando, bueno, vamos a hacer un solo estado, vamos a hacer la tal.
Bueno, al final, con un reduce estaría bien, seguramente lo mejor sería utilizar formic, porque nos quitaría un montón de boilerplate aquí, ¿vale?
Pero bueno, esto sobre todo para ahora mismo ver que todo funciona y ya está.
De hecho, uy, madre mía, ¿qué me ha importado ahí?
Vamos a poner esto por ahora, no es lo que deberíamos hacer, ¿vale?
Pero vamos a hacerlo.
No, no, bueno, sí, va, guárdamelo, guárdamelo.
Entonces, tenemos el handle submit, ahora lo que vamos a hacer es actualizar y cuando hacemos el submit, pues básicamente vamos a mostrar una alerta viendo qué es lo que hemos puesto ahí.
No es lo más guay, pero bueno, pone midudev, está bien, no me ha enseñado el password, no sé si es porque la he liado o porque...
Ah, bueno, claro.
Será porque si no escribo nada, el estado en realidad no ha cambiado.
Ah, pues no.
Ay, no, es que el alert no funciona así.
No le gusta...
Bueno, tampoco es muy importante, era solo para ver qué funcionaba y ya está.
Que teníamos esto...
Vale, eso es lo que he puesto, ¿vale?
Entonces ya tenemos el handle submit, ya tenemos el estado, ya tenemos todo esto, así que ya lo que nos va a interesar es que, claro, cuando hacemos el submit,
en realidad esto, por ahora vamos a dejar así, porque lo que nos va a interesar es que cuando nos logueemos e iniciamos sesión, pues nos lleva a otra página.
Así que aquí lo que vamos a hacer es utilizar el useLocation que tendríamos de Wooter.
Wooter es una alternativa a ReactRooter DOM, o sea que si utilizáis otro, pues lo podéis utilizar sin ningún tipo de problema, ¿vale?
Aquí el useLocation es un hook que te devuelve primero la localización y luego una forma de actualizar la localización.
Por ejemplo, esto sería pushLocation.
Le puedes llamar navigate, si quieres, que queda mapónico.
Entonces aquí podemos poner que esto navegará a la home y guardando los cambios, pues ahora cuando hacemos esto, ¡pum! Pues ya funcionaría.
No, todavía nos queda, todavía nos queda, ¿vale?
Pero al menos ya empieza a verse un poquito por dónde van los tiros.
Que vamos al login, vamos a loggearnos, si todo ha ido bien, entonces navegará, si todo ha ido bien.
Vale.
¿Qué más?
Lo que vamos a necesitar por el tema del usuario es sobre todo ya tener un contexto.
Entonces, ya teníamos uno muy parecido que es el GIFsContextProvider y tal.
Lo que vamos a hacer es copiarlo, así ya saco, y vamos a hacer uno nuevo.
Le vamos a llamar userContext.js, ¿vale?
Lo pegamos y le vamos a cambiar aquí el nombre a este UserContextProvider.
Esto sí que es el children.
Y aquí lo que vamos a guardar es nuestro token.
El token es el JavaScript token, así que vamos a llamarla JWT.
Set JWT.
Y esto es lo que vamos a tener por aquí, nuestro value.
Vale, ya tenemos nuestro UserContext.
Ahora necesitamos, pues, envolver nuestra aplicación para poder acceder a todo esto, ¿vale?
Así que nos vamos a nuestra app.
Y aquí en nuestra app ya teníamos algún context.
Teníamos este contexto de pepito que no estábamos utilizando para absolutamente nada.
Entonces, este pepito me parece que ha llegado muy lejos.
Vamos a quitarlo y vamos a importar este nuevo contexto, ¿vale?
El del usuario.
Ya dimos una clase de cómo se utilizaba el context, ¿vale?
Por si tienes dudas, pues, que sepas que puedes mirar el canal y ahí te lo vamos a comentar.
Esto, isDeclar...
Vale.
Entonces, esto ahora nos está diciendo que lo hemos declarado, pero que no lo estamos utilizando.
Entonces, vamos a utilizarlo.
Vamos a quitar este provider que no servía para nada, ¿vale?
Esto lo hacemos aquí.
Y aquí vamos a bajar, vamos a bajar y...
Vamos a este, ¿vale?
Ahí está.
Entonces, ya tenemos envuelta toda nuestra aplicación con este nuevo contexto.
Uy, algo no le ha gustado.
Esta barrita.
Ahí está.
Muy bien.
De hecho, también voy a formatear este archivo para que quede un poquito mejor.
Vale.
Ya tenemos nuestra aplicación toda envuelta con este contexto, ¿vale?
Entonces, en este contexto tenemos un estado.
Y este estado es crucial porque este estado lo vamos a poder compartir en diferentes partes de nuestra aplicación.
Y en este estado vamos a tener justamente el JavaScript Web Token, que nos va a decir si nuestro usuario está logado y lo vamos a poder utilizar en diferentes partes cada vez que hagamos una petición, ¿vale?
Así que esto ya lo tenemos.
Voy a...
Antes de continuar, voy a empezar a leeros un poquito, que estoy un poquito abandonados.
Y os voy viendo aquí por el rabillo del ojo, ¿vale?
Así que, a ver, vamos a ver.
Adiós, Pepi.
Adiós.
No, Pepi.
Adiós.
JG.
Hola y gracias.
Mendoza, Argentina.
Víctor Solís.
Hola, hola.
Desde Ecuador.
¿Cómo se hace para hacer zoom en algún segmento de tu pantalla?
Siempre me preguntan los mismos truquitos.
Esto es un tema de accesibilidad de Mac y lo podéis customizar a vuestro gusto.
Así que id a la accesibilidad y ahí lo tenéis.
¿Vale?
Para formatear bien los espacios, su código debe usar Prettier, ¿cierto?
Y no lo tengamos configurado.
Estaría bien.
Así que ahora mismo lo está formateando el editor y hace lo que puede.
Que tampoco está mal.
¿Vale?
¿Alguien sabe por qué los imports tienen algunos errores?
Sí, me aparecen algunos imports con errores.
No sé por qué.
Esto me ha pasado desde que he actualizado a la última versión de React.
Ay, de React.
De Visual Studio Code, ¿vale?
No lo sé.
No sé por qué me ha pasado esto.
Lo tengo que mirar, pero no me ha dado tiempo a mirarlo.
Y es súper raro.
Y sí, las validaciones de Formic se pueden hacer con Jupe o se puede hacer con un montón de cosas.
Pero sí, seguramente Jupe es la más interesante, ¿vale?
¿Qué más?
Sí, Formic cuando crecen los formularios va como un caracol.
Es verdad.
Y hay que empezar a fine tuning, ¿vale?
Básicamente hay que ir encontrando poco a poco dónde están los problemillas.
Un poco lo que vimos, ¿no?
De afinar, que no se renderice cuando es necesario y todo esto.
Juan David, otra vez, ¿por qué no haces un mismo estado para el username y el password?
Pues mira, en este caso hay dos motivos.
Uno, porque queríamos ir rápido.
Y lo segundo, porque aunque lo metamos en el mismo, al final, en el handle change, lo que tendrías que hacer es volver a generar el objeto donde ya tenías, por ejemplo, el password o tenías el username.
Sí, entonces es un poquito más raro, ¿vale?
O sea, no queda tan limpio a la hora de entenderlo.
Si yo utilizase un solo estado para estas dos cosas, lo que haría es utilizar un reducer, un useReducer en lugar de un useState, ¿vale?
En lugar de tener un solo estado para eso.
Vale, pues veo que, mira, a alguien le pasa lo mismo con Visual Studio Code y con Angular, así que no estoy solo.
Me alegro.
Vale, pues vamos a seguir.
Vamos a continuar, ¿vale?
Voy a poner por aquí mi pantallita.
¿Por dónde iba?
A ver, estado global.
Teníamos el contexto.
Ya teníamos un estado.
Entonces, lo que vamos a hacer es seguir la estrategia que teníamos de utilizar un hook para acceder al estado global que teníamos con el contexto, ¿no?
Entonces, teníamos este useGIF, ah, no, este globalGIF, algo así.
Entonces, vamos a hacer algo parecido, pero, bueno, algo más complicado, más parecido al useGIF, pero para los usuarios.
Así que vamos a crear aquí un archivo que, ¿cómo lo llamamos?
UseUser.
UseUser.
¿Vale?
Y aquí lo que vamos a hacer es hacer un export default function.
Si te gusta exportar más de forma nombrada, quita el default y ya está.
¿Vale?
Vale.
Y esto vamos a hacer un useUser.
No va a recibir, en principio, no debería recibir ningún tipo de parámetro, no debería ser necesario, ¿vale?
Entonces, lo que sí que necesitamos es recuperar tanto el JavaScript Web Token como la forma de actualizar el JavaScript Web Token del contexto.
Este contexto es justamente el que hemos hecho antes.
Así que esto lo importamos de context, userContext, ¿vale?
Y este contexto es el que necesitamos leer para recuperar el JavaScript Web Token y la forma de actualizar el JavaScript Web Token.
Ahora, esto, lo que va a devolver, podríamos devolver el JavaScript Web Token, pero tengo dudas que lo vayamos a necesitar por ahí.
Lo que sí que podemos hacer, por ejemplo, es decir, si está loggeado el usuario, o es log in, y esto lo podríamos mirar si el JavaScript Web Token tiene algún tipo de valor.
Luego veremos si esto realmente tiene sentido.
Si no tiene sentido, ya le daremos una vuelta.
Entonces, aquí, vale, iba a utilizar ya el useCallback porque es que es manía, ¿vale?
Pero aquí vamos a necesitar un método de hacer login, ¿vale?
Entonces, este método de forma de hacer login es lo que vamos a dejar que la gente o los que consumen este hook puedan hacer login, ¿no?
Entonces, ¿qué tiene que hacer este login?
Pues así de primeras, de primeras, sin meternos todavía en API, pues lo que tiene que hacer es cambiar el JavaScript Web Token.
Porque de esta forma, cuando tenga valor, lo que pasará es que este cambio se replicará, lo podrá leer y dirá, vale, pues ahora sí que está logado.
Pues por ahora lo que vamos a hacer es test, por ahora.
De la misma, bueno, por ahora lo voy a dejar así.
Entonces, para evitar crear esta función cada vez que actualizamos el JavaScript Web Token, que le llegue uno nuevo,
lo que podemos utilizar aquí, que esto ya lo vimos en otra clase, es el useCallback.
Y es que esto tengo una manía ya enorme, por eso está empezando a escribir ya useCallback, ¿vale?
¿Por qué? Porque queremos optimizar, no solo optimizar, porque por una parte optimizas, ¿no?
Estás optimizando que no se vuelva a crear esta función con este useCallback,
pero además también te puede ahorrar problemas, ¿vale?
Porque si por lo que sea estás haciendo que cada vez que se actualiza el useUser,
devuelva una nueva función y esta función la tienes como una dependencia de algún efecto,
de algún componente, la puedes liar muy parda, ¿vale?
Y puedes hacer algún loop infinito y tal, lo cual no es recomendable.
Vale, aquí ya se me está quejando, ¿no?
Que dice que el useCallback le falta una dependencia.
¿Por qué?
Porque este useCallback depende de este set JavaScript Web Token.
Así que lo tenemos que añadir aquí como una dependencia del callback,
de forma que cada vez que cambie este set JavaScript Web Token, que ya os digo yo, spoiler, no debería cambiar,
pero cada vez que cambie esta función debería volver a crearse, ¿vale?
Entonces vamos a hacer esto.
¿Vale? Tenemos el login, tenemos el login, una forma de saber si hemos logueado,
pues yo creo que esto más o menos debería funcionar.
Vamos a probarlo en el header, por ejemplo.
Podemos, a ver que me vais diciendo, muestra el JavaScript Web Token, ¿vale?
Lo mostraremos.
Vale.
Entonces, aquí, si lo recuerdas, ¿qué había hecho?
Pues había puesto un isLog a false, aquí a fuego, a piñón.
Y no tiene mucho sentido, ¿no?
Esto, lo que sería genial, es que pudiésemos recuperar nuestro hook
y empezar a ver un poquito de magia.
Y a partir de aquí ir construyendo, construyendo,
hasta que tengamos el tema del login.
Así que vamos a importar el useUser, este nuevo hook que hemos creado,
lo tenemos en hooks barra useUser.
Vale. Vamos a ver si esto funciona.
Entonces, voy a comentar esto.
Ahora, vamos a utilizar el useUser.
¿Qué es lo que devuelve el useUser?
Pues lo que estaba devolviendo era un objeto que, si recordamos y lo miramos,
tenía isLogin y login, ¿vale?
Uno es un método para hacer el login y otro es para saber si está logueado.
Pues vamos a importar los dos.
Es isLogin y el otro el login.
Mira, me gusta más el nombre de isLogged, ¿no?
Que es un poco más directo.
Así que vamos a cambiar este.
En lugar de isLoggedIn, vamos a cambiar isLogged.
¿Vale? Voy a guardar los cambios por aquí.
Y aquí todavía me falta este login.
Vale.
Bueno, este login aquí ni siquiera hace falta que lo utilicemos.
Por ahora, vamos a dejarlo así.
Guardo los cambios.
Vale.
Me ha dicho que el useContext no está definido.
Esto porque aquí estoy utilizando este useContext y no lo tengo definido.
Lo tengo que importar aquí, useContext.
Vale.
Vale.
Ahora mismo no hay ningún tipo de diferencia.
Ah, veo que está aquí siempre logout.
Es como que siempre está logueado.
Vamos a ver por qué.
Porque este, vamos a ver, el booleano este, me está dando que es siempre true.
Vamos a ver en el header cómo hemos puesto la lógica.
Hemos puesto isLog.
Vale.
Si está logueado, entonces tal.
Pues entonces el problema lo podemos tener aquí.
UseUser.
Hacemos esto solo cuando es login.
Pues este isLog.
Ahora no recuerdo qué es lo que he puesto en el...
Ahí.
Esto.
Quería mirar esto.
Vale.
Vamos a ver.
Un momento.
Ahí.
Vale, ya está.
Ya he visto el problema.
Ya he visto el problema.
Que esto es un array.
Esto es un array.
Vamos a ver el contexto o en algún sitio aquí la he liado.
En el useContext, ¿qué está pasando aquí?
Ah, claro.
Mira, aquí.
Sí, es que esto no está bien.
Esto debería ser o null.
Sí, creo que null sería más correcto.
Claro, el valor inicial del estado está siendo un array y entonces estaba entendiendo que sí que teníamos un JavaScript Web Token.
Bueno, pues eso.
Tenía que ser con null.
¿Vale?
Ahora sí, podemos ver aquí arriba.
¿Vale?
Vemos que está en login.
¿Y cómo vamos a cambiar el estado?
Pues cuando hagamos login.
O sea, que cuando vayamos a login, aquí que teníamos esto, vamos a ver qué tenemos que hacer.
Vamos a ver.
En el formulario de login, aquí.
Vale.
En este formulario, aquí tendríamos que hacer el login.
Así que lo que vamos a hacer es importar el login del useUser.
Y este useUser, useUser es el hook.
Así que importamos de los hooks, ¿vale?
Importamos el login.
Vale.
Y ahora aquí hacemos login.
Pero, claro, ahora vamos a ver qué está pasando con este navigate.
Que este navigate ahora deja de tener tanto sentido, ¿no?
Porque ahora todavía no sabemos si hemos hecho login.
Por ahora lo voy a quitar, ¿vale?
Voy a quitar esto.
Y lo que voy a hacer es que aquí vamos a importar también el isLogged, ¿no?
Del useUser que nos está devolviendo.
De esta forma, este navigate que estamos haciendo aquí lo quitamos y lo que podemos hacer es tener un efecto.
Un efecto que nos diga que si nos hemos logueado, pues que se vaya el navigate.
Y esto debería cambiar cada vez que cambia el isLogged.
IsLogged, ¿vale?
Ahí está.
Bueno, y el navigate.
Pero, bueno, el navigate no debería cambiar.
Entonces, ahora que sabemos cuándo el usuario está logueado, lo que vamos a hacer es ejecutar un efecto.
Le decimos, vale, pues si se ha logueado, pues navega directo.
Llévatelo de aquí.
Llévatelo porque ya no tiene sentido, ¿vale?
Así que es una dependencia.
Este efecto se ejecutará cada vez que cambie el isLogged.
Y miraremos si es true, ¿vale?
Si el isLogged este, si esto es true, básicamente.
Y si es true, pues lo sacaremos de esa página.
Haremos que navegue a otra.
Esto es como debería funcionar.
O sea, que si ahora le damos al login, pues ya está.
Está funcionado.
Aquí tenemos un logout.
Y esto es porque ya estamos logueados.
Si refrescamos, pues ya deja de funcionar porque básicamente, claro, no tenemos persistencia, ni sesión, ni nada.
Pero, bueno, al menos ya vamos viendo un poco el flujo por donde va tirando.
Podríamos hacer el logout súper fácil por ahora para ir preparándolo, ¿vale?
Porque son al final cosas que vamos a ir necesitando.
Y este logout podríamos hacer básicamente limpiar el JavaScript Web Token, ¿no?
De forma que este logout lo podamos utilizar en el header de forma...
A ver, ¿dónde está el header?
¿Dónde está el header?
No te escondas.
Vale.
Así lo podemos importar aquí también, logout.
Y este logout será cuando hagamos...
Es que esto, claro, no hace falta que navegue.
Esto debería ser...
Esto debería ser un on-click directamente, ¿no?
Y que cuando haga el on-click, hacer el logout.
No sé...
Podríamos hacer un export default.
Igual se queja de esto porque al final...
Claro, ¿ves?
Porque ha intentado navegar.
Porque no le estamos evitando que navegue.
Podríamos hacer un botón...
Bueno, podríamos hacer unas cuantas cosas.
Voy a hacer una cosa fácil, ¿vale?
Que básicamente es tener un handle click de forma que cuando le demos click,
evitemos la navegación con un prevent default.
No es lo mejor.
Y semáticamente no es lo más correcto, ¿vale?
Pero me lo vais a perdonar en este caso, ¿vale?
Para continuar, seguramente lo mejor es que fuese un botón.
Visualmente que fuese igual que el login, pero que no fuese un anco,
sino que fuese un botón, ¿vale?
Entonces por ahora lo vamos a hacer así, pero ya sabéis,
si os queréis entretener, también te deberéis.
Pues vamos a hacer esto y así de esta forma ahora no debería haber problema.
De forma que hacemos el login, hacemos login, aquí tenemos el logout,
le damos a logout.
Igualmente me ha hecho la navegación, ¿eh?
Porque me ha dejado esta almohadilla aquí.
Esto no mola.
Esto no mola.
Molaría que ni siquiera se viese esa navegación.
A ver, ¿otra vez?
No, me la deja.
Bueno, por ahora la vamos a dejar,
pero esto estaría genial que fuese mejor un botón para evitar esto,
que hiciese esta navegación que no es necesaria.
Cuando pones el hash, pues claro, cuela, pero no es lo ideal, ¿vale?
Vale, lo hemos dejado por aquí.
Vamos a ver qué me vais contando.
¡Uf! 43 minutos llevamos ya, pero madre mía.
Vale, pues a ver.
Voy a poneros aquí y os voy leyendo mientras voy poniendo algo de musiquita.
¿Qué más?
Dice Juan Riquelme.
En vez de bolean, yo lo que suelo hacer es bang, bang, la doble negación.
No sé si es un tema de mayor legibilidad del código, el uso de la función bolean,
pero la exclamación, la exclamación, lo tengo bastante interiorizado en el proyecto en el que trabajo actualmente.
Sí, yo la verdad es que, bueno, es lo que prefiráis.
A mí me gusta más el casting más que se lee, ¿no?
Que queda clarísimo que estás intentando transformar en boleano.
Además te lo hacen una vez, te lo transforman en boleano directamente.
Cuando haces la negación-negación, claro, lo pasas una vez, que te hace el cast y luego lo vuelves a negar.
Es una tontería, pero bueno.
Esto está para lamerte las manos.
Leonardo Torrico, tengo que decirte cómo mola esa expresión.
Yo digo muchas veces lo de esto está para lamerlo, pero me encanta esa expresión.
Me la voy a apuntar aquí porque me ha encantado.
Itzazo, muy buen trabajo.
Me estoy adentrando en React, vengo de Ángulo y me encanta cómo explicar.
Genio, muchas gracias.
Crack, eso sí que está guay.
Excelente vídeo, como siempre, no podré terminarlo de ver.
¡No, David, no te vayas!
Pero en la noche lo termino.
Gracias por compartir tanto.
Bueno, gracias a ti, hombre, por pasarte.
¿Cómo haces scroll hacia los lados?
¿Qué scroll?
¿Este?
Ahí, bueno, claro, no se ve.
Dices entre pantallas, con el trackpad, vas tirando con dos dedos.
Creo que da eso, ¿no?
Lo que estás preguntando.
¿Qué más?
¿Se muestra el JavaScript Web Token?
Todavía no.
El código lo tenéis en un repositorio, ¿vale?
Si no, me podéis buscar en GitHub, porque me preguntan por aquí Ana Paula,
que se acaba de apuntar.
Buscadme en GitHub, github.com barra midudev.
Me buscáis en midudev y entre mis repositorios tenéis el React Live Coding.
Y ahí está, ¿vale?
¿Qué más?
Vale, veo que más o menos ya lo tengo.
¿Cómo haces las importaciones absolutas?
Lo hicimos en la primera o en la segunda clase.
Y la magia está, voy a ponerme por aquí, la magia está en este archivo, en el JSConfig, en este de aquí, ¿vale?
Aquí puedes ver que le puedes decir las opciones del compilador y le dices que la URL base sea source.
De forma que tú cuando haces un import, pues ya te busca directamente la carpeta source.
Y te queda así tan, tan chulo que yo creo que está súper bonito.
Está muy bonito.
Como dicen por ahí, está para merlo, para merla en mano.
Vale, pues lo vamos a volver.
Ya tenemos el login, ¿vale?
Ya sé que no es un login en toda regla, ¿vale?
Pero vamos acercándonos.
Entonces, en el login, cuando hemos hecho el login, voy a ir cerrando, ¿vale?
Que tengo un montón de cosas ya abiertas.
Esto me suele pasar siempre.
El login, aquí, en este login, lo que estábamos haciendo, claro,
es ejecutar el método y ya se loguea.
Pero vamos a empezar a hacer que esto tenga más sentido.
Así que vamos a pasarle el username y el password.
Que justamente username y password, si vemos la API en el login,
son justamente como se llama, ¿vale?
Como tenemos que enviar el objeto.
Username y password, ¿vale?
Para que nos devuelva el JavaScript Web Token.
Por cierto, alguien me decía de mostrarlo.
Pues aquí está, aquí está el JavaScript Web Token.
Aquí está.
Vale, entonces, ya estamos pasando esto.
Ahora, si vamos al user, donde tenemos este login,
aquí ya nos debería estar llegando el username y el password.
Pero, claro, ¿qué hacemos con esto?
Me preguntarás.
Pues ahora lo que tenemos que hacer, básicamente,
es llamar a nuestro servicio para que nos devuelva lo que tiene que devolver.
Así que lo que vamos a hacer es crear el servicio.
Si recuerdas, tenemos un montón de servicios ya que es para recuperar los GIF y todo esto.
Entonces, entre los servicios vamos a añadir uno nuevo que le vamos a llamar login.js.
Guau, muchas gracias, Sergio.
10 dólares de...
Joder, madre mía.
Sergio Serrano, me tengo que crear un Patreon.
Tienes toda la razón.
Otro viernes aquí, a ver cuándo te creas el Patreon.
Ya queda menos para el Stream Deck.
Muchos saludos, crack.
Tienes razón, queda menos.
Y vaya pedazo de aportación, Sergio.
Muchísimas gracias.
Es muy crack, ¿eh?
10 dólares, menudo crack.
Gracias.
Vale, es que me pongo nervioso con estas cosas.
Ahora ya...
Vale.
Lo que queríamos hacer es el servicio, ¿vale?
El servicio, si miramos aquí, lo tengo en el puerto...
Aquí lo tenéis, ¿vale?
Puerto 8000.
Está en localhost 8000.
No lo he podido deployar todavía, pero os prometo que se va a deployar.
Porque quiero aprender a deployar cosas de Deno, de Dino.
Así que, bueno.
Entonces, voy a poner por aquí el endpoint, que es HTTP localhost 8000, para que así el día de mañana lo quitemos, ¿vale?
Porque esto tiene que desaparecer, debería desaparecer.
Entonces, vamos a poner el servicio que...
¿Qué es lo que le llega como parámetro?
Pues el username y el password, ¿vale?
Ahora, vamos a ver si esto puede ser interesante, ¿vale?
Tenemos que hacer un fetch, que utilizamos el endpoint y a qué ruta tenemos que ir.
A la de login.
¿Esto me lo estoy inventando?
No.
Esta es la ruta que tenemos aquí, ¿vale?
Tenemos que hacer un post al login.
De hecho, lo tenemos aquí, ¿vale?
Entonces, para hacer un post, aquí fetch recibe un segundo parámetro, que son como las opciones de la request.
Entre ellas, podemos indicarle el method, ¿vale?
Y otro son los headers.
Así que le podemos decir...
Además, mira, si tiene autocomplete.
Genial, por si me olvido.
Vale, esto ya no lo hace autocomplete.
Además, como queremos enviar un JSON, tenemos que decirle el content type.
El content type, si no recuerdo mal, es application barra JSON.
Siempre se me olvida, ¿vale?
Y lo que le tenemos que decir, ¿qué es lo que tiene que viajar en la request como el cuerpo de la request?
Pues hemos dicho que necesitamos un objeto, ¿vale?
Que es este.
Pero es un objeto...
Es un JSON, es un JSON, no es un objeto de JavaScript y ya está, ¿vale?
Entonces, lo que tenemos que hacer, esto no lo podemos enviar así como un JSON y ya está.
Tenemos que enviarle un string, pero que, digamos, que siga el contrato de los JSON.
Entonces, lo que vamos a hacer es un JSON.stringify del objeto username password.
Entonces, hacemos un .den, porque el fetch devuelve una promesa.
Esto nos devuelve aquí la respuesta.
Y aquí vamos a ver si ha ido bien la respuesta.
Si no ha ido bien, vamos a hacer un throw new error.
Response is not...
Ok, esto se podría mejorar millón de veces, ¿vale?
Para capturar mejor el error y ver, oye, ¿qué ha pasado aquí?
Y devolver diferentes errores.
Por ahora, vamos a saco.
¿Vale?
Y esto, ¿qué es lo que nos devuelve?
Vale, esto nos devuelve un JSON.
Por lo tanto, tenemos que transformar la respuesta a JSON.
Si ya ha ido bien, si ha sido ok, pues lo que hacemos es devolver la respuesta a JSON.
Y el res.json, que transforma el readable stream, ¿no?
El leer la respuesta del fetch a un JSON, esto también devuelve una promesa.
Así que tenemos que hacer otro .den aquí.
¿Vale?
Aunque seguro que estas cosas...
No sé por qué la explico, seguro que ya la sabéis.
Vale, la respuesta que devuelve este JSON.
Bueno, pues el JavaScript Web Token, esto lo tenemos en la respuesta.
Y ya está, ya podemos devolver el JavaScript Web Token.
Esto debería funcionar, si no se me ha olvidado nada.
Si se me ha olvidado algo, espero que me lo estéis diciendo.
¿Vale?
Vale.
Entonces, ya tenemos nuestro pedazo de servicio que hemos escrito ahí en un momentito.
Así que vamos a importarlo.
Vamos a utilizarlo.
LoginService.
FromServices, que es donde tenemos todos los servicios.
Y aquí, Login.
¿Vale?
Entonces, ahora, en lugar de utilizar esto, que no tiene mucho, ¿no?
No tenía mucha historia.
Vamos a utilizar nuestro servicio.
Que le pasamos el username y el password.
Y cuando tenemos la respuesta...
¿Qué hacemos cuando tenemos la respuesta?
Hacemos esto directamente.
Bueno, por ahora voy a hacer esto, ¿vale?
Luego, si eso me lo miro mejor, porque si queremos añadir más estados, ¿no?
Para ver cuando está cargando, cuando hay un error.
Sobre todo cuando hay un error puede ser interesante, ¿no?
Porque a lo mejor en el Login queremos decirle, oye, ha habido un error, pues tenéis que hacer lo que sea.
Bueno.
Y hacemos el catch.
Solo para loguear el error, ¿vale?
En el caso de que haya habido algo.
Y así, pues, no iremos tan perdidos.
Solo con este cambio, o sea, hemos hecho el servicio.
Ya hemos hecho el Login, ¿no?
Solo con este cambio ahora se supone que en el set JavaScript Token este, aquí lo que vamos a guardar tiene sentido.
O sea, ahora realmente sí que vamos a guardar el JavaScript Web Token que deberíamos.
Vamos a ver si esto es así.
Así que le voy a dar a Login.
Voy a abrir las herramientas de desarrollo y me voy a mover aquí.
¿Vale?
Perfecto.
Vamos a ver.
Voy a hacer esto más grande.
Igual no tanto porque si no, no vamos a ver nada.
Y es que me gustaría quitar un poquito de ruido, ¿no?
Vamos a quitar el info, vamos a quitar warning.
Vamos a dejar los errores y la consola.
Esto fuera, fuera.
Esto fuera.
Perfecto.
Entonces, lo que voy a hacer es darle a Login a ver qué pasa.
¡Pum!
No ha empezado bien, ¿vale?
Abortado, forbidden.
¿Vale?
¿Por qué ha pasado el forbidden?
¿Qué estamos haciendo aquí?
A ver si me da alguna pista.
Pues ha empezado mal esto, ¿no?
Vale.
Si revisamos aquí, tenemos el endpoint.
Vamos a mirar primero la request que estamos haciendo.
A ver qué he escrito bien.
Application JSON, ¿no?
A ver si la estoy liando.
Y el method, está bien.
Vamos a ver el Login aquí.
Y vamos a ver.
Login, forbidden, barra Login, bla, bla, bla.
Sí que tenemos el password y el username.
Y se supone que tenemos el course.
Pues, y el application JSON.
Pues esto ya ha empezado mal.
Vamos a ver.
Este funciona, ¿no?
¿El Login del post este?
Sí, este sí que funciona.
¿Vale?
Vamos a ver si los campos son los correctos.
El username, username y password.
Username y password.
Bueno, mientras, me podéis ir diciendo, ¿eh?
Si veis que hay algún problema.
Alguien me dice, ¿cómo se ve?
Al de course.
Course en principio no debería ser.
De hecho, debería haberse quejado de course.
Luego, este sí que tiene pinta.
¿Vale?
Que dice, JavaScript WebToken.
Vale, ¿dónde no estoy devolviendo bien el WebToken?
No.
Aquí cada uno pone, es 3.000, 8.000, es no sé qué.
Es 8.000, ¿vale?
Es 8.000, ¿no?
Eso está bien.
Es en localhost 8.000 barra login.
Esto sí que lo tengo bien.
De hecho, a ver, voy a pegarlo.
No vaya a ser que la esté ligando.
Eso, esto está bien.
8.000, ¿vale?
Luego, barra login.
Esto está bien.
El method, vamos a ver.
El method es post.
Esto está bien.
Los headers.
Luego es el application.json.
Application, no sé.
Eso sí que está bien.
El body.
Tiene que ser el username y el password.
A mí me parece que está bien, ¿eh?
Es el password.
Ah, qué fail, qué fail, qué fail, qué fail.
Claro, claro, esto está funcionando perfecto.
Muy bien, chicos.
Mira, me lo he dicho aquí.
Está muy bien, Mr. Blasor.
Claro, claro.
Es que, claro, que le he puesto bla, bla, bla.
Es que, madre mía, que funciona bien la API.
Claro, si yo pongo aquí, suscríbete, funciona.
Pero si que pongo bla, bla, bla.
Madre mía, madre mía.
Qué fail, qué fail.
Esto lo corto.
Que nadie lo vea.
Madre mía, menos mal que estáis ahí.
Os voy a tener que pagar ya vosotros.
Efectivamente.
Vamos a ver.
Esto está funcionando correctamente.
Está funcionando bien.
Y, claro, ya decía yo que me da un forbidden.
Y digo, qué raro, ¿no?
Claro, vamos a ver.
El tema es que el forbidden es porque está mal el password.
Claro.
Entonces, sí, sí, claro.
Es not OK.
Yo sí que no estoy OK.
Qué grande.
Muy bien, cracks.
Muchas gracias por la ayudita.
Ahí habéis estado atentos, ¿eh?
Eso es lo que me gusta, que estéis atentos.
Vale, efectivamente.
Entonces, vamos a poner aquí suscríbete, ¿vale?
Y le voy a dar al login.
Vale, ahora sí.
Ahora sí ha funcionado, ¿vale?
Ahora sí.
Ahí está.
Ahora sí.
Entonces, en el network podemos ver que tenemos la response.
Tenemos el JavaScript Web Token.
¡Bravo!
¡Bravo por este trabajo en equipo!
Muy bien, ¿eh?
Muy bien.
Vale, pues ya tenemos esto.
Entonces, ¿por dónde vamos a seguir?
Voy a quitar esto.
Ya tenemos el JavaScript Web Token.
Por supuesto, si le doy a logout, esto va a funcionar sin problema.
Vale.
Funciona bien.
Login.
Otra vez.
Y ya deberíamos estar logados con el JavaScript Web Token.
Vale.
Entonces, esto está bien, pero mira, esto, ¿ves?
Por eso digo, pues estaría bien poner algo de...
Mira, voy a hacerle caso al chico este que decía que...
Oye, ¿por qué no lo pones en el mismo estado?
Vale.
Pues vamos a hacerle...
En este caso le vamos a hacer caso, ¿vale?
Hacemos esto.
Use state.
Porque lo que voy a hacer es saber cuando está cargando el login y cuando hay un error, ¿vale?
Y así no me volveré tan loco, ¿vale?
Entonces, vamos a poner el loading a force y el error a true, por ejemplo.
Esto hay mil formas de hacerlo, ¿eh?
Pero bueno, vamos a hacerlo así que es fácil y siempre luego lo podemos iterar.
Vale.
Entonces, cuando hacemos login, vamos a hacer el set state este.
Que a mí no me gusta nada este nombre, pero bueno.
Así va a ver el chico que sabemos hacerlo.
Todo en el mismo estado, ¿vale?
Para que veas que lo podemos hacer.
Antes de hacer el login estaba cargando y los errores siempre pasarían a false.
Luego el set state, si lo ponemos aquí.
Esto vamos a quitarlo aquí.
Habría terminado de cargar y no habría ningún error.
Y aquí en el catch, pues aquí sí.
Habría terminado de cargar, pero sí que habría un error.
Entonces aquí podríamos poner isLoginLoading, por ejemplo.
IsLoginError o HasLoginError.
Y esto sería, ah, no.
Esto sería state punto, state punto.
¿Vale?
Esto es false.
Bueno, creo que lo he hecho bien, más o menos.
Si no, seguro que me lo decís.
Vale.
Pues entonces vamos al header.
Ah, no, al header no.
A la página de login.
Y lo que vamos a hacer en la página de login es, pues, recuperar esto, ¿no?
De forma que si estamos haciendo loading, bueno, ¿cómo lo he llamado?
¿Cómo lo he llamado esto?
IsLoginLoading, IsLoginLoading, HasLoginError.
Ah, Loading, no.
HasLoginError.
Ahí estás.
Vale.
¿Por qué?
Pues porque así podremos, por ejemplo, evitar que le dé dos veces rápidamente, ¿no?
Y si esto está cargando, pues yo que sé.
Podremos, ah, ah, ah, ah, ah, que estaba pensando.
Estaba pensando que aquí deberíamos poner algo, ¿no?
Así, login.
Entonces hacer aquí el formulario dentro del login o que se vea que estamos en la página de login.
Y a lo mejor esto aquí podríamos hacer que IsLoginLoading, pues decimos, ah, checking credentials.
Por ejemplo, vamos a ponerlo en negrita, a ver que se vea un poquito.
Ay, ay, ay, strong.
Vale.
Y luego vamos a poner que si no está cargando, pues esto, vamos a hacer esto, este formulario.
Aquí podríamos ir más al detalle, ¿eh?
Pero ya sabéis que me gusta dejarlo para que luego le deis caña.
Y si tenemos un error, pues credentials are invalid, por ejemplo, ¿vale?
Ha sido un poco a saco, ¿eh?
Así que no me hago responsable.
Vale, vamos a ver.
Uy, ¿cómo que hay un error ya de primeras?
¿Qué ha pasado aquí?
El error, ay, he puesto aquí true.
Vale, no me habéis avisado, ¿eh?
No, no he puesto el H2, está fuera del H2.
Ay, se me ha olvidado cerrarla.
Es que alguien ha dicho, no, por favor, no pongas un H2 dentro.
No, no, no quería ponerlo dentro, ¿eh?
No está dentro el formulario.
Pero esto, es que esto se me ha colado.
Se me ha colado.
No, no, esto quería hacerlo así, ¿vale?
Vale, vale.
Esto quería hacerlo así, ¿vale?
Vale.
Ahora, bla, bla, bla, credentials are invalid, ¿vale?
Y suscríbete.
Ahora sí, ha salido el checking credentials y ahora nos ha sacado.
Ay, vale.
Bueno, vamos avanzando, vamos avanzando.
Vale, de esta forma al menos ya tenemos esto.
Ahora, ahora que estamos logados, ¿no?
Que hemos iniciado sesión, pues, ¿cómo podemos demostrarlo, ¿no?
Realmente, ¿cómo podemos hacer algo?
Pues, vamos a empezar a crear el componente FAP, FAP, FAP, ¿vale?
Para hacer un favorito.
Entonces, vamos a quitar servicios y voy a crear aquí un componente en components
que le voy a llamar FAP de favorito.
Y, ¡ay, ay, ay, ay!
Perdón, que se me ha ido aquí.
Vale, y aquí vamos a poner el index.js.
Index.js.
Sí, no, no, no quería meter H2, ¿eh?
Ya decía, ya decía yo, primera vez que meten un formulae dentro de H2.
No, hombre, no.
Eso era, ha sido un error, ha sido un error.
Mea culpa, mea culpa.
Vale, pues, vamos a añadir el FAP.
Vamos a añadir el FAP.
Creamos un componente FAP.
Lo mismo, yo tengo aquí este snippet, ¿vale?
Para crear componentes que le doy, ¡pum!
Y ya le digo FAP.
Lo que tiene que llegarle seguro es la ID del GIF del que queremos hacer favorito.
Y aquí, pues, vamos a ver qué queremos renderizar.
Botón, ¿no?
¿Cómo se nos puede ocurrir este botón?
Pues, un botón que al hacer clic, aquí hacemos el handle clic o handle FAP.
Aquí vamos a poner un corazón.
Este.
Vale, esto hay que ponerlo en un span.
¡Ay!
Que si no se nos queja.
Esto era role image, area label FAP GIF.
No le ha gustado.
A ver.
El role, ¡ah!
Es IMG, perdón.
Vale, ya está.
¿Eh?
Accesibilidad, que no se nos olvide.
Y esto es mi talk, ¿eh?
De que tengo que ordenar las props alfabéticamente.
Sí, no sé, no sé por qué me pasan estas cosas.
Vale.
Entonces, por ahora, vamos a poner el handle clic.
Vamos a hacer que primero esto visualmente funcione.
Ay, no sé, como estoy con deno, no sé por qué lo detecta.
Y a veces, cuando pongo el alert, me importa ahí lo que le da la gana.
¿Vale?
Vale, por ahora vamos a hacer un alert aquí.
Lo primero, vamos a enfocarnos en que visualmente esto se vea bien.
¿Vale?
Entonces, este botón, por ahora lo dejamos así.
Y vamos a importarlo.
¿Vale?
Vamos a importar, porque el botón este no tiene mucha historia,
pero lo vamos a poner dentro del GIF.
Entonces, aquí dentro del GIF importamos fab from components fab.
Y lo vamos a poner justo antes del enlace, porque esto también es un tema de accesibilidad, ¿no?
No puedes poner dentro de algo clicable, algo clicable, porque se vuelve loco.
Vale.
Ahí está nuestro botón.
Un montón de corazones.
Vale.
Obviamente, esto vamos a tener que meterlo en algún tipo de GIF buttons, porque, bueno, quién sabe.
Igual día de mañana, pues, le ponemos más botones, como por ejemplo para compartir, que alguien me lo dijo.
¿Vale?
Por ahora no.
Alguien dice, Rob, ¿dónde guarda el JavaScript Web Token?
En el local storage, por ahora no lo estamos guardando, ¿eh?
Pero igual luego, cuando veamos que es un poco pesado esto, lo que hacemos es guardarlo en el...
Lo podemos guardar en el session storage, por ejemplo.
¿Vale?
Pero ahora lo veremos.
Vamos a primero a arreglar un poquito esto.
Vale.
GIF buttons.
El GIF buttons...
GIF buttons...
Lo que voy a hacer aquí es ponerlo position absolute, que esté ahí en la quinica, ¿vale?
Esto seguramente se va a quedar por detrás, ahora lo veremos.
Pero voy a poner aquí un position...
Bueno, para que veáis el error, ¿no?
Pero si yo hago esto, me imagino...
¿Ves?
Me lo ha puesto aquí arriba.
Porque no es relativo a nuestro elemento, así que le vamos a decir un position relative a este GIF, ¿vale?
Y ahora lo que ha pasado es que seguramente se está quedando...
Está detrás del GIF.
Entonces tendríamos que aumentar el zindex, ¿vale?
Vale.
Vale.
Uy, perdón.
Perdón por soplar, ¿eh?
Perdón.
Que sé que eso es un poco molesto.
Perdón.
Entonces...
Es que estaba pensando.
Entonces, ya aquí en el FAP, lo que podríamos hacer...
Ahora este botón no hace nada, ¿eh?
Bueno, sí.
Hace el alert este, que no está mal.
Pero ya podríamos utilizar aquí nuestro import user, ¿no?
Porque podríamos averiguar si el usuario ha iniciado sesión.
Por ejemplo, si es log nuestro usuario, vamos a hacer una cosa.
Vamos a hacer el alert, por ahora.
Por ahora el alert, ¿no?
O vamos a hacer otra cosa.
Si no está loggeado, lo que vamos a hacer es que navegue al login.
Esto es muy típico, ¿no?
Cuando le intentas dar a algo que, por lo que sea, necesitas sesión, ¿no?
Pues te dice, oye, te tienes que loggear.
Vale.
Pues vamos a hacer eso.
Que se tenga que ir al login.
El navigate, ya sabéis que lo tenemos que sacar del use location, del router.
Esto es del real router o del router que utilicéis, ¿vale?
Entonces, vamos a poner el navigate.
Esto es para navegar de forma así imperativa dentro de tu componente.
Entonces, ahora no estamos loggeados.
Por lo tanto, si le doy, me lleva el login.
Si me loggeo y le doy, me sale el alert.
Vale.
Entonces, ya el FAP, pues ya por lo menos, está haciendo esto.
Ahora arreglaremos lo de la sesión porque será un poco, claro, me imagino que esto va a ser un poco coñazo, ¿no?
Ahora, cada vez que hacemos un cambio, nos va a echar el usuario.
Y esto es un poco, no me gusta nada mucho.
Vale.
Entonces, vamos a estilar poquito, ¿eh?
Tampoco reconozco que no soy, sobre todo así con rapidez.
No soy el mayor maquetador.
Esto que no me vuelvo a pasar.
Así.
Vale.
Entonces, voy a poner aquí un class name que esto sea FAP.
Vale.
Voy a formatear esto.
Perfecto.
Vale.
Aquí he añadido este archivo FAP.css.
Más que nada, pues para...
¿Qué class name le he puesto?
GF FAP.
Vale.
Más que nada, pues para...
Nada.
Unos toquecitos, ¿vale?
Background.
No sé si tienen algún color ahí pensado.
Vamos a ponerle un rojo, un rojo más rosa.
Vale.
Ha salido algo, ha salido algo.
Vale.
Ahora esto me va a empezar a dar mil millones de problemas.
De hecho, voy a poner aquí el span.
Vamos a quitarle el borde.
No me está haciendo...
Ah, digo, no me está haciendo absolutamente ningún caso.
Bueno, esto, borde, radius...
Bueno, vamos a hacer que sea redondito.
Vale.
Más o menos.
Vale.
Cuando nos pongamos encima que nos salga el pointer...
Eh...
Me encantan las preguntas.
Dice...
¿Ha explicado alguna vez por qué no usa semicolon?
Tengo un vídeo pendiente.
Tengo un artículo escrito que todavía no lo he hecho y os lo explicaré por qué no uso semicolons.
Pero, bueno, que si usáis, que no pasa absolutamente nada, que ya está bien, ¿vale?
Que cada uno...
Que no está...
No creo que haya uno mejor que el otro.
Pero, bueno, os puedo comentar por qué yo no lo utilizo.
A ver, esto que quede un poquito más oscuro, por lo tanto, hacemos eso, que tenga más opacidad...
¡Uy, no!
No, esto no lo quiero poner aquí.
No, no, no.
Esto lo quiero poner en el hover.
Claro, lo que quiero es el hover.
A ver, ¿no?
Que sea más...
Esto aquí, lo que seguramente...
Es que los emojis para centrarlos un poco, coñazo.
Entonces, lo que vamos a hacer a saco es meterle aquí que tiene un ancho que más o menos se adapte al centrarlo.
Vale, ahí está.
Bueno, queda bien, ¿no?
Más o menos.
¡Ey!
¡Ey!
¡Qué bonito!
Vale.
Ya está.
Creo que hemos terminado el CSS para todo el vídeo, ¿vale?
Vale.
Entonces.
Vamos a ver.
Bueno, ya has podido ver, ¿no?
Que me ha vuelto a echar.
Entonces, seguramente, si queréis, arreglamos esto ya y nos lo quitamos de encima, ¿vale?
Y ya está, ¿vale?
Entonces, ¿cómo podemos hacer que nos guarde un poco...
O sea, que nos guarde la sesión.
Justamente lo que queremos, que nos guarde la sesión.
De forma que, si yo ahora refresco aquí, no me vuelva a aparecer el login porque en realidad yo, pues, ya me he logueado, ¿no?
Entonces, voy a cerrar todos los archivos de nuevo y vamos a ver.
Lo primero sería tocar el contexto.
Porque en el contexto, aquí es donde estamos como iniciando el JavaScript Web Token.
Entonces, ¿dónde podemos recuperar ese JavaScript Web Token?
O sea, podríamos guardarlo, por ejemplo, del sessionStorage.
Window.sessionStorage.
¿Vale?
Y podríamos tomar el item que sea JavaScript Web Token.
Lo he escrito bien, ¿no?
¿Por qué se queja esto?
Que dice que no existe.
Igual está borracho.
Vale.
Entonces, lo que vamos a hacer es recuperar el sessionStorage del sessionStorage del JavaScript Web Token.
Al menos para que, mientras no cerremos el navegador, no nos eche.
¿Vale?
Esto por un lado.
Voy a hacer esto así para que se vea bien.
Y por si te lo estabas preguntando, sí se puede utilizar una función para poner un estado inicial.
Y esto tiene una explicación de por qué lo hago.
Quiero decir, esto funcionaría exactamente igual, pero esto, aquí tenéis un midu truco o algo que creo que es muy interesante y muy poca gente sabe.
Es que el estado inicial del useState, aunque solo se utiliza una vez, cada vez que se renderiza tu componente,
imagínate que este userContextProvider se volviese a renderizar,
volvería a ejecutar lo que hay aquí dentro, en la línea 7.
Lo volvería a ejecutar.
¿Vale?
Aunque no actualizaría el estado con eso, pero volvería a ejecutar esa línea.
¿Y qué pasa?
Que el sessionStorage bloquea el thread.
Entonces, es una buena práctica que este tipo de formas de tener estado inicial,
con cálculos que son costosos, lo pongas en una función.
Porque esta función sí que es verdad que se va a ejecutar solo una vez.
Entonces, bueno, ahí tienes el midu truco de React, por si no lo sabíais,
que igual sí que lo sabíais y me parece interesante.
Luego, yo voy a utilizar sessionStorage, pero si queréis podéis utilizar localStorage.
LocalStorage, pues, cuando cerréis el navegador, seguirá estando ahí.
Tanto el sessionStorage como el localStorage, creo, nos va a funcionar y creo que para la primera parte va a estar bien,
pero tened en cuenta que a lo mejor tiene problemas de seguridad, que tendríamos que hacer más cosas y trabajarlo más
y a lo mejor la segunda parte, pues, lo subimos de nivel, ¿vale?
Pero estamos yendo como poco a poco, ¿vale?
Entonces, sessionStorage por ahora y cada uno que lo haga como quiera.
Aquí es donde lo leemos, ¿vale?
Leemos el JavaScript Web Token y lo recuperamos.
Luego, en el hook, lo que vamos a hacer, en el hook del useUser, lo que vamos a hacer es que cuando escribíamos el JavaScript Web Token,
aquí lo que podríamos hacer, pues, también sería sessionStorage.setItem, JavaScript Web Token,
y aquí, pues, escribimos el JavaScript Web Token.
Y, por supuesto, creo que puede ser, esto puede estar bien, ¿no?
Que lo borremos cuando hay un error.
No vaya a ser que tengamos, no sé, que tenga el JavaScript Web Token, pero va a un error al iniciar sesión y se guarde, no sé, cosas raras.
Y, por supuesto, cuando hagamos el logout, pues, también, ¿no?
Y, entonces, guardamos los cambios y, vale, hago logout, vale, hago login, hago login, refresco, ahí lo tenemos.
Y, si abro las herramientas de desarrollo, vale, bueno, ese warning o lo que sea, no es nuestro, ¿eh?
Nosotros no hemos hecho nada de eso, no es nuestra culpa, vale.
Si miramos en el sessionStorage, vale, pues, aquí lo tenemos perfectamente.
Y ya podemos tranquilamente, pues, seguir programando y ya lo tenemos aquí en logout y, pues, ya lo tenemos persistiendo.
Ya tenemos nuestro JavaScript Web Token persistiendo, ¿vale?
Una cosita menos, una cosita menos.
¿Por dónde íbamos?
Que tengo aquí el guión, más o menos, para que no se me olvide, ¿vale?
Vale.
Estábamos con los FAPs.
Entonces, necesitamos, vamos a hacer una cosa y es utilizar el UserContextProvider para tener la lista de FAPs que al usuario, pues, le ha dado FAP.
Vamos a utilizar el mismo contexto.
Podríamos tener otro separado y, seguramente, sería una buena opción.
Pero, bueno, en este caso vamos a hacerlo aquí, en el UserContextProvider para reutilizar lo que ya habíamos hecho.
Así que este FAPs también lo vamos a meter aquí en el value para tenerlo accesible cada vez que le damos el contexto en cualquier componente o cualquier hook.
Y también el setFAPs, ¿no?
Para esto...
Esto, vamos a hacerlo un poquito más legible.
Pam, pam, pam, pam.
Uy, pam.
Vale.
Esto así.
Vale.
Entonces, ahora tenemos los FAPs y tenemos un array vacío y esto no está haciendo nada.
Lo que vamos a querer es que cada vez que le demos al FAP, pues, esto se actualiza.
Para eso, un poquito más de lo mismo.
En el useUser este tenemos que añadir una forma de meter el FAP.
Vamos a poner un addFAP, por ejemplo.
Voy a decir qué me decís.
Saludo a mi gente, me quedé dormido.
Arquímedes, vamos a señalarte todos, me quedaste frito.
¿Qué requeriría medidas de seguridad extra?
Sí, sí, sí, sí, seguramente.
Esto, sí, sí, mira, Belardo preguntaba.
Sí, esto tiene medidas, o sea, tiene problemas de seguridad.
Esto necesitaríamos hacer más cosas y la API necesitaríamos hacer más cosas.
Pero creo que como primera parte ya está suficientemente bien, ¿vale?
Vale.
Entonces, ¿qué vamos a hacer?
Con el useStep, vale, lo que queríamos era añadir lo del FAP.
Entonces, vamos a ponerle FAP directamente y esto es básicamente muy parecido.
Aquí tenemos el callback, le metemos esto.
¿Qué vamos a querer cuando llamemos al FAP?
Pues pasarle la ID.
Aquí vamos a tener también un FAPService donde le vamos a pasar la ID y el JavaScript WebToken, ¿vale?
Lo vamos a necesitar para que sepa a qué usuario se refiere y si tiene permisos para hacer esto.
Entonces, esto nos va a devolver el endpoint, si nos fijamos, ¿vale?
Este endpoint, si yo le doy, vale, ahora no funciona porque el JavaScript WebToken no será correcto.
Pero si hago un getFAPS con este JavaScript WebToken, ahí, lo he copiado mal.
Vale.
Ah, no, lo había copiado bien.
A ver, a ver, ¿qué está pasando aquí?
¿Qué está pasando aquí?
A ver, este es el JavaScript WebToken.
¿Y ahora por qué me dice el getFAPS este que no está autorizado?
Ahora, no sé por qué.
Vale.
Entonces, vamos a hacer un post para que veamos, ¿no?
Hacemos un post aquí y lo que me devuelve es la lista de FAPS que tenemos, ¿vale?
O sea, el que ha añadido y todos los que tuviese ya.
Y esto nos va a venir bien porque así cuando hagamos un FAP lo recuperamos.
Y también, bueno, aquí tenemos para borrarlo, lo vamos a borrar, ¿vale?
Porque no queremos que esté y nos genere ruido.
Ahí, ¿por qué dice que no encuentra?
Vaya.
A ver si esto ahora deja de funcionar.
Bueno, a ver si me añade otro.
A ver, ¿sí?
Vale, me lo está añadiendo.
No sé, a lo mejor el delete, tampoco lo he mirado mucho el delete.
Vale, el caso es que el post, cuando hagamos un post, nos devuelve la lista de FAPS.
Y esto nos va a ayudar, pues, a sincronizarlo, ¿vale?
Así que en el servicio, esto nos va a devolver la lista de FAPS y esto haremos un set FAPS de FAPS.
Y este set FAPS lo vamos a recuperar del contexto.
Así que este set FAPS lo tenemos aquí.
Y luego también aquí tendríamos la lista de FAPS por si la queremos utilizar.
Ya hemos visto que antes la hemos añadido en el contexto, ¿vale?
Esto es en el caso de que vaya todo bien y en el caso de que haya un error,
pues, vamos a poner un console error del error, ¿vale?
FAPService, bueno, obviamente el FAPService no existe.
Vamos a poner add FAPService, que creo que esto nos ayudará a entender mejor lo que hace.
Vale, ya escribo el token, set FAPS y vamos a crear el add FAPService,
que es muy parecido a este, al del login, ¿vale?
Add FAPService y esto lo add FAPService.
Pues nada, vamos a los servicios addfab.js.
Es muy parecido al login, así que voy a hacer un copy-paste de estos que, vamos, pam, ahí está.
Ahora, esto es add FAPS, esto es, buena pregunta, esto es FAPS, ¿vale?
Esto es FAPS, y lo importante aquí es que se le tiene que pasar la id aquí.
Así que aquí le pasamos la id.
Así que entre los parámetros, aquí vamos a tener la id y el JavaScript Web Token.
Y de hecho, el JavaScript Web Token es lo que ahora le vamos a pasar en el body.
Esto hasta aquí viene.
Luego, esto ahora no devuelve un JavaScript Web Token.
Esto devuelve FAPS.
¿Es FAPS?
Sí, es un objeto que tiene FAPS, ¿vale?
Y estos FAPS son los que vamos a devolver, con el que vamos a setear el estado y se cerra el círculo, ¿vale?
Esto lo puedo hacer chiquitito, este también.
Y nos vamos a enfocar en este, ¿vale?
Esto, de hecho, esto lo podemos dejar así, que queda un poquito más bonito, ¿vale?
Entonces ya tenemos el FAP y lo vamos a exportar aquí,
de forma que ahora en nuestro botón FAP, FAP.js, ¿vale?
Ahora podríamos utilizar el FAP.
Y ahora pues ya hacemos esto.
Y, vale, esto hasta aquí bien.
Ahora lo que vamos a ver es si en las herramientas de desarrollo vemos que esto funciona.
¿Vale?
Ahora hacemos el click y hacemos un FAP y esto ya pues viajará.
Ah, ojo, ojo, aquí hay un error, ¿no?
Porque este compu... Mira, lo he visto antes de...
Esto aquí, esto aquí está nombrado.
Le estamos pasando un objeto.
Y aquí le está ahí pasando directamente la idea.
Esto me iba a petar, lo sabe Dios que me iba a petar.
Madre mía.
Vale.
Espero que no haya cometido más errores así.
Porque son de estos errores que te vuelven loco, ¿vale?
Vale.
Entonces, vamos a ver si le doy aquí, ¿qué pasa?
Vale, no pasa nada.
Eso es buena noticia.
Porque eso significa que no ha petado.
Bueno, ok, ok, ok, está ahí, está ahí.
Bien, bien, me gusta, me gusta.
Entonces, yo si recupero aquí los FAPs, vale.
Aquí tenemos este GIF.
Ya está, ya está la primera.
Vamos, vamos, vamos.
Vale, hemos añadido el FAP, pero obviamente no se diferencia, ¿no?
El FAP que tiene aquí no se ve diferente.
Una cosa que podemos hacer con esto, para empezar, ¿no?
Tenemos el objeto, tenemos el FAPs, ¿vale?
Tenemos la lista de FAPs, la tenemos aquí.
Aquí en el use, uy, perdón, perdón, perdón.
Aquí.
El useUser tiene FAPs.
Entonces, igual que tenemos, esto lo voy a cambiar el nombre, ¿vale?
Voy a poner addFAP.
Esto, addFAP.
Es que FAP igual queda demasiado addFAP.
Al menos parece más un método, ¿no?
Y aquí vamos a ponerle también addFAP.
A este método le llamamos addFAP.
Y aquí, en el useUser ahora vamos a exportar la lista de FAPs.
Hay dos opciones aquí.
Mira, vamos a hacer esto, pero lo vamos a cambiar, ¿vale?
¿Qué podríamos hacer?
Aquí tenemos la lista de FAPs.
Entonces, podríamos hacer isFAP y le podemos decir faps.som y miramos si la ID, la ID de ese favorito, de ese GIF, está en la lista de favoritos, ¿no?
Y entonces, según este isFAP, lo que podríamos hacer es pintar diferentes cosas.
Por ejemplo, voy a hacer esto un poquito más chiquitito, a ver si así se ve un poquito mejor, ¿vale?
Pero básicamente lo que he hecho es recuperar la lista de FAPs y lo que hago es un .som.
Lo que hace el .som es devolver un true en el caso de que encuentre alguno.
Y le digo, vale, de toda la lista de FAPs, ¿hay alguno que sea exactamente de los favoritos?
¿Que tienes ahí uno que tenga la ID de este?
Vale, pues eso significa que este GIF ya está en favorito.
Por lo tanto, podríamos cambiar cómo funciona este GIF, o sea, este botón.
De hecho, aquí ya podríamos decir que si es favorito haga, o sea, si no es favorito, esto sería, si ya es favorito que haga aquí un delete FAP,
que no lo vamos a hacer hoy, ¿no?
Pero, porque no da tiempo, pero ya podríamos, ya van por aquí los tiros, ¿no?
Que podríamos hacer esto.
Eso por un lado.
Por ahora vamos a dejar el add FAP para todo, pero lo que vamos a hacer es que cambie lo que se pinta.
De forma que vamos a hacer, tener un label y tener, vamos a tener el label y el emoji.
Vamos a tener dos cosas distintas, un label y un emoji, ¿vale?
De forma que el label, en el caso de que sea FAP, sea, el label será remove GIF, ¿no?
Porque ya está favorito, lo queremos quitar de los favoritos.
Favorites y como emoji, para quitarlo, una X.
Vale, bueno, más o menos para que se vea la diferencia, tampoco nos volvamos locos.
Add GIF from two favorites y el emoji ya hemos dicho que es un corazón, ¿vale?
Entonces, ahora, este label y este emoji que tenemos aquí, que por cierto,
esto es una cosa que me encanta mucho hacer para utilizar una ternaria
y no tener que escribirla dos veces, lo que hago es un array, lo desestructuro y paso dos arrays.
Esto es una fricada mía, ¿eh?
No digo que lo hagáis ni que sea una buena práctica, pero bueno, habéis visto que es bastante cómodo, ¿no?
Porque lo hemos hecho bastante rápido.
Vale, entonces ahora tendríamos el label y el emoji.
Guardo los cambios aquí, ¿vale?
Me ha petado algo, pero de una forma horrible.
¿Por qué?
Ah, fíjate.
He puesto delete FAP y como no ha sabido dónde encontrarlo, ha dicho,
madre mía, yo lo busco, vamos, y lo ha buscado hasta en deno.
Flipa.
Vale.
Vale, menos mal que lo he quitado.
Y, claro, vale, ahora miramos esto.
Vamos a guardarlo todo.
Vale.
A lo mejor el fallo ese es que le faltaba recuperar algunos cambios.
Vale, ahora, ¿qué pasa?
Que nada más entrar no estamos recuperando la lista de favoritos del usuario.
Y por eso, aunque haya algún favorito que ya esté en el usuario, no lo vemos, ¿vale?
Pero cuando le demos sí que debería recuperarlos y ver si hay alguno que sea favorito ya, ¿vale?
Así que, por ejemplo, este.
Vamos a darle.
Pam.
Vale.
Y este.
Pam.
Vale.
O sea, que esto está funcionando ya.
Y esto está funcionando, está funcionando bien.
O sea, ya nos está indicando cuál es favorito y cuál no.
Claro, el tema es que si yo refresco aquí, los pierdo.
Pero no significa que no esté ese GIF.
El problema es que si te has fijado, todavía no estamos recuperando los GIF favoritos de primeras.
Y eso lo vamos a hacer ahora.
Así que, vale, voy a ponerme aquí.
Y la primera vez que escucho de .som.jg, pues es una maravilla.
Mucha gente utiliza el .filter para encontrar un elemento.
Y hace un .filter y accede a la primera posición, a la posición cero.
Y existe el .fine.
Y es del palo porque no utilizas el .fine, que ya te devuelve directamente el primero que encuentras.
Pero entonces, hay gente que para ver si existe uno, busca el .fine.
Cuando puedes utilizar el .som, que te devuelve un true o un false.
Y es mucho más cómodo.
O sea, es mejor porque se lee mejor el código, ¿vale?
Sí, mira, de hecho lo están comentando por aquí.
¡Ay, mira!
Brian Graff.
Brian, 200 soles argentinos, pesos argentinos.
Muchas gracias por compartir estos conocimientos.
Es excelente.
Muchas gracias.
Brian, te lo agradezco un montón.
Gracias de corazón.
Muchísimas gracias.
Gracias por el aporte.
Viendo desde Chile, saludos, dice Marcos.
Los corazones de favoritos solamente deberían aparecer los GIFs cuyos ID están en la lista.
No.
El corazón, lo que vamos a hacer es que el corazón aparezca en todos.
En todos los GIFs, ¿no?
Y que cuando le des, te lo añada a favoritos.
Y para quitarlo, que te aparezca la X.
Sé que no es la mejor UI del mundo, ¿vale?
Lo sé.
Y os invito a que hagáis PRs al respecto.
Pero bueno, creo que más o menos para que se vea.
Vamos a hacer que el botón se vea en todos.
Y el botón del corazón sea como quiero añadirlo a los favoritos, ¿vale?
Más o menos.
¿Qué más?
¿Qué más?
A ver, me comentáis por aquí.
Gente que se acaba de añadir.
La contraseña es suscríbete.
Dado que no está en BD.
Sí.
¿El código lo comparto en algún repositorio?
Sí, efectivamente lo comparto.
Así que no os preocupéis.
Que por cierto, aprovecho para pediros algo.
Ya que estamos ahí 228.
Que os agradezco un montón que estéis aquí.
Que os suscribáis, por favor, al canal.
Que ayuda un montón.
A mí me ayuda cuanto más seamos.
Más vídeos de estos haremos.
Y más contenido.
Y por supuesto que le deis un like al vídeo.
Que eso ayuda también un montón.
Y hombre, a uno le anima.
No sé.
A mí me anima.
Vale.
Pues vamos a arreglar el tema de que, claro, nada más entrar.
Pues esto es un poco raro, ¿no?
Que no te salen los favoritos.
Y voy a aprovechar y voy a poner musiquita.
¿Vale?
Que me he quedado así.
Y pasamos al código de nuevo.
¿Vale?
Entonces, ¿cómo hacemos esto?
¿Qué estoy pensando?
Necesitamos el servicio.
Ah, lo que había pensado del check is esto.
Que a lo mejor tendría sentido que lo hiciese el hook.
O que el hook te exportase esto.
Porque parece una funcionalidad que se puede utilizar.
¿No?
O sea, en lugar de hacer esto, que hagas un...
Exportar un check is fab, ¿no?
Y lo haga el hook.
Pero bueno, era una idea.
¿Vale?
Entonces, vamos a empezar ahora por el servicio.
Que creo que es lo primero que ya se me ocurre que vamos a necesitar.
Para getFabs.
Y esto lo vamos a copiar del addFab, más o menos.
Es muy parecido.
Solo que el getFabs, para recuperar los favoritos, no necesita ID.
Porque los queremos recuperar todos.
Así que esto fuera.
Esto fuera.
Luego el método es get.
Y esto tiene truco, ¿no?
Porque a un get tú no le puedes pasar el body.
Entonces, yo lo que he hecho, que esto es otra cosa que se suele hacer,
es que se acepte un header autentificación o token o como queráis.
Yo, en este caso, he puesto authentication.
Voy a asegurarme, porque...
A ver, a ver.
Esto lo tenía por aquí, ¿eh?
Pa, pa, pa.
Authorization.
Authorization.
Vale.
Pues eso.
No es autentificación, es autorización.
Vale.
Y le puedo pasar por ahí el JavaScript Web Token directamente.
Y así también lo detectará.
Bueno.
Igual puede ser mejor opción pasarlo siempre por header,
sino pasarlo por el body, la verdad.
Igual lo miramos, ¿eh?
Para el siguiente.
Entonces, a ver, que me sitúe.
Ya tenemos el get, tenemos el headers, la autorización.
Esto está bien.
Luego la respuesta es todo vuelvo un faps.
Entonces teníamos los faps.
Vale.
Ahora, el tema es, ¿dónde vamos a llamar a este servicio?
¿Dónde lo llamamos?
Porque, claro, uno podría pensar, vamos a llamarlo en el hook,
pero no podría.
O sea, no es el sitio.
Porque es que este hook se puede llamar más de un...
De hecho, se llama desde un sitio diferente, ¿no?
Lo llamamos desde el header, lo llamamos desde un montón de sitios.
Si nosotros ponemos aquí un useEffect, la liamos parda, pardísima.
O sea, claro, porque se va a llamar cada vez que se ejecute ese hook.
Aquí no es el sitio donde deberíamos hacerlo.
Deberíamos hacerlo en un sitio que solo ocurra una vez
y de alguna forma hidratemos esta información de inicio, ¿no?
¿Y dónde podemos hacer eso?
A ver si lo sabes.
En el contexto.
Lo vamos a hacer aquí.
De hecho, tenemos aquí el state.
Ya tenemos este estado.
Entonces, aquí sí que no podemos hacer una llamada fetch.
No podemos hacer esta función con una llamada fetch.
Aquí sí que tenemos que hacer un useEffect.
Pero aquí ya podríamos hacer el useEffect, ¿vale?
Que nada más montarse lo hiciese.
Aunque en realidad aquí lo que vamos a querer es que cada vez que cambie
el JavaScript Web Token, que es lo que nos está indicando que se ha logueado
o se ha dejado de loguear un usuario, ¿no?
Pues lo tenga.
Entonces, aquí se me ocurre que si no tenemos JavaScript Web Token,
lo que deberíamos hacer es resetearle los favoritos.
Esta podría ser una.
No sé si esto va a ser problemático.
Bueno, lo vamos a ver.
Vale.
Pero si tenemos JavaScript Web Token, bueno, que igual esto podría ser así.
¿Vale?
Si llegamos ahí, si no tenemos JavaScript Web Token, ¿no?
Si ha cambiado el JavaScript Web Token, ¿no?
Lo estamos poniendo como una dependencia del efecto.
Por lo tanto, este efecto se ejecutará cada vez que el JavaScript Web Token cambie.
Por lo tanto, si no tiene JavaScript Web Token,
estoy pensando si esto deberíamos hacer en otro sitio.
Bueno, bueno, lo voy a dejar así y qué puede pasar.
Lo peor que puede pasar es que esto reviente y se caiga al directo y qué más da.
Bueno, si no tenemos JavaScript Web Token, vamos a resetearle los fabs al estado inicial.
Y si tiene, aquí lo que vamos a hacer es llamar al servicio que hemos creado.
Así que esto era un get fabs from services, get fabs, ¿vale?
Y aquí pues nada.
Tenemos el get fabs, necesita el JavaScript Web Token, que se supone que tendrá algún valor.
Hacemos un then.
Aquí tenemos la lista de favoritos.
Por lo tanto, ya podemos hacer directamente un set fabs, ¿vale?
Y podemos pasarle directamente la referencia del método,
porque la entrada del método encaja con lo que llega de la promesa, ¿vale?
Esto no es magia, sino que es, básicamente estamos haciendo como un túnel,
una tubería por este método, justamente por casualidad,
bueno, no tanta casualidad, ya lo estamos haciendo apuesta,
la entrada de ese método es justamente lo que está devolviendo el punto then, ¿vale?
Entonces le podemos pasar por parámetro la función y ya la pillaría.
Vale, entonces ya tenemos el set fabs y esto es así.
Guardamos los cambios.
Y madre mía, si es que esto funciona la primera.
Esto funciona la primera.
Señores, sí, señoras.
Vale, ya lo tenemos, ¿vale?
Entonces, en el efecto, si tenemos el JavaScript Web Token,
y esto va cambiando, ¿no?
Pues, ¿qué está haciendo?
Está haciendo esta llamada.
Hace la llamada, recupera los favoritos y ya de primeras, pues ya lo vemos.
Entonces, pues nada.
Ahora ya podemos ir añadiendo favoritos.
No sé si se ve, pero los estoy añadiendo.
Y ahora, si refresco, pues podemos ver de primeras que están.
A ver, es imperceptible.
No te voy a engañar.
Pero sí que hay como un pequeño saltito, ¿no?
¿Por qué?
Porque como tenemos un estado, esto es asíncrono y tal.
Entonces, cuando lo tengamos deployado, seguramente nos damos cuenta que tenemos que evitar,
a lo mejor, que se muestren hasta que no tengamos esta información, ¿no?
Porque, ¿qué pasa?
Que podría ser que al principio el usuario viese que puede añadir el GIF y luego de repente dice,
ah, no, si ya lo he añadido, ¿no?
Puede haber ahí un lapso.
Entonces, a lo mejor lo que tenemos que hacer es, pues, o esperar a que los favoritos estén
cargados para enseñar los GIF.
Eso puede ser una.
A mí no me suele gustar.
Me gusta más ir presentando la información al usuario conforme ya la tenemos, ¿no?
Y cuanto antes, mejor.
Y si es asíncrono, pues, oye, va llegando.
Entonces, lo que podemos hacer es que el botón aparezca en cuanto tengamos la información inicial
o no se necesite.
Pero bueno.
Entonces, si hago logout, vale.
Aquí podemos ver que ha vuelto al estado inicial y no se ha petado, no ha pasado nada.
Si voy a login y hago otra vez esto, pues, nada.
Aquí ya tenemos otra vez los iniciales.
Entonces, si voy y busco Matrix, pues, aquí tengo a Neo, ¿vale?
Y ahora refresco y aquí podemos ver que ya os tenemos.
Pues, nada.
Creo que ha estado bastante bien, ¿no?
En una hora y media.
256 que nos están viendo y 256 y hay uno que nos ha dado dislike.
A esa persona.
Vamos a buscarte.
Vamos a enviar a nuestro mejor hombre, a Neo, para que te busque.
O es porque no te haya gustado.
De verdad.
No, hombre.
No pasa nada.
Pues, nada.
A los 256 que estáis, ya sabes.
Dadle like, que estas cosas me animan para seguir.
Y hasta aquí esto ha estado bien, ¿no?
Hemos tenido ya el inicio de sesión.
Tenemos el logout.
Que, bueno, el logout, al final lo único que haces es...
Podríamos hacer el logout más interesante.
Ahora mismo lo que hacemos es borrar, básicamente, el JavaScript Web Token.
Pero lo que podríamos hacer es invalidarlo, ¿no?
Que cuando cerremos la sesión, enviemos al servidor de decirle, oye, bórrame este token.
Y que te lo borre, ¿vale?
Y, además, eso podría ser algo interesante.
Me lo voy a pensar para la segunda parte.
En la segunda parte, ¿qué vamos a hacer?
Claro, porque ahora no quería hacer el registro.
Al final es muy parecido al login.
Aquí podríamos hacer otro usuario, ¿no?
Y podríamos hacer, yo qué sé, podríamos poner el nombre que ha puesto el dislike.
El hater no le gusta.
Vale, pues al hater que no le gusta esto, ¿vale?
Le podríamos hacer un usuario, ¿vale?
Ahora se ha creado el usuario y podríamos loguearle.
Y decirle al hater que no le gusta, ¿vale?
Pues nos devuelve el JavaScript Web Token que tendría al hater que no le gusta.
Entonces, ahora ya tenemos otro registrado.
Al final, registrar es bastante fácil porque es pasarle un objeto y tal.
Entonces, a la segunda parte haremos lo del registro.
Y seguramente lo haremos con Formic.
Para ver Formic, porque me lo habéis pedido muchas veces y creo que es bastante interesante que veamos,
aunque el login lo dejemos así, pues a lo mejor el registro lo hagamos con Formic
y vemos las diferencias, las ventajas que tiene uno u otro.
Y eso siempre, pues, para comparar está bien.
Entonces haremos el registro, haremos lo del delete también para que podamos borrarlo, ¿no?
Que una vez que le demos aquí, pues se borre porque ahora no se está borrando.
Tampoco se están añadiendo, ¿eh?
Aunque esté haciendo la llamada, es lo suficientemente inteligente para que haga este post.
Si miramos aquí, si yo empiezo a darle aquí todo el rato, no se añade, ¿eh?
Esto me lo he currado, esto me lo he currado en Dino.
Me ha parecido súper interesante lo de Dino, así que ahí tienes el código para trastearlo.
Voy a ver qué me contáis mientras.
Muchas gracias.
Ah, no, eso no me lo está diciendo a mí.
Mega 2413.
Hola, yo estoy inscrito en un curso que tienes en Udemy y suscrito a tu canal.
Sos excelente.
Y sos maravilloso.
Muchísimas gracias, Mega.
Me alegro que te gustase el curso de Udemy.
Está totalmente gratis.
Es de React, pero es verdad que no está tan actualizado.
Y yo lo que os recomiendo es que, pues nada, disfrutéis del curso de Udemy porque está hecho con clases y te explica los ciclos de vida de React,
que es algo que ya no se lleva tanto, pero hay muchas empresas que todavía tienen código que utiliza eso.
Entonces puede ser interesante.
Entonces podéis ver el vídeo y luego pasáis por el canal de YouTube, hombre, y aquí pues estamos dándolo todo, con lo último.
¿Vale?
Alguien me dice que me dejó una pregunta que no tiene nada que ver con esto, que es cómo manejo el contenido de tu web.
¿Usas un CMS creado por ti, una librería o usas un servicio externo que vinculas?
Pues Martín, utilizo Hugo.
De hecho, te puedo comentar que mi web es de código abierto porque a mí me encanta hacer cosas de código abierto y, por lo tanto,
que, por cierto, si me queréis seguir, aquí estoy, ¿eh?
Mi Dudev, este soy yo.
De hecho, mira, aquí gente me ha estado siguiendo.
Hola, Ana Paula Santillán, hola.
Vale, este es el repositorio, una vez más, que me lo habéis preguntado un montón de gente.
React Live Coding, ¿vale?
Aquí lo tenéis.
Y podéis participar, podéis enviar PRs y haced lo mejor, ¿eh?
Y participáis y lo dejáis niquelado, ¿vale?
Entonces, mi web es de código abierto.
Y también podéis participar para enviar artículos, para mejorar typos y tal.
Por lo tanto, podéis ver cómo está hecha.
Ya te digo que está hecho con una cosa que se llama Hugo CMS.
Y lo que me gusta mucho es que es muy rápida, muy limpia y tiene cero boilerplate.
O sea, puedes hacer que no cargue nada de JavaScript.
Y a mí es lo que me gusta y mi web, pues, va muy rápido, o yo considero que va muy rápido, justo por eso, ¿no?
Porque no tiene absolutamente nada.
Y, bueno, me gusta que, total, es un blog, es para leer, pues eso.
Bueno, pues, lo podéis ver, podéis trasearlo, le podéis dar una estrellita también, si queréis.
Y tal.
Así que, no sé si te ha gustado, pero ahí lo tienes, ¿vale?
Alexandro Munera dice que ya vio al Messi de fútbol.
Ahora va a ver al Messi.
O sea, ya vio al Messi de programación, ahora va a ver el Messi de fútbol.
Muchas gracias.
Muchas gracias a ti, Alejandro.
Menudo crack.
Alexandro, menudo comentario.
Ojalá fuese la meta, ¿eh?
Francisco Ferreira pregunta, ¿con qué me recomendarías empezar a estudiar programación?
Pues yo te recomendaría Code Academy.
Code Academy.
La verdad es que si tuviese tiempo, si tuviese tiempo, me gustaría hacer vídeos de cómo aprender a programar.
A partir de cero, porque me parece muy interesante y a mí, no sé, el cómo me hubiera gustado, me hubieran explicado a mí, ¿vale?
Pero en Code Academy tienes algunos cursos para empezar que está bastante bien.
Por ejemplo, puedes empezar con Code Foundations o directamente puedes ir HTML, CSS.
Para empezar, creo que está muy bien.
Lo malo, que tiene cosas que son pro, pero las cosas que son gratuitas están muy bien para empezar.
Así que yo le daría un tento, ¿eh?
Por ahí.
Y me dicen, ¿tienes RSS?
RSS, por supuesto, tengo RSS en mi blog.
Te lo crea Hugo.
Lo tengo aquí.
Mira.
Ay, no sé si se ve, pero aquí está mi RSS.
Tengo RSS, ¿vale?
Hice el curso de Udemy, pero después con estos lives me pude actualizar muy bien, dice Sebastián Almada.
Bueno, esa era la idea.
Que además en el curso de Udemy me sabe mal que muchísima gente, pues estaba,
no voy a decir cabreada, pero querían que actualizase el curso.
Pero para seros totalmente honestos, Udemy es muchísimo trabajo y al menos a mí, a no ser que tengas muchísimos estudiantes que,
yo tengo 20.000 o 25.000, una cosa así, pero muchos han sido ya gratuitos.
Pero vaya, es complicado, ¿eh?
Porque no compensa casi Udemy.
Yo lo ponía 10 euros el curso y había algunos que me daban un euro y medio, a lo mejor una venta.
Entonces, para ganar un euro y medio, para ganarme 100, 200 euros, digo, pues lo hago así abierto.
Y bueno, y cuanta más gente tal, pues a lo mejor más me puedo dedicar y quién sabe si el día de mañana me puedo dedicar a vivir de esto.
Ojalá. Esto os necesito vuestra ayuda, que lo compartáis un montón y tal, pero bueno, que no me compensaba.
Y por eso, en lugar de dejar que Udemy siguiese lucrando con mi trabajo, por lo que he decidido,
es que, bueno, compartirlo con la comunidad y que la comunidad, si ve que es interesante, pues aporte o no.
Y ya está. Y disfrutarlo entre todos y ya está.
Madre, hola.
Guau.
Guau, guau.
Guau.
Uri Ustrel dice, no creo que puedas ser consciente de la muchísima gente a la que estás ayudando, Midu.
Este curso vale más que cualquier otra que haya visto.
Muchas gracias. Sobre todo, sobre todo, por la pasión que lo expone.
20 abrazos. Joder, Uri.
Sí. Muchas gracias. De corazón. Muchas gracias.
La verdad es que, joder, me emociono un montón con esto.
Y sobre todo, no sé, me emociono cuando mucha gente me escribe en LinkedIn, en Instagram, en Twitter,
y me dice, oye, que he encontrado trabajo gracias a ti, que he tenido una entrevista de React,
y me he visto todos tus vídeos, y gracias a tu curso he conseguido que además, que me lo digáis,
que me encanta que me lo digan, y guau, es que me levanta un montón del ánimo.
Y espero que sí, que estas cosas os ayuden, y que os gusten, y que, no sé, que valgan la pena.
Que realmente, la verdad es que hay un montón de esfuerzo detrás, pero que lo compensa con estas cosas,
con estos comentarios, y que realmente cambie la vida de la gente.
Eso me parece brutal. O sea, que me venga alguien y me diga, guau, es que esto que hiciste, no sé,
alguna vez me ha venido alguien y me ha saludado, y me ha dicho, oye, en una conferencia,
oye, que es que tengo que darte las gracias, porque he cambiado mi vida gracias a ti,
y yo, joder, madre, o sea, porque encontré el trabajo de mi vida, porque no sabía React,
y todo como lo has enseñado, lo he intentado mil veces, y no sé, eso, no sé, a mí me emociona, y me encanta.
Uri, chapo, muchas gracias, te lo agradezco, ¿eh?
Que también os digo, y os lo digo de corazón, me ayudáis un montón si compartís el contenido,
si le dais like, si comentáis, si comentáis en los vídeos, si le dais retweet al contenido que hago,
para que cuanto más gente le llegue, mejor, ¿vale?
Y eso me ayuda mil millones, así que, y para mí tampoco tiene, no tiene precio,
así que os lo agradezco un montón, ¿vale?
Oscar, son los mejores lives de React que he visto, y tú eres el mejor comentarista que he visto también mucho tiempo.
Muchas gracias.
Para nadie, dice, ¿eres antiangular?
Sí, no, no, no soy antiangular, la verdad es que no, no soy antiangular, no soy anti nada,
a mí me encanta el frontend, me encanta todo sobre frontend,
y bueno, ya podéis ver que en el canal tengo vídeos de Svelte,
que muy poca gente da un duro sobre ello, pero es que a mí me gusta,
entonces, a mí siempre de toda la vida me han gustado todas las tecnologías web.
Ahora, ¿qué pasa? Que la gente confunde el hecho de que cuando alguien me pregunta,
oye, ¿qué debería aprender? Pues yo digo, React, a ver, ¿qué debería aprender?
Una vez que ya sabes JavaScript, CSS y HTML, pues digo, React, ¿por qué?
Porque creo que en términos uno de presente y futuro a corto plazo,
y luego de trabajo, de cómo se está pagando, la demanda que hay,
me parece que React es lo acertado.
¿Que esto significa que sea antiangular? Para nada.
Hay una versión que no me gustó nada, que es Angular 2, y lo reconozco,
esa versión no me gustó, pero yo no sé antiangular,
de hecho tengo vídeos aprendiendo Angular, y al final cada uno tiene que estar cómodo
con lo que utiliza. Vue, me encanta, Angular, la última versión me parece espectacular,
me encanta la documentación. ¿Que me gusta más React? Sí, pero a lo mejor es solo
y simplemente porque lo utilizo más, ¿sabes? Entonces no, no soy antiangular,
no soy anti nada, la verdad, y en fronte menos, y más teniendo en cuenta el esfuerzo.
Yo he conocido a gente de Angular, al Mircos, lo conocí en persona,
es una persona fantástica y aprendí un montón, un montón.
Hay gente detrás de estas librerías que se desviven y tienen un trabajo sensacional detrás
y sé que hacen lo mejor. Entonces empatizo mucho y jamás sería anti una librería, jamás.
Jamás lo sería, lo seré y os recomendaría que no lo seáis,
porque ese código se basa en personas, no se basa en máquinas.
No lo hace una máquina que le das a un botón y, ah, toma Angular, no.
Si no, hay mucha gente detrás, una comunidad que está apoyándolo
y que vive de ello, y por supuesto. Así que no soy antiangular.
De nuevo, mi recomendación de aprender sería React,
pero eso no significa que sea anti nada, ¿eh? Anti nada.
Muchas gracias, Pablo Rodríguez, por esos 12 hours.
Muchísimas gracias. Muchas gracias, Miguel, sos muy crack.
Y tú también eres muy crack. Te lo agradezco muchísimo.
¿Qué se puede usar para no usar Bootstrap con React?
Esto me lo preguntan un montón, ¿vale?
Pero al final Bootstrap me parece una buena solución para empezar muy rápido, ¿vale?
Para hacer un prototipo y tal.
Tienes un montón de soluciones. Tienes Bulma, tienes Material UI,
y tienes el de, ¿cómo se llama? El undesigned.
Entonces, depende de cómo de grande sea tu proyecto y tu empresa.
Si es una empresa muy, muy, muy grande, mi opinión es que deberías crear
tu catálogo de componentes, tu design system, tu propio Bootstrap,
tu Material Design y tal, si es muy grande, ¿vale?
Si no, pues nada, ahí tienes un montón de alternativas.
Y creo, sinceramente, que hay algunas que pueden ser incluso mejores,
que Bootstrap como lo puede ser undesigned.
Me parece muy interesante, ¿vale? Mi opinión, ¿eh?
Vale, ¿qué más? Dice Chavigú, dice, yo te sigo, like y comento,
si me ayudas, o sea, esto es rollo un intercambio, ¿eh?
Si me ayudas a comparar dos arrays de objetos diferentes, un campo concreto,
y si es igual, copiar un campo de un objeto a otro.
¡Guau! Yo te ayudo, hombre. Pónmelo en el comentario del vídeo,
ponme en el comentario, ahora no lo voy a hacer, pero ponme en el comentario
y te ayudo, hombre. Pero eso, ¿eh? Like, comentar y me sigues, ¿eh?
Porque te voy a ayudar, así que ya sabes, ¿vale?
Pues, mira, dicen por aquí Chakra UI, Chakra UI creo que es el de Microsoft,
si no me equivoco, ¿puede ser? A ver, voy a buscarlo en el tab.
Chakra UI creo que es el de... ¿Puede ser o no lo es?
No, no, Chakra UI no es el de Microsoft. No, no, perdón, perdón, es cierto.
Es que Microsoft tiene uno con el que hace Office, ¿eh?
React Design System Microsoft.
Tiene el de, ¿cómo se llama? Fluent UI, exacto.
Que también, a ver, lo malo es que a veces se parece mucho a los productos de Microsoft.
De hecho, lo utiliza en sus proyectos.
Pero de verdad, es que hay tantas opciones.
Hay una vida, hay mucha vida más allá de Bootstrap.
Y bueno, para los que me conozcáis, ya sabéis, a mí me encanta la diversidad en el frontend.
Sé que soy muy de React, porque, bueno, lo domino y me gusta.
Pero a la hora de probar librerías, por ejemplo, tú utilizo Guter, porque me gusta probarlo.
Ahora he utilizado Dino, en lugar de... podría haberlo hecho con Node y a lo mejor hubiera tardado menos.
Pero, no sé, creo que a veces está bien darle un toque a las cosas probando cosas nuevas,
que eso te abre un poco la mente.
Pues muy buena la de Chakra UI, tampoco me acordaba, ¿vale?
Tailwind CSS, podéis crear vuestros propios componentes, súper fácil, con Tailwind CSS, ¿vale?
¿Qué más? Fabric UI, dicen por aquí.
Un Design, un Design, este no lo conocía.
Design System, un Design...
Ah, un Design, no.
Digo un Design System, no UnDesign, sino que creéis un Design System.
Por ejemplo, en mi empresa tenemos este, ¿vale?
Y esto lo hemos creado nosotros desde cero.
Y aquí tenemos un botón, ¿vale?
Y tenemos los diferentes verticales, y esto lo cambiamos con variables de SAS.
Y al final es que somos una empresa muy grande, que necesitamos tener cierto control sobre las cosas que hacemos
y asegurarnos que tienen el mejor rendimiento posible, la personalidad, la experiencia del usuario.
Entonces, tampoco os digo que reinventeis la rueda a la mínima, ¿vale?
Pero si eso es un proyecto lo suficientemente grande, una multinacional,
hombre, vale la pena ir más allá del material UI, ¿vale?
Y, por ejemplo, pues este mismo.
O sea, es que hay muchas empresas que hacen su Design System.
Este mismo lo podríais utilizar.
Todo esto son componentes de React.
Esto podéis decir, aquí tenéis la API con todas las pros que se utilizan.
Tiene incluso algún test.
No sé si funcionan los tests.
Bueno, no funcionan los tests.
Bueno, tienen Ritmi, cómo utilizarlo.
No sé, quiero decir que hay un montón de opciones, ¿vale?
Que no te cambien la versión y te rompan cosas.
Por cierto, muchas gracias.
Pablo Rodríguez, like.
Like, muchas gracias por compartirlo, Pablo.
La verdad es que que lo compartáis me ayuda un montón.
¿Qué más dicen por aquí?
Y que no te cambien la versión y que te rompan cositas.
Dice Juan Riquelme, pues con toda la razón.
Sí, señor.
Es que, claro, a la mínima tenés Material Design, tenés Bootstrap, por lo que sea.
Y, sobre todo, tener cuidado de ataros demasiado a algo, ¿sabes?
Si ahora todo lo tienes con Bootstrap y todos tus componentes ven que tiene Bootstrap, pues locurón.
Separad las cositas, ¿vale?
Pues nada, señoras y señores, muchísimas gracias a todos, una vez más, por estar aquí.
Sois de verdad, o sea, de corazón, sois la leche.
Sois una compañía maravillosa.
¿Qué puedo decir?
Que os suscribáis si no lo estáis.
Que, por favor, antes de iros, dejéis vuestro like, que ayudan un montón.
Y que si queréis ver cositas para la semana que viene, que ya os digo, seguramente haremos el registro,
Formic, Delete, de los favoritos, una página para ver todos nuestros favoritos, iremos viendo, ¿vale?
Pero eso es lo que vamos a hacer en la segunda parte.
Dejad en los comentarios si queréis ver otras cosas en el comentario de este vídeo.
En el comentario no dejes en el chat porque el chat desaparece, ¿vale?
El chat, como corto cosas, bueno, corto el principio, sobre todo, para que la gente que lo ve después, pues no vea todo el principio,
pues se pierde el chat, entonces dejadlo en los comentarios del vídeo, ¿vale?
Y ya sabéis que me podéis encontrar en Twitter como MiduDev, en Instagram como MiduDev,
pero cuidado que hay un MiduDev que no soy yo, es midu.dev, ese que sí que soy yo.
Me podéis encontrar en YouTube, por supuesto, que es donde estamos,
y en Facebook, si por lo que sea lo utilizáis.
Así que espero que os haya gustado muchísimo la clase, yo me lo he pasado genial, me lo he pasado muy bien,
ha sido súper divertido.
Un ejemplo con Gatsby para el futuro, me dice Adrián Nieves, sí.
¿Para crear un juego recomiendas usar Socket Ayo?
Bueno, pues depende del juego, pero puede ser que sí.
Andrés Lucas, me lo perdí, no pasa nada, ahora le das al play cuando termine.
Bueno, hasta el próximo live, os mando un abrazo enorme a todos y a todas,
gracias por estar aquí una semana más, nos vemos en el siguiente,
cuidaos mucho, por favor, y ya sabéis, seguid dándole al frontend.
Un abrazo, hasta luego.