logo

midulive


Transcribed podcasts: 746
Time transcribed: 15d 5h 20m 39s

This graph shows how many times the word ______ has been mentioned throughout the history of the program.

Muy buenas tardes, ¿qué tal? Bienvenido, bienvenida, espero que tengas muchísimas ganas de aprender hoy conmigo.
Vamos a ver cómo manejar un estado global con Redux desde cero, paso a paso, y utilizando Redux Toolkit.
Una cosa que intento es que sean bastante prácticos, que siempre estemos haciendo un proyecto práctico que nos enseñe alguna cosa en concreto.
Y hoy vamos a hacer algo parecido a un CRUD, ¿vale? Que es muy típico.
Si no sabes lo que es un CRUD, el CRUD es Create, Read, Update, Delete.
Porque obviamente la gran mayoría de aplicaciones ahí fuera y de productos no dejan de ser un CRUD glorificado, en el que tú creas datos, actualizas datos y tal.
Pero vas a ver que vamos a hacer cosas un poquito diferentes.
Desde el Inter, que va a ser un poquito diferente, los componentes que vamos a utilizar que son muy interesantes, un montón de cosas diferentes para darle una vuelta.
Y una de las cosas que va a ser diferente es utilizar Redux.
Ahora bien, si quieres ver todas las clases, todo el código que tenemos de este pedazo de curso de RIA que estamos haciendo desde cero, que sepas que tenemos un repositorio.
Tenemos un montón de clases, la de TypeScript, Lazy Loading, Use Context, un montón.
Y hemos hecho un montón de proyectos.
La Follow Card de Twitter, hemos tenido pruebas técnicas, hemos hecho ya dos pruebas técnicas, hemos creado un e-commerce, hemos hecho un RIA Router, hemos creado un Google Translate con ChatGPT.
Y hoy vamos a crear otra cosita más, ¿vale?
La vamos a hacer también hoy la clase con TypeScript, pero si no sabes TypeScript, no te preocupes.
¿Por qué?
Porque lo que vamos a ver hoy es bastante fácil.
No es que sea algo muy pesado de TypeScript, son unas pocas líneas de código y vas a ver que además tienen sentido y son muy fáciles de entender.
Así que no te preocupes.
¿Qué vamos a utilizar?
A ver, amigos, hoy vamos a utilizar Redux Toolkit.
Seguramente ya conoces Redux.
Redux es una forma de gestionar el estado no solo de React, sino de cualquier cosa.
Redux está pensado para que lo puedas utilizar con React o sin React, pero ha sido durante mucho tiempo la forma más famosa de gestionar estados en React.
Hoy vamos a utilizar Redux Toolkit, que es como la forma oficial, opinionada, como aconsejada de utilizar Redux de la mejor manera posible.
A lo mejor si ya sabes un poco de Redux, pues te va a venir bien para actualizarte.
Si no conoces Redux, no te preocupes, que te voy a estar explicando paso a paso cómo se utiliza, buenas prácticas a la hora de utilizarlo y todo esto.
Y lo vamos a ir viendo aquí con el Getting Started.
¿Qué quiere decir con baterías incluidas?
Pues quiere decir que viene con pilas.
Baterías, ¿qué quiere decir?
Baterías quiere decir que viene con utilidades, con cosas que lo hacen todavía más potente.
¿Sabes?
Es como decir que viene con cosas extra que te va a facilitar la vida.
Esa sería un poco la expresión.
Se refiere a esto que creo que pone aquí.
Bateries included.
No es que venga con peli, o sea, con pilas, sino que viene con ciertas cosas que hacen que todavía sea más potente, con utilidades y todo esto.
Mira, os comento un poco lo que vamos a ver hoy.
Vamos a ver.
Crear el proyecto desde cero.
Vamos a utilizar un linter que no es slint y lo vamos a configurar desde cero.
Vamos a utilizar unos componentes de React que seguro que no conoces y están muy chulos.
Vamos a instalar Redux, obviamente.
Vamos a crear los slides.
Te voy a explicar qué es un slides, qué es un lastor.
Vamos a leer del lastor, actualizar el lastor.
Vamos a mostrar los datos.
Va a quedar bonito el proyecto, ya lo verás.
O sea, porque vamos a utilizar unos componentes que están bastante bonitos.
Vamos a poder crear con usuarios, borrar usuarios, editar usuarios.
Con MyDelWars vamos a hacer dos cositas.
Una, poder guardar en el local storage nuestro estado.
Y lo vamos a hacer desde cero.
No lo vamos a hacer con una biblioteca, porque quiero que entiendas cómo funcionan los MyDelWars.
Y también vamos a hacer que se pueda sincronizar con una base de datos nuestra información.
Porque muchas veces un error que veo, no un error, pero muchas veces un problema que suele pasar
es que la gente no sabe cómo sincronizar los datos con base de datos.
Hay una forma muy famosa que es utilizando Zangs, pero a mí no me gustan.
No me gustan y yo te voy a enseñar hoy una.
Y más adelante igual hacemos Zangs, no lo descarto.
Pero hoy me gustaría que entendieses cómo lo podrías hacer tú de una forma totalmente separada de Redux.
Poder sincronizar los datos con una base de datos y que además quede súper bien.
Y que lo puedas hacer súper mantenible.
Entonces te lo quiero enseñar con una posible forma que además se utiliza mucho en muchas aplicaciones de la vida real,
como puede ser Facebook, Twitter y todo esto.
Pues sí, lo podríamos hacer este mismo proyecto con Zustan para que veáis las diferencias.
Lo cual me parece bastante bien.
Vamos a empezar con nuestro proyectito.
Voy a quitar esto.
Me voy a ir al barra dep.
Y empezamos aquí nuestro proyecto.
Vamos a utilizar bit.
Así que ponemos bit, arroba latest.
He dicho que vamos a utilizar TypeScript también, lo cual está interesante pero muy sencillo.
O sea, no te tienes que preocupar, no tengas miedo.
Porque vas a ver que es bastante fácil.
Le voy a llamar, ¿cómo le podríamos llamar?
A ver, es un CRUD.
O sea, que CRUD Redux, React Redux.
React Redux.
Vamos a utilizar React, vamos a utilizar TypeScript con SWC y CRUD React Redux.
Aquí ya tenemos nuestro proyectito.
Vamos a poner pnpm install o npm install o jang, el que tú quieras utilizar.
Cualquiera de los tres está perfecto.
Todo funciona maravillosamente.
Os he dicho que vamos a hacer un proyecto un poco diferente para que probéis cosas nuevas.
Porque está bien probar cosas nuevas y que no siempre hagamos lo mismo.
Entonces hoy no vamos a utilizar slint.
Vamos a utilizar ROM, ROM Tools.
Si no sabes qué es ROM, pues está bien, no te preocupes.
Es algo muy parecido a slint y Prettier.
Es muy rápido.
Y te voy a enseñar cómo lo podrías configurar en un proyecto para empezar.
El ROM es del creador de Babel.
Y ahora mismo ya funciona con JavaScript, con TypeScript, con JSON.
Y tienes tanto el formateador como el linter.
Están trabajando también el compilador, el valer y tal.
Pero vamos a utilizar el formateador y el linter.
Estas son las dos cosas.
Y entonces, está interesante porque no utilizamos slint, que ya está muy visto.
Así que utilizamos pnpm add ROM menos D mayúscula.
¿Por qué?
Porque es una dependencia de desarrollo.
¿Vale?
Menos D mayúscula es porque queremos guardarla como dependencia de desarrollo.
Y ahora ejecutamos pnpm rom init.
Vamos a ver si esto funciona.
Fíjate que me dice que ha creado el archivo rom.json.
Próximos pasos.
La extensión del editor, que ahora te enseñaré.
Ejecutar el comando.
Lo podríamos hacer.
Podríamos hacer pnpm rom cchecks.
¿Re?
Sí, me parece.
Para chequear.
¿Ves?
Tenemos aquí unos cuantos errores.
Porque no le he pasado argumentos y lo que sea.
Pero bueno, esto no es importante.
Y leer la documentación.
Bla, bla, bla.
Esto no queremos leer documentación.
Para eso es tuyo.
Para que no leamos documentación.
Pero fíjate que ya me ha creado aquí un archivo de rom.
Con organizar los impors.
Está enable force.
Yo le voy a poner a true.
Y ya verás por qué.
Porque está bastante divertido.
El inter activado true.
Con las reglas recomendadas a true.
Y también podéis activar el formateador.
Que sería como el pre-tier.
Le ponemos enable true.
Y aquí no hace falta poner las rules.
¿Vale?
Esto lo quitamos por aquí.
Esto por acá.
Y ya está.
Con esto tendríamos las ROM tools.
Las herramientas ROM.
Como el linter.
Ya la tendríamos configurada más o menos.
¿Qué pasa?
¿Qué pasa?
Que ahora muchos.
Seguro que os pasa a muchos de ustedes.
Que lo que os debe pasar es que tenéis el linter en algún sitio.
Tenéis slint.
No se preocupen.
Yo les voy a explicar cómo lo haría yo.
En mi caso.
En este momento en el que yo voy a utilizar las ROM tools.
Y ya tengo slint.
Lo primero que deberíais hacer es.
En las extensiones.
Vamos a buscar las ROM.
Tenéis que instalar esta.
Esta oficial de ROM.
¿Vale?
Yo ya la tengo instalada.
Esta la tenéis que tener activada.
Luego.
Buscáis la de slint.
Y en slint.
Ves que la está activada.
Yo.
Como no la voy a utilizar en este workspace.
Lo que podéis hacer es disable workspace.
Desactivamos esta extensión.
Solo para este entorno de trabajo.
Y lo mismo hacemos con Prettier.
Así que vamos a Prettier.
Y hacemos disable workspace.
Le damos a reload required.
Ahora.
Pues parece que todo está exactamente igual.
Pero vamos a ir a uno de los ficheros.
Como por ejemplo este.
Vale.
Fíjate.
Que ya me pone cositas en rojo.
Por ejemplo aquí.
Me pone target blank.
Y este error.
Me lo está dando ROM.
No es de slint.
Ni es de Prettier.
Ya es de las ROM tools.
O sea.
Ya me está funcionando bien el link.
Que algo es algo.
Y vamos a ver.
El formateador no me funciona.
Porque fíjate que he guardado.
He puesto aquí un montón de semicolons.
Y no me está formateando el código.
¿Qué es lo que pasa aquí?
Pues que muchas veces tenéis una configuración que entra en conflicto con vuestras.
Con lo que queremos hacer.
Mi recomendación en estos casos es.
Aquí podéis hacer una cosa.
Podéis crear un archivo.
Que sea .biscode.
Y aquí settings.json.
Y podéis tener una configuración para vuestro proyecto.
Que solo funcione en este proyecto.
Y así no entra en conflicto con vuestra configuración que tengáis.
Porque si miráis mi configuración.
Veréis que yo tengo ahí.
Pues en el JSON tengo slint.
No sé qué.
Slint no sé cuánto.
Arreglar.
Cuando hago un save.
Arreglar todo de slint.
Esto para que funcione bien en vuestro proyecto.
Si queréis utilizar las ROM tools.
Pues podéis decir aquí.
Mira.
Primero voy a decirle que haga un format on save.
Que cuando guardemos que me formatee el código.
Por ahora esto no funciona.
Normal.
Porque tenemos que decir cuál es el formateador que queremos utilizar.
Bueno.
Pues le vamos a decir.
Primero.
¿Cuáles son las acciones al guardar?
Lo primero que queremos hacer es que.
Todo lo que es el código.
Lo arregle de las ROM.
ROM tools.
¿Vale?
Veis que pone true.
Vale.
Esto me va a hacer un fix de los errores que tengamos.
De hecho ahora si intento guardar.
¿Vale?
¿Veis que me ha solucionado esto?
Esto es porque con la configuración le he dicho.
Quiero que me arregles todo.
Con las ROMs.
True.
Cada vez que guardo.
Ahora.
Cuando guarde.
Me va a arreglar los errores del inter que tengo.
Los problemas del inter que pueda arreglar.
Me los arreglará.
También vamos a poner el de otra opción que tiene.
Que es el de organizar los impos.
Y lo vamos a poner a true.
¿Por qué?
Porque ahora cuando guardemos.
¿Veis que me ha hecho aquí?
Me ha cambiado esto.
Me los ha ordenado.
Esto está bastante interesante.
Porque el ROM también lo que puede hacer.
También lo puedes hacer en el slint.
Te organiza los impos de forma que te hagan sentido.
Todavía no funciona el formateador.
Pero los impos ya los ordena.
¿Vale?
¿Qué es lo último que tenemos que hacer?
Y ya con esto terminamos.
Lo que tendríamos que hacerle.
Es indicarle en cada lenguaje de programación.
Bueno.
En este lenguaje de programación.
O sabor.
Le tendríamos que decir.
¿Cuál es el formateador que queremos utilizar?
Le podemos decir.
Que el editor.
El default formatter.
Default formatter.
No es ROM AJS.
Es ROM.ROM.
¿Vale?
Y esto lo deberíamos repetir para.
Por ejemplo.
Pues para JavaScript React.
Para TypeScript.
Para TypeScript React.
Y con esto.
Ahora sí.
Le estamos diciendo.
Que para todos estos lenguajes de programación.
O para este tipo de ficheros.
Tiene que utilizar.
Para formatearlo.
ROM.
Así que si volvemos aquí.
Y guardamos.
Ahora.
Ahora podéis ver que.
Si le pongo.
Le quito el semicolon.
Me lo añade.
O sea.
Ahora sí que está formateando el código.
¿Ves?
Si hago esto.
¿Veis que me lo he arreglado?
Ya hemos configurado el linter para nuestro proyecto.
Y hemos utilizado un linter totalmente distinto.
Que no sé si lo habías visto.
Es bastante interesante.
¿Por qué?
Pues porque muchas veces siempre se utiliza Slint.
Y está bien.
O sea.
Slint está muy interesante.
No pasa ningún problema.
Si queréis seguir utilizando Slint.
Pues tremendo.
Pero quería que empecéis a aprender algún linter.
Que es una alternativa.
Que cada vez lo vais a escuchar más.
De hecho.
Ya veréis.
Dentro de 6.
12 meses.
Un año y medio.
Vais a tener ROM hasta en la sopa.
Y diréis.
Yo esto ya lo vi en los directos de Midu.
Ya verás.
Para configurarlo.
Aquí podéis configurar tanto las reglas.
Como aquí lo podríais configurar también como el indentado.
Todo.
Todo lo podéis configurar.
Le faltan cositas.
No es todavía tan potente como Slint y Prettier.
Pero ahora ya diría que se puede empezar a utilizar.
Creo que sigue siendo mejor Slint y Prettier.
Pero es verdad que ROM es mucho más rápido.
Que si el proyecto es muy grande.
Seguro, seguro que vais a notar una diferencia.
Es muchísimo más rápido ROM porque está hecho con Rast.
Vamos con lo siguiente.
Que es que vamos a utilizar en nuestro proyecto esta colección de componentes.
Es muy fácil de utilizar.
Se ve muy bonito.
Así que no te preocupes porque vas a ver que nos va a ayudar un montón.
Tremor es una colección de componentes.
Igual que tenemos algunos proyectos que utilizan, pues yo que sé, Tailwind.
Que vamos a tener que instalarlo.
Tailwind, Bootstrap, Chakra UI.
Tremor, que aunque está en beta, sobre todo está muy pensado para formularios, para gráficas, para dashboards.
Y está muy bonito.
Mira, para que te hagas una idea.
Se ve más o menos así.
Y es el que vamos a utilizar en este proyecto.
Porque vamos a querer mostrar como tablas.
Y no gustaría, pues, no tener que estilarlas porque no nos da tiempo.
Así que vamos a instalar Tremor.
Es súper fácil, de nuevo.
PNPM at.
Y le decimos aquí Tremor barra React guión E.
Mayúscula E de versión exacta.
Porque tienes una versión en producción.
Y vamos a decir que sea exacta.
Mira, si queréis ver la tabla que vamos a utilizar, pues esta sería la tabla.
Esta, bueno, podemos utilizar esta, por ejemplo.
¿Vale?
Y aquí pondremos los enlaces de los botones de editar y todo esto.
Aparte de utilizar Tremor, vamos a utilizar los iconos de Hero Icons.
No sé si los conoces, pero los...
Bueno, no vamos a utilizar muchos.
Pero los copiaremos directamente.
A mí es un proyecto que me gusta mucho.
Tiene muchísimos iconos.
Casi 300 iconos que tienes disponibles.
Y son de los creadores de Tailwind.
Así que si no los conocías, también te los puedes poner en tus favoritos.
Que te va a encantar.
Y lo otro que vamos a utilizar, más que nada porque lo necesita Tremor para funcionar.
Fíjate, en Tremor el otro día lo pusieron.
Que se han pasado totalmente a Tailwind CSS.
No te preocupes si no sabes Tailwind, porque no vamos a utilizar Tailwind.
Pero tengo que instalarlo porque Tremor lo necesita.
¿Vale?
Tremor utiliza Tailwind y por lo tanto lo tenemos que instalar.
Pero no lo vamos a utilizar en el proyecto o lo vamos a usar casi cero.
¿Vale?
Muy poquito.
Para instalar Tailwind, ¿qué tienes que hacer?
Tienes que añadir de dependencias de desarrollo, Tailwind CSS, Post CSS y Autoprefixer.
¿Vale?
Los instalamos.
Y cuando termine, ejecutamos Tailwind init-p.
Y esto lo que nos va a hacer es crearnos los archivos de configuración que necesitamos para que funcione Tailwind en nuestro proyecto.
Aquí en nuestro proyecto nos vamos aquí, Tailwind config.js, ¿ok?
Y en el contenido tenemos que decirle los ficheros que tiene que mirar.
Uno va a ser, obviamente, el .barra index.html.
Otro donde tenemos todos nuestros componentes, ¿no?
En source, aquí tenemos páginas, componentes, pues aquí, excepto view, que no lo tiene que mirar.
Vamos a mirar todos los ficheros que tengan estas extensiones.
Y necesitamos añadir el path de Tremor, Tremor No Modules, ¿vale?
Porque también, como utiliza Tremor Tailwind, tenemos que observar su carpeta.
La carpeta esta no es correcta, la que ha puesto, pero bueno, al menos me ha ayudado.
Es No Modules.
Esto te lo ponen en las instalaciones aquí, ¿eh?
Si veis que el documentation, veréis que te lo indica, ¿eh?
En vid, yo más o menos me lo sé de memoria y no lo he hecho.
Pero, ¿veis?
Aquí te dice, este es el path que tienes que utilizar.
Vale, pues este es el path que tenemos que utilizar.
Nos faltarían los detalles estos de importar en el index.css, index.css.
Quitamos todo esto que teníamos, importamos lo de Tailwind y ahora sí, pues vamos a hacer un pnpm rundev
para ver cómo va quedando nuestro proyectito y eliminamos unas cuantas cositas, ¿vale?
Vale.
A ver.
Vale.
Ya veis que tenemos estilos, está un poco raro.
Ahora eliminamos esto y empezamos con nuestro proyecto.
Así que nos vamos aquí y en el index, en el index, en el main, no, en el app.tsx, ¿vale?
Quitamos este estado y vamos a quitar todo esto y vamos a poner aquí nuestro proyecto con Redux.
Fíjate en esto, una cosa que me gusta mucho de las ROM Tools, que cuando hace el import, o sea, cuando ve que un import no lo utilizas y guardas, mira lo que hace.
Los elimina automáticamente.
Eso está muy chulo.
La verdad es que es un poco peligroso porque hay imports que aunque no utilices lo que importa, a lo mejor sí que lo utilizas, pero bueno, es un poco raro, no es buena práctica.
Pero en este caso, fíjate que cuando le doy a guardar, te los elimina.
Está súper chulo porque te hace una limpieza genial, automática, no te tienes que preocupar.
Bueno, tiene cosas muy interesantes que por eso quería probarlo con todos ustedes para que lo puedan ver y lo puedan disfrutar.
Vale, pues ya tenemos nuestro proyecto con Redux aquí desde cero.
Muy bien.
Vamos a empezar pues ya con lo que queremos mostrar para que podamos ver rápidamente algo.
Dentro de Tremor habíamos visto que aquí en Blocks ya vienen como unos bloques que vienen preparados.
Así que aquí en la tabla, fíjate que en la tabla tenemos este me gusta.
Y si no, no sé si utilizar, mira, igual este que se ve un poquito más sencillo y no parece que sea muy complicado.
Nos vamos a copiar todo este código, ¿vale?
Este código lo que hace es renderizar esta tabla.
Nosotros lo que vamos a hacer es renderizar en la tabla, pues vamos a renderizar también aquí el nombre del usuario y un poquito, alguna información suya.
Pero bueno, ahora lo editaremos porque es donde vamos a querer mostrar nuestros usuarios.
Ponemos components y le podemos llamar, a ver cómo le llamamos a esto, listofusers.tsx.
Lo copiamos aquí a saco y ahora lo editamos un poquito.
Te voy a enseñar un poquito el código, te lo explico.
Todo este import es para importar los componentes de Tremor React que ya están preparados para que puedan mostrar cars, tablas, badges, lo que sea.
Aquí tendríamos la información de los usuarios que queremos mostrar.
Aquí nos sobra un poquito de información.
Voy a empezar poniendo, le voy a llamar users y en lugar de poner name, lead, sales, quota, variance, que parece que es demasiada información, vamos a poner, vamos a tener por un lado el name y por otro lado, a ver qué podríamos tener aparte del name, podríamos tener el email.
Vamos a empezar poniendo sencillito, el email, el github, ¿vale?
Sí, el github, vamos a poner el github y la id, ¿vale?
La id, ¿vale?
Y entonces aquí vamos a inventarnos esto, vamos a poner id y vamos a poner uno.
Lo vamos a poner aquí, a ver, voy a mirar usuarios del chat.
Yazmanito, ¿vale?
Yazmanito, vamos a poner Yazmanito, Yazmanito.
Esto lo podemos quitar, vamos a poner el email, el email, vamos a poner yazmanito.gmail.com y en el github y ahora pondremos unos cuantos más, ¿vale?
Vamos a poner el github, Yazmanito también, Yazmanito.
Bueno, el nombre vamos a poner Yazman Rodríguez.
No sé cómo se llama este chico, lo siento, ¿eh?
Pero para que salga el nombre, ¿ok?
Para que salga el nombre.
Vale, quitamos esto y ahora esto en realidad, github pilot, y esto es una de las cosas que más me gusta de github pilot, tío.
Es que tú le dices uno y entonces ya te va diciendo como mock data, ¿ves?
Ya te va metiendo ahí mock data.
Está súper chulo.
Pues te va metiendo ahí mock data que queda súper bien porque en un momento te creas aquí unos cuantos usuarios que quieras o no.
Mira, vamos a poner otro, Hakon Dalberg.
Hakon, Hakon Dalberg.
Email, vamos a poner Hakon, Hakon.
Luego utilizaremos estos usuarios también para Hakon y ya está.
Venga, al menos ya tenemos tres usuarios que es lo que nos interesaba.
Ahora, aquí lo que vamos a querer exportar es el list of users y no el example.
En la tabla tendríamos aquí el nombre.
Vamos a poner nombre.
Vamos a quitar todos los class names estos.
Vamos a hacer que todos tengan lo mismo.
Quitamos este class name.
Vamos a tener el nombre.
Vamos a tener, bueno, pondría idea.
Luego el nombre.
Luego vamos a quitar todo esto.
Vamos a mostrar el email.
Y ya está porque el GitHub no lo vamos a mostrar.
Y aquí vamos a poner las acciones.
Acciones, ¿vale?
En users, de cada uno tendríamos la idea, el name, luego tendríamos el email y ya está.
¿Vale?
Y aquí lo que vamos a tener en este caso serían las acciones.
Vamos a poner aquí acciones.
Y ya está.
Fíjate que en un momento ya hemos hecho la tabla.
Gracias, obviamente, a Tabler, a Tremor, porque lo tiene todo súper preparado.
Vamos a guardar los cambios y vamos a intentar renderizar esta aplicación aquí.
Vamos a importar el list of users.
Y en lugar de poner esto, ya vamos a poner...
Bueno, no hace falta ni que pongamos nada por aquí.
El list of users.
No sé por qué no funciona autocomplir.
No sé si es una cosa de...
Vale, vamos a nuestro proyecto.
Pronto, ya tenemos algo.
Ya empieza a pintar algo.
Para que esto quede todavía mejor, una cosa que vamos a hacer al lado del nombre, ¿vale?
Al lado del nombre vamos a hacer un pequeño detalle que creo que le dará un poquito de vida.
Y es que en el image vamos a utilizar un avatar punto...
A ver si me acuerdo cómo era el proyecto este.
Un avatar de nuestro amigo unavatar.ion.github.
Y aquí ponemos el nombre del usuario que está en GitHub.
Y ya verás, así podemos conseguir su avatar súper fácil.
Súper fácil.
A ver...
Vale, ¿veis?
Mira, en el caso de este hombre lo he adivinado.
Vamos a ponerle aquí un estilo que sea 32 píxeles...
32 píxeles...
Vale, ya os he dicho que voy a intentar no utilizar Tailwind porque no lo hemos explicado.
Pero bueno, que si hace falta pues algo utilizaremos, ¿vale?
Pero al menos para no tener que explicar también Tailwind, por si no lo sabéis, voy a intentar hacerlo un poquito a manija, ¿vale?
Para que nadie se me pierda.
Así que lo que estamos haciendo ahora mismo sería centrar y poner una imagen al lado del nombre.
¿Ves?
Estamos poniendo la imagen al lado del nombre.
Ponemos el borde radius de la imagen también.
Borde radius.
Estos serían estilos en línea de CSS normales y corrientes.
Y le ponemos un margin-right de 8 píxeles.
Y ya tenemos ahí un poquito de separación.
Que bueno, pues le da un toque.
Ya tenemos nuestra lista de usuarios al menos, ¿no?
Me arreglo con el tipo de proyecto que va a usar de Tremor para el todo list.
No es un todo list, es como una agenda que vamos a hacer.
Ahora, en acciones vamos a poner los dos botones.
En lugar de poner aquí acciones, vamos a poner el botón editar y el botón eliminar.
Como os he dicho que vamos a utilizar botones de giro icons, vamos a poner aquí un delete.
Vamos a buscar aquí el delete.
Este me gusta.
Fíjate que cuando estás en giro icons lo puedes, o te copias el SVG o el JSX.
Pues lo que tienes que hacer es JSX, ¿vale?
Vamos a poner aquí JSX, te lo copias y aquí donde le hemos puesto eliminar copiamos el código.
Provide explicit type.
Vale, aquí vamos a poner type y vamos a poner button.
¿Vale?
Le vamos a decir que son de tipo botón.
Curioso ese linter.
Y para editar vamos a buscar un edit y me gusta este.
Este está bien.
En lugar de editar, ponemos aquí el edit y vamos a ver cómo va quedando esto.
Vale, pues ya tenemos aquí nuestros dos botoncitos, el de editar y el de borrar.
Esto es lo visual, pero ahora lo que queremos es que esta información venga, ahora sí, de Redux.
Venga de Redux.
Obviamente lo que tenemos aquí en el list of users es que tenemos aquí los usuarios a fuego.
Pero, ¿qué pasa si al final lo que queremos es tener los usuarios en más de un sitio, que podamos ver cuántos usuarios tenemos, que se sincronice en más de un sitio la interfaz y sepa los estados que necesitamos, ¿no?
Por ejemplo, una cosa que podría ser es que aquí podríamos poner un título.
Lo voy a poner un momento.
Aquí.
Title.
Podríamos poner title.
Creo que lo podemos importar.
El title viene de Tremor, ¿vale?
Tremor tiene aquí un título.
Lo podemos traer.
Y también tiene un badge, que también me lo voy a traer.
Son dos componentes que ofrece Tremor React.
Y vamos a poner aquí, por ejemplo, usuarios.
Y vamos a poner usuarios.
Vamos a poner el badge.
Y vamos a poner el número de usuarios.
Users.length.
Sería algo así.
Queda un poco raro porque está muy juntito.
Pero, bueno, esto lo arreglamos un momento.
Le ponemos un margin-left aquí de 8 píxels y ya se separa.
¿Vale?
O sea, que aquí tendríamos el número de usuarios.
Y la idea es que cada vez que cambiamos el número de usuarios, también aquí aparezca el número de usuarios correctamente.
Vale.
Vamos a empezar con Redux.
¿Qué es Redux?
¿Cómo funciona Redux?
Y todo esto, no te preocupes porque además te voy a enseñar un diagrama que lo vas a entender perfectamente.
Pero primero vamos a instalar las dependencias antes de ponerme ahí a explicarte al detalle.
Para las dependencias de Redux, vamos a utilizar Redux Toolkit, que es la forma recomendada a día de hoy de utilizarlo.
¿Por qué?
Porque Redux, de forma histórica, todo el mundo decía estas cosas, ¿no?
Configurar Redux es muy complicado.
Hay que añadir muchos paquetes para hacer que Redux sea algo útil.
Y Redux requiere mucho boilerplate.
Han sido los tres problemas históricos que todo el mundo se ha quejado de Redux.
Y la verdad es que yo creo que con razón.
Yo creo que con razón porque es verdad que siempre era un problema.
No tenías que instalar muchas dependencias y tal.
Bueno, esta vez lo han cambiado totalmente.
Lo han cambiado y lo único que tienes que hacer es instalar Redux Toolkit.
Esta de aquí.
Y si utilizas React, que sí que lo necesitamos, tendrías que instalar también React Redux.
Así que vamos a traernos este Redux Toolkit y hacemos pnpm install, Redux Toolkit y React Redux.
Voy a hacer esto un poco más grande para que lo veáis bien.
Que si no, luego me decís que no lo veis.
Que no lo veis y que os dejo ciegos.
¿Vale?
Lo vamos a poner menos E mayúscula.
Esto significa que queremos la versión exacta del Package JSON.
Si no pusiera el menos E, por si te lo estás preguntando, ¿por qué pone el menos E?
Si no pusiera el menos E en el Package JSON, me aparecerían las versiones así.
Con el Caret.
Y ya sabéis, yo al menos lo he explicado muchas veces, que el Caret yo no lo recomiendo.
Porque lo que hace es instalar versiones que a lo mejor no estáis controlando.
Así que lo mejor que podéis hacer es quitarle el Caret y vosotros ir controlando cuando queréis actualizar una nueva versión.
Podéis utilizar una extensión como esta de Version Lens que tenemos aquí.
Que te detecta qué versión está utilizando.
Y fíjate, si tiene una versión nueva, es súper chula la extensión esta.
Os la recomiendo un montón.
Esta extensión está muy chula porque imagínate que dices, ostras, quiero actualizar Bit.
Pues solo dándole clic aquí, te la actualiza la versión y ya está.
¿Qué es lo primero, lo más importante a la hora de trabajar con Redux que necesitamos?
Y es un concepto que vas a necesitar en un montón de gestores de estado global.
Vamos a crear una carpeta que vamos a llamar Stores.
Lo voy a llamar Store, como en singular, porque aquí es donde vamos a tener todo.
En la Store, digamos que es donde se guardan las cosas.
Vamos a tener aquí un index, .ts.
Estamos utilizando TypeScript, aunque todavía no hemos visto mucho TypeScript.
Y vamos a importar el Configure Store de Redux Toolkit.
¿Vale?
Configure Store.
La Store, digamos que es donde lo guardamos todo.
Donde lo estamos guardando todo y por lo tanto es donde vamos a tener nuestro estado, las acciones, los Reduxers y todo esto.
No te preocupes si no sabes qué son las acciones Reduxer y tal, porque mientras lo vayamos creando te lo voy a explicar.
Pero por ahora lo más importante y lo central es que entiendas que necesitamos tener un sitio donde vamos a guardar nuestro estado,
nuestra parte del estado y donde va a ocurrir toda la magia, donde se sabe cómo tiene que gestionar este estado.
Así que confirmamos la Store y le decimos que Reducer, por ahora, lo dejamos como un objeto vacío, como que no tiene nada y ya está.
O sea, esto es todo lo que tenemos.
¿Vale?
Hacemos un Export, Const, Store, Configure Store.
Estamos configurando la Store y ya está.
Simplemente estamos haciendo esto.
¿Por qué?
Porque antes de nada, una de las cosas más importantes que tenemos que hacer para que podamos utilizar Redux
es que en nuestra aplicación tenemos que envolverla con un provider.
Tenemos que decirle de alguna forma que para poder utilizar Redux y poder leer esa Store desde cualquier componente,
le vamos a decir, vale, yo tengo esta Store.
Así que importamos la Store.
Yo tengo esta Store.
Y esta Store, ay, esta Store que tengo aquí, esta Store que tengo aquí,
quiero que utilizando este provider de React Redux, ¿vale?
Se la pases a toda mi aplicación.
Me la voy a quitar Strip Mode porque, total, no lo vamos a utilizar y así nos da menos problemas.
Utilizamos el provider y utilizamos la Store.
Y este provider es el que nos va a permitir que ahora, desde cualquier parte de nuestra aplicación,
podamos leer la Store y mandar acciones a la Store para que genere nuevos estados.
Esto es, esta es la magia que nos permite hacer esto de, desde cualquier sitio, poder leer la Store.
Así que ya tenemos esto.
Ya tenemos aquí la Store.
Vamos a, mira, ya me he eliminado los impuestos que no utilizo.
Perfecto.
Tenemos la Store, que es donde guardamos todas las cosas de nuestra aplicación, ¿no?
Una Store.
Piensa en la Store como si fuese una caja.
Una caja donde vamos a guardar las cosas.
Dentro de esa caja, claro, tú imagínate el estado de toda tu aplicación puede ser muy complicado.
En tu aplicación puedes tener productos, puedes tener usuarios, puedes tener posts, puedes tener búsquedas, puedes tener un montón de cosas.
Así que en esta caja vas a querer ser organizado.
Para poder organizarte, vas a dividir esta caja en diferentes secciones.
Y cada sección le vamos a llamar slice.
Como las pizzas, ¿sabes que en las pizzas tienes un slice?
Un slice es una porción de la pizza.
Para poder tener la pizza entera, al final lo que haces es separarlo en porciones.
Pues vamos a tener diferentes porciones donde una porción se va a referir a los usuarios, otra a posts, a lo que sea.
¿Cómo hacemos esto?
Pues lo que tenemos que hacer en este caso es crear un slice, una parte de estas.
Dentro de Store yo voy a poner aquí users y vamos a poner aquí slice.ts.
Y vamos a crear aquí nuestro primer trozo de la Store.
Utilizamos el create slice y lo importamos de Redux Toolkit.
¿Cómo creamos el slice?
Pues igual que hemos hecho antes, export const users slice.
Y en este slice le tenemos que decir que, ¿cómo llamamos a este trozo de la caja?
Pues le vamos a poner un nombre, le llamamos users.
Necesitamos tener un estado inicial, que todavía no sabemos cuál es, ahora lo hablaremos.
Y por otro lado necesitamos los Reduxers, que no te preocupes, pero ahora te explicaré cuando terminemos el slice de users,
te explicaré un poco qué son los Reduxers y cómo funcionan.
Pero los Slides necesitan un nombre, su estado inicial y los Reduxers.
Eso es lo que tiene este trocito.
El estado inicial, en este caso, lo más interesante que tienen los Slides,
es que puedes hacer que un Slice, su estado, no tiene por qué ser un objeto.
Para los usuarios lo que vamos a querer es tener simplemente un array.
Y podemos tener un estado global que sea un array.
Hay una mala concepción de que siempre tiene que ser sí o sí un objeto.
Y no tiene por qué.
Lo importante es que sea global el estado, pero podría ser hasta un string, si lo quisieras.
Es raro, pero lo podría ser.
Así que vamos a crear aquí la interfaz.
Esto es de TypeScript, pero lo que vamos a hacer es como describir las propiedades que tiene un usuario.
Un usuario, ya hemos visto, que tendría el nombre, tendría por otro lado su email y también tendría su username de GitHub.
Ahora bien, tenemos dos tipos de usuario.
El usuario como sus propiedades, pero también tendríamos el usuario que guardamos en el estado.
Tendríamos en el estado, el usuario del estado va a extender a este usuario que tenemos aquí.
Y simplemente vamos a añadirle la id, porque la id es algo que solo vamos a tener más que el estado.
Podemos poner user with id, por ejemplo, más que estado.
User with id, por ejemplo, o algo así.
Porque una cosa sería el estado, por ejemplo, el que podemos crear.
Podemos crear un usuario pasándole esto y la id se la ponemos después.
Pero también podemos tener users with identification, que extiende este usuario y que tiene la id que va a ser un string.
Ya tendríamos aquí como dos objetos que hemos descrito y ahora podríamos ya crear nuestro estado inicial.
El estado inicial va a ser un array de usuarios con id.
Así que creamos aquí un array.
Y en el array ya ponemos los objetos que habíamos creado aquí.
Ya que lo hemos creado aquí, pues nos lo vamos a traer.
Vamos a traernos esto y quitamos el users este.
Fuera, fuera.
Y estos los vamos a poner aquí.
Ya que teníamos estos, ¿vale?
Esto que era el tipo, esto lo podemos quitar, esto lo podemos quitar.
Y con esto ya tendríamos nuestros usuarios.
Este sería el estado inicial.
Obviamente, en la vida real, el estado inicial debería ser un array vacío.
Porque todavía no debería tener ya usuarios.
Pero nosotros vamos a poner tres para que al menos podamos ir viendo que todo va funcionando.
¿Vale?
Que al principio cuando refresquemos veamos que de alguna forma funciona.
Así que nuestro estado inicial es un array de objetos.
Ya está.
Que en este estado vamos a empezar a hacer operaciones.
Y estas operaciones serán las que podamos poner en los reducers.
Por ahora el initial state lo utilizamos aquí.
Los reducers por ahora lo dejamos vacío, aunque luego lo utilizaremos.
Y vamos a hacer un export default de users slice.reducer.
¿Por qué necesitamos users slice.reducer?
El tema es que lo que creo aquí en este slice, lo único que, bueno, lo único no, lo que nos interesa en este punto es sobre todo el reducer.
¿Qué es el reducer?
¿Cómo se utiliza?
¿Y para qué funciona?
Mira, pues te lo voy a enseñar aquí.
Cuando entramos aquí a cómo funciona Redux, tenemos primero este data flow que es el más sencillo, donde es circular.
Tú tienes la vista, que sería el componente, el componente envía una acción y la acción lo que hace es cambiar el estado y el estado al cambiar vuelve a actualizar la vista.
La vista, el usuario le da clic a un botón, va a una acción, a un estado, tal.
Pero, ¿qué pasa con esto?
En este punto de aquí, en esta rayita, en esta rayita, es donde entran en juego los reducers.
Los reducers, que es parte de la terminología de Redux, pero que también son cosa de React, porque ya sabes que tenemos el custom hook de use, reduce, y que lo hemos explicado y que no lo hemos visto.
¿Qué es lo que hace?
Lo que hace es reducir, pero no en el sentido de hacer pequeño, sino en el sentido de transformar.
Lo que hace es transformar el estado del previo al nuevo, dependiendo de la acción que le estemos diciendo.
Por ejemplo, si queremos borrar un usuario, el reducer lo que haría es decir, vale, si me dices que borre un usuario, voy a recuperar el estado y voy a quitar este usuario.
A mí me gusta mucho más la gráfica que hay más abajo.
Está esta de aquí, que es mucho más bonita y además se mueve.
Fíjate, mira, vamos a empezar.
Esta es la store, que es la caja donde, como puedes ver, tienes por un lado todos los reducers y por otro lado el state.
Lo que va a ocurrir aquí es que en la store es donde tienes los reducers, que son los que se encargan de transformar el estado.
Y cada vez que, como ves aquí, en el estado tienes, vale, el estado, tengo 10 dólares.
El usuario le da click y pues le quita deposit.
El event handler lo que hace es enviar la acción a la store y en la store llega a un reducer y este reducer genera un nuevo estado.
Este nuevo estado va a la interfaz, el usuario vuelve a darle a un botón, este event dispatcher, pues al final hace un dispatch de la acción, del tipo tal, el payload tal, va a la store y así es todo el rato.
Es así, es súper interesante porque al final es rotativo e infinito.
Lo que está muy bien es que va siempre en una sola dirección.
Como ves, siempre va en una sola dirección.
Estos son los reducers, entonces.
Los reducers recuperan una parte del estado, por eso tiene esta flechita de aquí, ¿vale?
Dentro de la store, los reducers lo que hace es recuperan el estado y con la acción que le ha llegado y el estado que tiene en ese momento, va a calcular el nuevo estado.
Esto es todo cómo funciona Redux.
Esto es todo lo que tienes que saber de Redux.
Si tú tienes dudas de cómo funciona Redux, de qué es lo que hace Redux, lo único que tienes que hacer es venir aquí y ver esta gráfica.
Luego hay cosas más complejas como My Deluxe y tal, que te lo voy a explicar después, pero lo importante es que esto lo tengas clarísimo.
Y ahora, conforme vayas viendo qué hace cada reducer, seguro que con esto en la cabeza lo vas a tener clarísimo.
Así que venga, vámonos para aquí.
Todavía no voy a poner Reduxer, luego lo añado, ¿vale?
Para que no liemos a nadie, pero podríamos empezar primero por leer la store.
Lo primero que vamos a querer hacer, seguro, es leer la store.
Así que ahora que hemos creado al menos nuestra parte de la store, que sería para los usuarios,
lo que vamos a hacer es volver a nuestra store, que era esta de aquí, y vamos a importar el slice que teníamos del users slice reducer.
Así que vamos a poner aquí, users reducer from users slice.
Y este user reducer, dentro de reducer, lo que vamos a hacer es decirle, vale, tengo una parte de los reducers,
que es de los usuarios, que te la estoy pasando aquí, que es users reducer.
Con esto ya tendríamos la store preparada, al menos, para que pueda funcionar con nuestra parte de usuarios.
Lo más interesante es que esto, tú extenderlo, lo puedes extender infinito y lo que quieras.
Ya podrías crear un slide para post, para lo que tú quieras, y ir añadiendo y concatenando aquí.
Aquí pondría ya post, use reducer, no sé qué. Así de fácil, sin ningún tipo de problema.
Vamos a leer la store. ¿Cómo podemos leer la información que tenemos en este slice?
Súper fácil. Lo único que tenemos que hacer es, nos vamos aquí al list of uses,
o en cualquier parte de la aplicación donde lo queramos hacer, import, use selector, vale,
no sé por qué no hace el autocomplit, pero debería estar ahí, vale, de Redux, use selector.
Y aquí llamamos al use selector, decimos, mira, los usuarios, lo utilizas del use selector, del state,
y del state me sacas state.users. ¿Por qué state.users? ¿De dónde sale esta magia? ¿Por qué users?
Vale, este users viene de este users. Si yo aquí pusiera de pepitos, tendríamos que poner aquí .pepitos.
O sea, esto no es mágico de que el .user se lo esté inventando,
sino que nosotros al ponerle el nombre Reduxer aquí de users, está recuperando este nombre
y ya nos está separando el estado en users, vale, ya nos está agrupando que los users tienen su propio estado
y que cuando queramos acceder a él, en este caso esto será un array, pues ya lo tendremos.
Vale, ya ves que hay un problema de TypeScript, no te preocupes que luego lo arreglamos,
pero ahora por ahora lo importante es que podamos recuperar los users y vamos a ver si realmente esto funciona.
Así que vamos aquí, vale, parece que todo funciona. Si nos vamos al slice y yo que sé, vamos a cambiar
jacón dalberg, vamos a ponerle que soy yo, vale, de github, a ver si así, vale, veis, funciona perfectamente,
parece que funciona bien y que se actualiza y que está recuperando del estado.
Ya estamos leyendo el estado global, esto significa que podríamos leer esta información
desde cualquier sitio, desde cualquier componente, simplemente con esta línea de código.
Pero vamos a arreglar el problema de TypeScript. Uno de los problemas que mucha gente tiene,
y es normal, es el tema de tipar en Redux. Y es un rollo. ¿Cuál es mi recomendación a la hora
de tipar en Redux y este tipo de cosas? Aparte de mirarte la documentación. Es intentar tipar lo
menos posible. ¿Por qué? Porque alguien en este punto se puede volver loco y puede decir,
ostras, pues aquí vamos a poner que esto es users state, no sé qué, y cada vez que esté utilizándolo
se va a volver aquí tarumba tipándolo todo en todos los sitios a la vez y en todas partes.
Y eso no funciona así, porque es muy difícil realmente poderlo tipar bien.
Ya en la documentación te explican diferentes formas de cómo arreglar esto de forma casi
semi-automática. Por ejemplo, podrías tener por un lado aquí, podrías exportar un tipo
que sea el del estado de la raíz y le dices que el tipo del estado del root state va a ser
el return type. Esto es una utilidad que tiene TypeScript en la que le tenemos que pasar
de dónde, de qué función debería sacar esto. En este caso le decimos del typeof del
state punto, del store punto get state. ¿Vale? Estamos diciendo que de la función
store punto get state que hemos creado aquí, de este tipo que tenemos aquí, el tipo que
devuelve sea el que tenemos en el root state. Y fíjate que ha hecho la magia en el que ha
detectado automáticamente que ahora el root state este va a tener usuarios que es un array
de usuarios con id. ¿Vale? O sea, estamos haciendo store punto get state. Esto es una
función. Estamos sacando la función, el tipo de la función y hacemos el return time
que lo que nos hace es poder obtener el tipo que retorna la función. Puede ser que te esté
volando la cabeza, pero no pasa nada porque la buena noticia es que esto lo haces una
vez y ya está. Y de hecho esto lo ponen en la documentación. Si vas a la documentación
y dices cómo utilizar TypeScript con Redux, te dicen pon esta línea directamente. No te dicen
nada más. Lo que pasa es que lo tienes que hacer tú porque la store, como la estamos
creando aquí, no son capaces de poder inferirlo. Así que le tienes que decir tú de qué store
que has creado tiene que recuperar el tipo. Y lo mismo podemos hacer a la hora de hablar
de los dispatch. Así que hacemos export type aquí app dispatch y le decimos que el type
pop del store punto dispatch es el que queremos tener. Así que este app dispatch ya tiene perfectamente
también tipado cuando lancemos las acciones. Va a saber qué acciones son las que puede lanzar
porque es de esta store que hemos creado justamente aquí. Así que con esto ya nos
ayuda a tipar. Pero aún así podríamos utilizar este root state, utilizarlo por aquí y hacer
algo así. Decir vale, pues este root state viene de aquí o este state es el root state.
Podríamos hacerlo de diferentes formas. Pero una buena práctica siempre en este tipo de
casos es en lugar de estar constantemente llevándote el tipo allá donde lo necesitas,
lo que debes hacer y pensar es más bien al revés. Tú lo que haces es crear un custom
hook en un sitio y aquí pues puedes poner, no sé si ponerle store. Ponemos store, ¿vale?
Y aquí pues lo que podemos hacer es primero importar el tipo, los tipos que hemos creado, el
app dispatch y el root state, ¿vale? El root state. Luego vamos a importar tanto el use
dispatch, que sería la forma de enviar acciones, como el use selector, que es el que hemos
visto que hemos utilizado ya. Y esto lo traemos de Real Redux. Y luego vamos a importar el
tipo también de type use selector hook. ¿Qué hacemos aquí? Pues vamos a crear nuestros
custom hooks, que son los que vamos a utilizar ya en toda la aplicación y así nos olvidamos.
Por un lado vamos a utilizar el selector, le puedes llamar use app selector, esto es como
lo recomiendan en Redux, pero le puedes utilizar el nombre que tú quieras. Incluso aquí podrías
hacer custom hooks para acceder solo a partes de tu estado, no hace falta que accedas a todo el
estado. Si quieres podrías hacer un custom hook para acceder solo a la parte de los usuarios.
Aquí en nuestro caso no tiene mucho sentido, pero nosotros lo vamos a hacer más general,
porque solo vamos a hacer el de usuarios y ya está. Y aquí tenemos que tipar el use selector hook
y le decimos que esto lo que va a hacer es utilizar el root state que ya tenemos. ¿Cuál es el valor
que tiene esto? Simplemente use selector, no tenemos que hacer nada más. O sea, esto en realidad
sería como esto. Lo que le decimos que el use app selector le decimos el tipo, lo tipamos con el
root state y es como que le estamos haciendo, lo estamos como renombrando y a la vez le estamos
indicando el tipo. O sea, estamos como cambiándole el tipo al use app selector para que encaje
perfectamente con nuestro estado. Y es algo parecido con lo que vamos a hacer con el use app dispatch,
que le vamos a decir que esto lo que hace es app dispatch, que lo hemos recuperado aquí.
Lo bueno es que esto te lo puedes copiar y pegar y ya está. No hace falta que te... No es muy difícil
de entender, pero es una cosa que es que hay que hacer porque no es capaz Redux de inferir todo
este tipo de datos y por desgracia necesitas un par de líneas. Pero no es difícil. O sea, tendríamos aquí
que en lugar de utilizar, como estamos utilizando aquí, el use selector directamente, sin utilizar
el use selector directamente, lo que estamos haciendo es este use selector no sabe qué estado
tiene. Pues vamos a crear nuestro propio use selector, ¿vale? Este use selector lo vamos
a asignar a otra constante, se llama use app selector y le vamos a decir cuál es el estado
que tiene. Esto lo que nos permite es evitar tener que hacer esto constantemente en todos
nuestros use selector. Así te olvidas, te olvidas y además es buena práctica porque ya no vas a ver
real redux. Ya simplemente haces use app selector, esto lo importas de tus custom hooks, ¿vale?
Que serían store y ahora utilizas el use app selector. Y fíjate, utilizando el use app selector
que hemos creado, ahora ya no me da el error de TypeScript. ¿Por qué? Porque este use app selector
sabe que vamos a tener en el estado el objeto de users, del array de users with id. Ya está, punto
pelota. Si no utilizas TypeScript, pues no necesitarías hacer nada de esto. Aún así, ojo, cuidado,
imagínate que utilizas solo JavaScript. Aún así, sería buena idea hacer algo parecido
a esto, aunque sea algo así. Y algo así. Y la pregunta sería, ¿por qué? Esto puede ser buena
idea porque esto lo que hace es añadir una capa de abstracción entre tu componente y React
Redux. Un error, un error muy común que veo con React Redux o con Redux Toolkit es que la gente
está haciendo este import, este import, este import en todos sus componentes. Y esto es un rollo. Esto
es un rollo porque esto lo que estás haciendo es romper totalmente. O sea, estás teniendo una
dependencia muy bestia dentro de tus componentes. Y va a hacer que sea muy fácil que tu aplicación
se rompa si al final quieres algún día quitar React Redux y quieres utilizar Zustan. Lo que estamos
haciendo es una pequeña abstracción que si el día de mañana cambia Redux por Zustan, pues sea
totalmente transparente. Y solo con dos o tres líneas de código lo puedes conseguir. Porque tú haces esto
y entonces si el día de mañana en lugar de Zustan aquí, o sea, de Redux utilizas Zustan, lo vamos a poder
hacer. Pues nada, utilizamos nuestro app store que hemos creado aquí. Use app selector, ahora
totalmente tipado, perfectamente. Ya tenemos aquí los users y si miramos aquí en navegador, todo
funciona perfectamente. Venga, vamos a hacer una acción ya. Vamos a hacer una acción porque ahora
todo lo que hemos hecho, pues alguien dirá, joder, pero no has hecho nada. Haz algo, haz algo, haz que haga algo.
Venga, vamos a hacer algo. Vamos a hacer el más fácil que es el de delete user. Delete user by ID.
Te voy a enseñar cómo hacerlo. La primera opción, cómo hacerlo mejor y cómo hacerlo bien. En los reducers,
tú lo que utilizarías aquí es tener un objeto donde le pondrías como key el nombre de lo que haría,
delete user by ID, y aquí tendrías un método para que haga esa acción. Como primer parámetro, lo que va a recibir
es el estado y como segundo parámetro va a recibir la acción. Para borrar un usuario de aquí, del estado,
es bastante sencillo. Lo puedes hacer de diferentes formas. Esta está bien. Esta está bastante bien. O sea,
recuperar la ID del action load y del estado, filtrar aquellos usuarios que sean diferentes al ID. Y
entonces el que tenga la ID lo que va a hacer es no devolverlo y por lo tanto lo borrará. Como va a
devolver un nuevo estado, pues ya está. Lo tendríamos así y ya funcionaría. Esto sería una forma de hacerlo
y me parece que es la correcta. Así que lo vamos a dejar tal cual así. Pero fíjate que aquí en el
payload, aquí tenemos payload any. Aquí me extraña, la verdad es que me sorprende. Bueno, no me sorprende
porque claro, como ID es any, pues se lo come con patatas. Pero ya sabemos que la ID esta, el action,
la ID es un string. De hecho, lo tenemos aquí. ¿Veis? Es un string. O sea que lo podríamos tipar un poquito mejor.
Una cosa que podríais hacer aquí en el action para tiparlo un poco mejor sería decirle, bueno, esto es un string
y el payload es un ID. ¿Vale? Porque es el user ID. Ay, es un string. ¿Vale? Porque es el user ID y esto
seguiría funcionando perfectamente y se lo va a comer sin ningún problema y tal. Pero habría una forma un
poquito mejor de hacer esto. Porque vamos a necesitar de alguna forma que sepa exactamente cómo es la
acción y qué es lo que le tenemos que pasar. A ver, una cosa que podríamos hacer aquí es separar el user ID que
tenemos por aquí. Podríamos también ponerle un tipo. Por si el día de mañana en lugar de, no sé,
en lugar de ser un string, pues le cambiamos a number y entonces cambiándolo en un solo sitio, pues ya lo
tendríamos. Ya teníamos este user ID aquí y lo podríamos poner aquí, user ID. Pero lo más interesante
de esto, en lugar de tipar el objeto que es un poco rollo, justamente Redux Toolkit tiene un tipo
que se llama payload action. Y en el payload action podemos utilizarlo aquí como un genérico. Y lo único que
tenemos que pasarle es como el tipo que va a tener el payload. O sea, le pasaríamos esto, user ID. Y al
action, fíjate que nos lo está haciendo bien. El payload es un string, el type es un string, porque el
user ID es un string. Queda un poquito mejor y sobre todo para que cuando son bastante más complejos
funcionen sin tener que tipar todo el objeto, pues lo hace mejor. Y además te da algún tipo de, te extiende
mejor el payload de posibilidades como ver metadatos y el error. Así que puedes utilizar cualquiera de los dos.
Yo creo que este sería el más recomendado para tener los tipos totalmente. Ya tenemos aquí este reducer, ¿vale?
Ya tenemos como el primer reducer que hacemos. Ahora, lo podemos utilizar de dos formas, pero lo mejor que podéis hacer
cuando tengáis un reducer es exportar la acción. Esto es una cosa muy interesante que tiene Redux Toolkit porque te permite
de forma muy sencilla, sin tener que utilizar el string a la hora de decirle qué acción tiene que hacer, podéis exportar la
constante de delete user by ID, que es el mismo nombre que tenemos aquí. Y esto lo sacaríamos de users slice actions, ¿vale?
Cuando hemos creado aquí el users slice, tenemos por un lado el reducer y por otro lado todas las acciones que van a ser
todas las que vamos a poner aquí. Fíjate que ya es súper fácil porque ahora esto lo vamos a poder importar y no va a ser tan difícil
de tener que preocuparte del string como muchas veces hacían Redux, que tenías que hacer. Actions sería algo así como
delete user by ID, ¿no? Y era un poco rollo porque tenías que saberte exactamente el string, entonces tenías que crear una constante.
O sea, tiene mucho menos boilerplate Redux Toolkit. Ahora que lo exportamos, nos vamos a ir a la list of users
y vamos a importar aquí el delete user by ID de store users, no. A ver, ¿de dónde hay que importarlo? De store, de store, tu, tu, tu, tu, store users
slice, ¿vale? Y ya tendríamos el delete user by ID. Te voy a enseñar cómo lo haríamos primero, pero lo más recomendable en este caso
de nuevo sería utilizar un custom hook. En lugar de hacer esto, que vamos a hacer, pero te voy a enseñar cómo lo que se hace
lo más típico, sería primero recuperar la forma de enviar acciones con el use app dispatch, que lo hemos creado antes, ¿no?
Esto lo importaríamos junto al app selector que hemos creado y este dispatch es el que ahora nos permite enviar acciones.
Si miramos otra vez el, os voy a enseñar otra vez el data flow, ¿vale? Para que veáis lo que hemos creado y qué es lo que vamos a hacer ahora.
Vale, fíjate, este dispatch es el que vamos a hacer ahora y esta acción es la del delete. O sea, que hemos hecho en el reducer, ya lo hemos creado
y ahora lo que estamos haciendo, lo que estamos implementando es la parte del event handler, el onclick, el dispatch, que es lo que acabo de recuperar
y lo que tenemos que llamar, y la action es lo que acabo de importar aquí. Este delete user by ID es esa action que estamos viajando, ¿no?
Y este dispatch es esta parte de aquí, ¿ves? Este dispatch aquí sería este. Y este action, que veis que está viajando, sería la ejecución de este método
delete user by ID. Para hacer esto, vamos a crear justamente este event handler que veis aquí. Así que hacemos aquí, le podemos llamar
handle remove user, ¿no? Handle remove user. Que aquí tenemos la ID del user ID. No sé si el user ID no lo hemos exportado.
Vamos a exportarlo, este tipo. Lo ideal sería tener los tipos separados en otro sitio, pero bueno, vamos a ponerlos por aquí.
User ID. Y aquí llamamos al dispatch con el delete user by ID y le pasamos la ID del usuario.
Este handle remove user lo tendremos que ejecutar en el de borrar, que si no me equivoco es el segundo, ¿vale?
¿Veis que tenemos aquí el botón de borrar? Pues el segundo es su eje, que vamos a ponerle aquí, área, label, remove element.
En este botón vamos a llamar al handle remove user. Que le tendríamos que pasar al handle remove user, le tenemos que pasar cuál es el usuario que queremos borrar.
Así que item.id, le pasamos el usuario y en el handle remove user, aquí recupera la ID del usuario y hacemos el dispatch del delete user by ID.
Esto debería funcionar. Vamos a probarlo a ver si funciona. Hemos hecho todo bien. Vamos para acá, borramos este, ¡pum! Vale.
Y ha desaparecido. Si borramos este, pues ha desaparecido.
Bueno, y fíjate que ya lo bueno de esto es que cambia automáticamente el número de usuarios que tenemos aquí y también en la lista, pues solo queda uno.
Si lo quitamos, pues nos quedará cero y ya está. Ahora, si refrescamos, pues van a recuperar otra vez. ¿Por qué?
Porque no hemos persistido el estado. Esto es súper importante, que mucha gente se cree que Redax hace magia y te persiste los datos, vete a saber de dónde, ¿no?
Esto, lo que estamos haciendo en realidad es, en memoria, estamos calculando el estado. En memoria.
Pero una vez que nosotros refrescamos la página, pues esto se pierde.
¿Qué es el área label? Es un tema, es como una etiqueta que se le da para saber de accesibilidad a qué se refiere ese icono, porque si no...
Puedes repasar sobre lo que es el slice. El slice es una parte de la store, es un trocito de la caja que es lo que guarda todas las acciones reducers y el estado que tiene que ver con ese trocito.
En nuestro caso, en el slice, hemos creado un slice. Hemos creado un slice, aquí creamos un slice, que es para los usuarios con su estado inicial y los reducers, que van a ser los que van a gestionar cada parte del estado.
Son las acciones para cambiar el estado. Por ejemplo, ahora hemos creado la acción de borrar el usuario por id. Y borrando el usuario por id, lo que hacemos es cambiar el estado, filtrando esos usuarios que no tienen justamente esa id.
Así, cada vez que queramos borrar uno, como le decimos, borra el número dos. El que no tenga el número dos, pues se queda. Ya está.
Ahora, a mí esto es otra cosa que suele hacer mucho la gente, pero gente que son senios, que tienen 14 años de experiencia y hacen estas cosas.
Yo esto no os recomiendo que lo hagáis en vuestras aplicaciones porque tiene bichos. ¿Por qué tiene bichos? Porque estáis atando, o sea, es como que a nivel de componente se ven las tripas de vuestra aplicación,
de cómo esto además lo tenéis que hacer en todos y cada uno de los sitios. Lo mejor, normalmente, es que podáis tener incluso, yo qué sé, podéis llamar, aquí cada uno ya lo puede hacer como queráis, ¿vale?
Pero yo recomiendo que en lugar de utilizar el useAppDispatch en todos los sitios, podéis tener un useUser o useUserActions, userActions, por ejemplo, que los separéis, ¿vale?
Es muy fácil separarlo, no tiene mucha historia. Lo único que tenéis que hacer, mira, ya justamente esto que tenemos por aquí, lo podríamos tener aquí.
Aquí, pues, separáis el handleRemoveUser o, lo que sé, o removeUser, por ejemplo. Esto lo podemos poner así, removeUser y ya está.
Ahora quitamos esto, lo importamos aquí, o sea, importamos todo lo que necesitemos. Esto hay que ponerlo así, useAppDispatch, lo importamos, el userID también.
Y ya está, o sea, así tenéis todas las acciones separadas y si el día de mañana quitáis, por lo que sea, que Dios no lo quiera, pero si tenéis que quitar, yo qué sé, Redux,
pues no lo tenéis constantemente en todos vuestros proyectos, o sea, en todos vuestros componentes, que luego cuesta un montón sacarlos, que no salen ni con agua caliente.
Es que cuesta un montón. Así que, mira, el handleRemove, esto al final ya lo del onClick, de hecho, esto ya, pues, lo podéis poner incluso en el propio, esto lo ponemos así, userActions y el removeUser,
o lo podéis hacer en el propio onClick, si queréis, si os gusta, pues lo podéis hacer aquí y ya está. Y esto funciona exactamente igual, pero a la hora de repetir código,
tener que repetir constantemente los impos, el dispatch y todo esto, es muy doloso y hace que vuestro código sea muy poco sostenible.
Es mucho mejor que el dispatch y todo esto lo tengas en un custom hook y a partir de ahí, pues ya lo tengas en un sitio, ¿no?
¿No sería mejor todos los hooks que tengan objetivo entre actuar en ese store, estar dentro de store, users, así te permite tener la posibilidad de crear más stores
y cada uno tenga todo lo que vincula en su carpeta? No tiene por qué, o sea, no tiene mucho sentido, la verdad, que esté dentro de store users.
De hecho, yo, a la hora de hacer las carpetas estas, ahora lo dejo así bastante sencillo, pero yo no lo haría como comentaba Gaspar.
¿Por qué? Porque estás metiendo la store, o sea, estás metiendo un hook dentro de la store y si el día de mañana ya utilizas la store
y lo utilizas otra cosa, entonces lo vas a mover, es raro. ¿Cómo se debería hacer esto normalmente?
Realmente deberías tener un users, o sea, en el Screaming Architecture lo que deberías tener aquí en users es,
dentro de users tendrías con los componentes, podrías tener los hooks, o sea, sería más bien al revés.
Y de hecho, yo recomiendo que el hooks, que debería ser bastante agnóstico a lo que utilicéis,
no lo tengáis dentro de la store, porque dentro de la store, al final este hook utiliza la store
porque es lo que estás utilizando, pero podría utilizar otra cosa, entonces no lo metáis tan dentro
porque al final no tenía mucha historia, ¿vale?
Pero si no, lo que puedes hacer es users y dentro de users es tener tanto hooks como hooks, podrías tener la store,
o sea, podrían meter esto que hemos metido aquí, sería como darle la vuelta.
Y tiene mucho más sentido porque a la hora de cambiar tecnologías es mucho más fácil esto que no esto,
porque tienes la arquitectura en el primer nivel cuando en realidad lo más importante en tu negocio
en realidad son los usuarios, no la store.
Y esto es lo que se le llama Screaming Architecture.
Si queréis echarle un vistazo, Screaming Architecture, porque ahora no me da tiempo a explicaros todo Screaming Architecture,
pero le podéis echar un vistazo a este artículo, que lo explica bastante bien, bastante antiguo, pero está bastante bien,
y si no, buscar más sobre Screaming Architecture y veréis un poquito esto, ¿no?
Como en lugar de tener Django, o esto sería el correcto, ¿no?
¿Ves? Es que empiezas por Django, o sea, está mal, porque empiezas por Django y si cambias Django,
o sea, es que está mal. Lo correcto sería esto, ¿no? Utilizar backoffice, contratos, create, offices, listar, car renta,
o sea, estás poniendo tu negocio por delante y luego dentro tienes los modelos, tendrás el controlador y ya está.
Screaming porque lo que está haciendo es gritar, es que te está gritando realmente lo que utiliza tu negocio,
eso es lo que sería, pues eso se le llama Screaming Architecture.
Pues ya que tenemos el delete, ya hemos hecho un poco esto, luego aquí cada uno que lo haga como quiera,
lo podéis hacer como queréis, si lo queréis meter en el store, yo os digo como lo haría yo.
El problema que tenemos con esto, obviamente, la persistencia, ¿no?
Cada vez que refresco me aparecen aquí otra vez mis usuarios, esto no puede ser,
porque la gracia es que tenga persistencia.
Entonces te voy a enseñar el concepto de Midelware.
Un Midelware es un concepto muy interesante porque al final está aplicado a muchas cosas, ¿no?
Pero Midelware es algo que se ejecuta en mitad de algo.
Es casi como un proxy y en Express tienen algo bastante similar,
pero lo que quiere decir es que vamos a capturar en un momento en concreto,
y en este caso vamos a tener la posibilidad de ponerlo aquí, aquí en medio, ¿ves?
En toda esta raya, vamos a tener la posibilidad de tener un Midelware aquí,
aunque también vamos a poder hacer cositas aquí, ¿vale?
O sea, que vamos a poderlo aquí y aquí.
Un Midelware lo que nos va a permitir es como capturar cada vez que se hace un dispatch,
ver lo que está haciendo, poder esperar a que termine esto,
y después, una vez que tengamos el nuevo estado, hacer algo también con eso.
Esto lo que nos permite es cambiar la funcionalidad que está haciendo nuestra aplicación,
y de una forma totalmente transparente, sin necesidad,
de que es como lo haríamos muchas veces, de meter nada aquí.
Porque obviamente aquí podríamos llamar al local storage, ¿no?
Podríamos llamar y eliminar al usuario también.
Podríamos actualizar aquí el local storage y constantemente estar ahí en el local storage
en cada uno de los reducers.
Pero lo que queremos hacer es hacerlo bien.
Así que, ¿qué vamos a hacer?
Vale, vamos a crear un Midelware, que le vamos a llamar local storage,
bueno, persistence, que me gusta más, Midelware.
Un Midelware es una función que recupera la store,
que tiene que devolver una función que recupera un método next,
que tiene que devolver una función que recupera un método action.
Seguramente ahora estarás alucinando y dirás,
pero a ver, ¿qué ha pasado aquí? ¿Qué ha pasado aquí?
Esto, que no es tan raro como parece,
porque al final esto es una función que devuelve todo esto.
Esto es una función que devuelve todo esto.
Y esto es una función que devuelve esto de aquí.
¿Por qué hace esto? ¿Por qué realmente necesita hacer esto?
Esto lo hace porque como está en diferentes puntos,
lo que vamos a querer es, por un lado, poder leer la store,
pero también vamos a querer llamar el reducer para que actualice el estado.
O sea, vamos a querer tener una forma de ejecutar una función
para que pueda ir al siguiente paso.
Y por eso tenemos una función que devuelve una función que devuelve una función
porque le estamos inyectando en cada uno de los pasos diferente información.
Por un lado la store, por un lado una forma de ir al siguiente
y por otro lado la acción que se le está enviando.
Entonces, hay gente que diría, bueno, pero ¿por qué no se le pasa así?
¿Por qué no se le pasa así? Y ya está.
Porque en realidad la ejecución de cada uno de los métodos
está pasando en un momento distinto.
No es que se esté ejecutando uno a la vez,
sino que se está ejecutando cada uno, cada función que está devolviendo
en una parte diferente de forma interna.
Por eso es que necesita tres funciones
y que cada función devuelve e inyecta la información que puede en ese instante.
Por eso el MyDellware es así.
Recibe la store, devuelve una función que recibe una forma para ir al siguiente
y devuelve una función para tener la acción que le ha llegado.
Ahora que ya tenemos esto, es bastante sencillo en este caso.
Pero bueno, os voy a enseñar, por ejemplo, el store.getState aquí.
Vamos a recuperar el estado de la store.
Aquí vamos a llamar al next pasándole la acción.
Esto sería como haz lo siguiente que tengas que hacer
y luego vamos a hacer un console.log aquí del store.getState.
Lo bueno de esto es que vas a ver muy fácilmente
cómo cambia cada una de las cosas.
Vamos a poner aquí la action también para que lo veas.
action, para que veas la acción que la ha recibido.
Fíjate, vamos aquí.
Voy a borrar...
Ah, espérate, claro, que está muy bien, que he hecho el MyDellware,
pero no lo estamos usando.
No estamos utilizando el MyDellware.
Tenemos que aquí en MyDellware,
MyDellware, tenemos que utilizar el persistent MyDellware.
Aquí lo que le vamos a decir...
Ay, ¿qué ha pasado aquí?
Ay, que esto lo estoy haciendo donde no es.
Lo he hecho en el slice y lo tenía que hacer en la store.
Lo teníamos que hacer aquí.
Aquí es donde tenemos que hacer.
Y es este persistence que lo he añadido aquí.
Esto tenemos que añadir la store.
Lo he puesto ahí, no sé por qué lo he puesto ahí.
Aquí, vale.
Entonces, en reducer, tenemos los reducers.
En MyDellware le pasamos un array con todos los MyDellware
que queremos utilizar.
Esto está muy chulo porque no solo vamos a poder persistir
en local storage.
Persistence local storage, voy a llamarle.
Me parece mejor.
Porque luego vas a ver cómo podemos persistir en base de datos
y cómo puedes hacer un rollback del estado y todo,
que está bastante chulo.
Ahora que ya tenemos esto, fíjate, voy a borrar.
Y aquí vamos a poder ver el console.log aquí.
Aquí tenemos el console.log.
Me dice, el estado anterior era tres usuarios,
tres usuarios, que eran estos usuarios.
Vale.
Ha recibido la acción de borrar el usuario con el payload de uno.
Una vez que se ha hecho la acción,
hemos recuperado el estado y ya solo me quedaban dos usuarios.
O sea, que aquí ya puedes ver que hemos hecho,
podemos hacer cosas antes,
justo antes de que se actualice el estado
y justo después de que se actualice el estado.
Y esto lo que nos permite es controlar,
pues podríamos validar datos,
podríamos enviar una petición asíncrona,
si quisiéramos, para recuperar datos,
para validar datos, para hacer lo que queramos antes y después.
En este caso, lo que queremos hacer es justo después.
Después de cualquier acción,
lo que podemos hacer aquí es hacer un localStorage.setItem,
le podemos llamar ReduxState,
vamos a poner ReduxState,
por ponerle un nombre así que no tenga colisión,
transformamos toda la store,
el estado a un string y lo guardamos.
Ya está.
Eso es todo lo que tendríamos que hacer en este punto.
Esto lo que va a hacer, obviamente,
sería transformar el estado.
O sea, esto no va a tener ningún problema.
Si le damos, pues está borrando el estado,
todo funciona, si miramos el localStorage,
vamos a aplicación,
vamos a localStorage,
aquí localStorage,
ves, ReduxState, aquí tenemos el estado.
Pero si yo refresco, me vuelven a salir los tres.
¿Por qué?
Porque no estamos leyendo esta información.
Esta información la hemos guardado,
pero no la estamos leyendo.
Así que aquí,
ves que tenemos aquí un initialState
con todos los usuarios y todo esto.
Vale, el initialState este ahora va a cambiar un poquito.
Mira, vamos a dejar este default,
este le voy a llamar,
defaultState, ¿vale?
Con lo que teníamos antes,
el array que teníamos antes.
Pero el initialState que habíamos puesto aquí,
vamos a cambiarlo un poco.
Vamos a decirle, mira,
vamos a, mira,
esto está muy chulo porque muchas veces me preguntáis
para qué serviría una función
que se invoca a sí misma.
Pues mira, aquí vamos a ver un ejemplo
bastante interesante.
Mira, vamos a leer primero el persistedState
del localStorage.getItem.
Si tenemos un state persistido,
¿vale?
Si tenemos el persistedState,
entonces vamos a devolver,
joder, esto solo sabe todo.
Vamos a devolver del estado el .users.
Vamos a utilizar del estado persistido,
vamos a parsear ese JSON
y vamos a devolver como estado inicial
el json.pars.users.
Y si no, vamos a utilizar el defaultState.
¿Por qué?
Esto está muy chulo.
Esto está muy chulo porque estamos llamando una función
que se autoinvoca, ¿vale?
¿Por qué?
¿Por qué estamos haciendo esto?
Porque esto, lo que está haciendo el return
es devolvernos uno de los dos.
O este de aquí, o este de aquí.
Esto lo podríamos hacer de una forma mucho más,
seguramente, sucia,
que sería sacarlo fuera, ¿no?
Podríamos sacar aquí const persistedState.
Podríamos sacar todo esto.
Podríamos sacar esto.
Y podríamos tener aquí letInitialState.
Y le podemos decir que esto es userWithIdDefaultState.
Podríamos hacerlo de otra forma, ¿vale?
Podríamos hacerlo así, persistedState.
Si tengo persistedState,
entonces initialState es esto.
InitialState es esto.
Podríamos hacerlo así.
Esta sería una forma de hacerla.
El estado inicial, por defecto, es el defaultState.
Pero si tengo en el localStorage el ReduxState,
si lo tengo, si no es null,
entonces el initialState lo machaco,
lo machaco y hago un JSON.parse,
y hago esto, y me saco los users.
Pero la verdad es que una forma que está bastante bonita
sería hacer esta.
Esta está bastante bonita,
se entiende bastante bien,
a mí no me desagrada.
y es una razón justamente para utilizar,
por la que podrías utilizar una ifi,
que será una Immediately Invocate Function Expression.
Como es una expresión,
lo que hace es devolver el valor,
y de una, sin necesidad de sobreescribir,
lo que hace es meterlo directamente.
Además, queda bastante acotado,
porque es en el sitio en el que necesitas inicializar esta constante.
Me parece una forma bastante chula,
que muchas veces me preguntáis,
oye, ¿para qué sirve una ifi?
Pues aquí tenéis una forma de encapsular una parte de lógica
para inicializar una constante
sin necesidad de tener que preocuparse
por el nombre de las constantes y tal,
creando aquí dentro una closure,
y ya está.
Lo que hace es que si no funciona directamente el ternario,
podéis hacer que...
Si no funciona directamente el ternario,
podéis hacer aquí un ternario si queráis.
A ver, es indiferente,
no me parece muy importante,
pero si queréis el ternario,
podéis hacer este el ternario.
Pero bueno, me parece que cualquiera de las dos,
con el if o con el ternario,
podéis utilizar este si queréis.
Pero claro, primero tenéis que hacer el getItem fuera,
obviamente, no lo podéis hacer dentro del ternario,
pues necesitáis saber si tenéis el getItem.
Pero si os gusta más esta, pues haced esta,
cualquiera de las dos.
Ahora, fíjate que ahora estoy refrescando,
y ahora sí que tengo el estado,
lo está inicializando correctamente.
Si ahora vuelvo a borrar,
pues ves, me queda solo una.
Si vuelvo a borrar, ya no tengo ninguna.
Ahora debería en el local storage,
lo podría borrar en el local storage,
y ahora me saldrían otra vez todas, ¿vale?
Vamos a hacer rápidamente,
ahora que ya tenemos el initial state,
vamos a hacer rápidamente lo de añadir un usuario,
porque obviamente vamos a querer añadir un usuario.
Uy, ¿qué le pasa aquí?
Se me ha puesto loco.
No sé qué le pasa.
¿Qué le slice?
Slice.
No me guarda el fichero.
¿Veis que no me guarda el fichero?
¿Qué le pasa?
No sé.
Ah, ahora sí que me lo ha guardado.
No sé por qué me da aquí un error,
pero yo creo que esto es que se le ha ido a la mano.
Espeta semicolon,
una implicit semicolon after statement,
but found none.
Mentira, aquí hay uno.
Aquí hay uno.
Es que se le ha ido como aquí la cabeza,
porque no sé por qué no lo está pillando muy bien.
Bueno, vamos a hacer rápidamente
el de crear create new user.tsx.
Vamos a traernos de Tremor.
Vamos a traernos unas cuantas casas.
Vamos a traernos el button,
la card,
el text input,
el title de Tremor React, ¿vale?
Y export function,
create new user,
return.
Creamos una card,
ponemos la card,
ponemos el title,
create new user.
Vamos a ponerle aquí una separación a mano
para que no se nos pegue con la parte de arriba.
Y aquí vamos a poner un formulario.
Vamos a poner esto.
Text input con el label.
Vamos a ponerle...
No, el label.
Yo creo que no tiene el label esto.
Vamos a poner un playholder.
Aquí el nombre.
¿Vale?
Text input,
playholder,
aquí el apellido no.
Aquí el mail,
aquí el email,
text input,
aquí el password no.
Aquí el usuario,
el usuario de GitHub.
¿Vale?
Text input,
form,
no sé qué.
Y os voy a enseñar una cosa muy chula
sobre mutabilidad
en Redux Toolkit.
¿Vale?
Ponemos aquí un botón,
¿vale?
Me parece bien.
Crear usuario,
un botón,
¿vale?
Y yo creo que con esto,
crear usuario,
con esto deberíamos tenerlo.
¿Vale?
No sé qué le pasa a mi usuario,
a Studio Code.
Vamos a cerrarlo un momento.
Quit anyway.
Vamos a cerrarlo un momento.
Porque no sé qué le ha pasado.
Que no sé,
que no me estaba...
Y si quiero consumir una API,
luego lo vamos a ver.
Tenéis,
podríamos hacer Redux Thanks,
aunque yo no lo recomendaría,
de hecho,
yo tampoco,
no lo recomendaría,
la verdad.
Intentaría evitarlo
a toda costa
y utilizaría más React Query,
por ejemplo,
para hacer,
llamar a una API.
Porque es que tenéis que dividir,
o sea,
tenéis que,
no tenéis que pensar
que queréis llamar la API
desde el estado global.
Que eso es otro error
súper,
súper,
súper tremendo,
¿no?
Que mucha gente mete
las llamadas a las APIs
dentro de los reducers.
Y yo creo que los reducers
deberíais intentar
que en realidad sea
para gestionar estados.
Pero es que la lógica
del action
esté en el mismo action
o en la función
que ejecuta el dispatch.
Depende de la lógica.
Si la lógica es
de actualizar el estado,
esa lógica debería estar
en el reducer
y no en el componente.
Para llamar a API
está bien usar
los extra reducers,
está bien,
pero también podrías utilizar,
podrías hacerlo
directamente fuera.
O sea,
que no debemos hacer
dispatch de un fetch
a una API
y luego guardarlo
en el estado global.
Sí que podríais hacer
no dispatch de un fetch,
sino que podríais hacer
el dispatch
donde
una vez que tengáis
el resultado,
por ejemplo.
O no utilizarlo
con React Query,
por ejemplo.
Es que con React Query
no lo vais a necesitar.
Y ya está.
Ahora que sí que parece
que funciona
lo demás,
ahora que ya os he contestado
ahí vuestras preguntas,
vamos a...
Vamos con lo siguiente.
Vamos a ver.
Tú, tú, tú.
¿Por dónde nos hemos quedado?
Bueno, queríamos hacer...
Esto no sé por qué me ha abierto.
Me ha cerrado el...
¡Hostia!
No sé.
¿Apiers corrupt?
¿Pero qué ha pasado aquí?
¿Qué ha pasado aquí
que me dice
que mi instalación
está corrupta, tío?
O sea, ¿qué está pasando?
Bueno,
vamos a utilizar
el create new user este.
Vamos a utilizarlo aquí
en el index...
en el main...
No,
en el app.tsx.
Vale.
Lo ponemos aquí.
Create new user.
Import.
Create new user.
No me está pillando los...
O sea,
es que no sé qué le pasa.
De verdad,
se le ha ido de las manos esto
porque no tengo
la autocomplete,
no tengo nada.
Y de hecho,
tampoco me funcionan
las ROM tools ahora.
No sé qué le ha pasado,
que se le ha ido.
Vamos a desactivar
el console ninja este
a ver si es culpa de esto.
Me extraña,
pero...
Sí, sí,
o sea,
se le ha ido.
Se le ha ido aquí la...
ROM,
restart lsps.
Mira.
Igual se le ha ido
a la ROM tools,
no sé.
Vamos a hacer un pnp install
por si acaso.
Pero sí,
no,
no.
Se ha perdido
el formato y tal.
Bueno,
no pasa nada.
Mientras no note problemas,
vamos a añadir aquí
el formulario
y vamos a hacer súper rápido
el...
Para que veáis otro ejemplo
y que tengamos
unos cuantos ejemplos,
¿no?
Add new user,
action,
aquí vamos a tener
el payload action
del user.
Vamos a añadir
un nuevo usuario
a nuestro estado.
¿Cómo añadimos el usuario?
Aquí,
esto es una cosa
muy interesante
de Redux Toolkit.
Obviamente,
cuando creemos el usuario,
tenemos el nombre,
el email y el usuario
de GitHub,
pero no tenemos la ID.
¿Ves?
Que la ID,
en realidad,
la tenemos que generar.
Hay diferentes estrategias
de cómo generar IDs.
Por ejemplo,
se podría generar la ID
a través de la base de datos
y por lo tanto,
lo que haríamos aquí
sería diferente,
aunque luego,
como lo vamos a ver
con el middleware,
también podría tener solución.
Pero aquí,
vamos a hacerlo en local,
vamos a crearle
un random UID
y aquí podríamos hacer algo,
¿no?
Aquí normalmente,
en Redux
o cuando gestionamos estados,
lo que hacemos es
crear siempre un nuevo estado
a partir del anterior.
Y aquí podríamos añadir
un nuevo objeto al final
y action.payload.
O sea,
lo que le estamos pasando
aquí al nuevo usuario,
tendríamos el estado
todos los usuarios anteriores
más el nuevo usuario
con la nueva ID
que estamos creando aquí
y toda la información
que nos ha devuelto.
Esto,
como vamos a ver ahora,
esto funcional funciona.
De hecho,
vamos a poder utilizarlo
aquí en un momentito.
Nos vamos aquí.
Otra vez,
aquí en el use,
use user actions.
Aquí podríamos poner
const add user
y aquí tener
el payload del usuario.
¿Qué podríamos ponerle aquí?
Pues que necesitamos
el name,
el email
y el GitHub.
¿Vale?
Hacemos el dispatch
del add new user,
que esto nos lo traemos
también de la store
y le tenemos que pasar
el name,
el email
y el GitHub.
Estos tres parámetros
de aquí justamente
son los que tenemos
en el user.
¿Qué veis aquí?
Lo tenemos aquí.
Name, email, GitHub.
O sea,
que ya veis que
todo va teniendo sentido
de tiparlo una vez
y no tener que estar
constantemente tipándolo,
sino que una vez
lo hacemos
y ya nos olvidamos.
Ya tenemos aquí
el add user
y ya podemos importar aquí
el add user
desde,
ostras,
lo malo es
que como no tengo
el autocomplete
no me salen
hooks,
use user actions.
¿Este add user
cuándo lo tenemos
que llamar?
Bueno,
pues cuando hagamos
un submit
del formulario.
Cuando hagamos
un handle submit
hacemos aquí
handle submit
y aquí tendríamos
un event
y este event
lo tenemos que tipar
porque eso no se nos quejaría.
Ahora no se me queja
porque creo que el editor
se le ha ido la olla
y no lo están entendiendo
muy bien
de qué está pasando.
Pero tendrías que sacar
de react form event
y luego decirle
de dónde viene este evento
de html
form event.
Y en este handle submit
es donde va a pasar
toda la magia
de añadir
este nuevo usuario.
Una cosa interesante
de handle submit
ha cambiado
la documentación
de react
y antes
lo que te decían
es crear
un estado
para guardar
cada una de la información
del formulario
no sé qué
o sea tener
como controlados
los inputs
pero ahora
he visto
que están recomendando
más la forma descontrolada
lo cual me parece
súper bien
y está muy bien
porque es bastante fácil
de hacerlo
puedes recuperar
primero el formulario
del event.target
luego
del formulario
tenemos el form data
y aquí
no tengo ni hija
copilot
entonces me siento
un poco inútil
pero sacamos
el form data
del formulario
ya que ahora
ya podemos recuperar
el name
de form data
get name
y esto
lo tratamos
como un string
aquí el email
de hecho
vamos a hacer esto
y ya
podríamos traernos
el email
y el git hub
para que esta magia
funcione
necesitamos que en el formulario
todos tengan su nombre
por ejemplo
el primero será
el name
será el name
el segundo
name
será el email
¿vale?
y este
el name
será el git hub
estos nombres
que ves aquí
son estos nombres
que estamos utilizando
aquí para recuperar
el form data
o sea que
si le ponemos aquí
pepito
pues aquí
debería ser pepito
también
esta es la magia
con la que puedes hacer
el form git
para recuperar esto
y aquí ya
simplemente llamamos
al add user
le pasamos el name
el email
y el git hub
y con esto
deberíamos ser capaces
de crear un nuevo usuario
vamos a ver si esto funciona
que eso nos ha quedado
esto
picueto
ah fíjate
es que se me está quejando
algo
no machine export
de add user
ah porque
es que esto no devuelve
un add user
esto es el user actions
este
yo también me lo he inventado
aquí
user actions
y esto aquí
es el que tiene
el add user
de user actions
así es como
tengo que llamar
esto es porque
estoy aquí trabajando
sin linter
y sin nada
y se escapan cosas
vamos a ver si esto funciona
midu
midu
arroje mail
punto com
midu dep
crear usuario
vale
porque ha dado este salto
ha dado este salto
porque la idea del usuario
que ahora nos crea
fíjate que es bastante
tocha
entonces es bastante
normal que pase esto
pero crear
ha creado el usuario
o sea ya estamos creando
el usuario
y si refresco
también lo persiste
porque como lo tenemos
a nivel del
el middleware
en nuestra store
como en nuestra store
la tenemos
que cualquier acción
que pase
cualquier acción
que pase
pasa por aquí
y después
de que haya actualizado
el estado
guardamos
en el local storage
el set item
por eso
se está guardando
constantemente
y así que ya
cualquier acción
que hagamos
que modifiquemos
el state
ya lo tenemos aquí
guardado
y persistido
¿por qué ha funcionado
en el prevent default?
buena pregunta
porque no tenía aquí
un action
como no tenía un action
por defecto
seguramente
ha hecho algo ahí
de cualquier forma
pero sí
tendríamos que hacer
aquí un event
punto prevent default
¿vale?
para evitar justamente
el refresco
es como un crude
lo que estamos haciendo
¿no sería mejor
un object from entries?
podría ser
lo podríamos hacer
pero
lo malo del object from entries
en este caso
es que no le podríamos añadir
lo de las string
como necesitamos
tiparlo
aquí en este caso
podríamos hacer así
podríamos utilizar un for
del entries
también para decirle
que todo lo trate
como un string
y tal
o podríamos tiparlo
de otra forma
pero bueno
esto me ha parecido
lo más fácil
a la hora de tipar
para que pueda decirle
que cada uno es un string
y ya está
lo del form data
lo he recomendado ahora

la verdad es que React
está recomendando esto
y ya está
no
con el formulario
no es mejor usar un ref
no
no es mejor usar un ref
en este caso
en este caso
de forma totalmente nativa
sin utilizar un ref
lo que podemos
es recuperar los datos
y lo estamos haciendo
nativo de javascript
sin ningún problema
¿qué es el form data?
el form data
como dice el nombre
tal cual
es sacar los datos
del formulario
le tienes que pasar
el new form data
lo que hace es generar
los entries
del formulario
utilizando el nombre
de cada input
entonces aquí
lo que le pasa es
ese elemento
del formulario
donde tienes que extraer
todo el form data
todos los datos
del formulario
lo que te crea
en estos entries
es una forma
de poder acceder
a cada uno
de los nombres
y recuperar el valor
y ya está
mira
como alguien me pregunta
por manejo de errores
podemos hacer un manejo
de errores
un momento
lo más interesante
de Redux
es que
cuando utilizamos Redux
no tenemos que olvidar
que también tenemos
React
entonces
yo para hacer un manejo
de errores
aquí bastante sencillo
si alguien intenta
hacer algo
con nuestro estado
o sea nuestro estado
con nuestro formulario
yo que sé
voy a hacer algo
sencillo
¿vale?
pero que nos sirva
para ver un manejo
de errores
en un momento
vamos a decir
que tenemos un estado
local
porque no hace falta
que todo lo hagáis global
ahora que sabéis
hacer un estado global
por ejemplo
en este formulario
tiene sentido
que este estado
sea local
¿no?
no hace falta
que todo sea global
¿vale?
entonces
cuando hagamos un submit
podemos decirle
que el set result
lo pasamos a null
que es por defecto
como que no tiene
ni ha ido bien
ni ha ido mal
sino que no tiene ningún error
pero aquí podríamos chequear
¿no?
si no tenemos nombre
o no tenemos email
o no tenemos GitHub
o las validaciones
validaciones que tú quieras
validaciones que tú quieras
y por lo tanto
aquí podrías
en lugar de OK KO
podrías utilizar el string
que quieren mostrar
lo que tú quieras
podríamos decir aquí
pues return
set result
KO
yo lo voy a hacer
bastante sencillo
¿por qué?
si haces un return
ya no seguiría ejecutando
el código
ya no añadiría el usuario
y ya está
entonces aquí estamos
manejando ya
el error de esta forma
aquí sí que podríamos decir
set result
OK
para actualizar
por un lado
el estado global
y otro el local
y además podríamos resetear
también el formulario
podríamos hacer un form reset
que también es bastante buena idea
que esto es un error
también muy común
que no sé por qué la gente
no lo hace
que una vez que enviamos
el formulario
¿veis?
se queda aquí el texto
no tiene sentido
tenéis que
tenéis que resetear
el formulario
¿vale?
entonces reseteamos
el formulario
y con esto
¿qué podríamos hacer?
podríamos buscando aquí
en los componentes
los componentes
que tiene
Tremor
vale
veo que tiene un batch
mira
podríamos sacar el batch
y en el batch
este
vamos a hacer una cosa
esto para que
salga algo
al menos
para que lo veáis aquí
más o menos
justo al lado del button
que tenemos aquí
un crear usuario
podríamos ponerle al lado
un span
¿vale?
le ponemos un span
y vamos a hacer
que si el result
es OK
vamos a poner
un batch
de color green
de color verde
que he guardado
correctamente
para enseñarle algo
¿vale?
¿batch?
¿cómo haces
para que puedas ver
los datos del estado
entre diferentes navegadores
o incluso otros usuarios?
no se puede
a no ser que te lo envíes
no se puede
y no tiene sentido
que lo hagas
lo que sí que puedes hacer
es que si hay un error
te envíe el
¿sabes?
si detectas un error
podrías leer la store
y enviarla
por tema de privacidad
me parece un poco
problemático
pero lo puedes hacer
¿sabes?
podrías decir
hacer un error app boundary
que cuando detecta un error
haces un store.getState
o utilizas el
useAppSelector
que hemos hecho antes
lees toda la store
y la envías
a donde tú quieras
pero entre navegadores
y entre usuarios
verlo
lo único que puedes hacer
es enviar la traza
y ya está
vale
con esto
con esto
ya deberíamos tener
una especie
vale
hay algún error
vale
este no
useState
vale
que no me ha importado
el useState
useState from React
vale
si le doy a crear usuario
vale
error con los campos
y ahora me pongo
a poner cositas
crear usuario
guardado correctamente
y hemos reseteado
el formulario
esto es una forma
bastante sencilla
de tener una
comprobación
bastante
bastante normal
pero que
funciona
funciona
hola midu
hola
como hiciste
para eliminar
la barra
por defecto
devscode
que está
abajo
de los tabs
eso se llama
breakgram
buscas
breakgram
y
esta
breakgram
enable
creo que dices esta
pues breakgram
la desactivas
y ya está
¿cuál es la diferencia
entre context
y redax?
que redax
es para gestionar
estados globales
y context
no
que en context
también lo puedes hacer
pero es que sus utilidades
son totalmente diferentes
context
sería
para
para
tener
accesible
desde cualquier parte
del árbol de elementos
de react
cierta información
que también puede ser
un estado
y de hecho
react
o sea
de hecho redax
utiliza de forma interna
el contexto
a la hora de poder
acceder a las utilidades
de redax
el context
es una forma
que te permite
de poder acceder
desde cualquier parte
del árbol de elementos
a cierta información
no se puede hacer
habilación
mientras escribe el usuario
claro que se pueden hacer
a brixen
que no las hagamos aquí
por tiempo
no significa
no se puedan hacer
pero claro que las puedes hacer
podrías hacer
on change
y que cada vez que hagas
un on change
vas mirando
vas mirando claramente
ahí cada una de las acciones
y ya está
vas mirando el texto
y vas validando
punto
no tiene mucha historia
ahora la complejidad
ahí está
en qué validaciones
haces
cómo las haces
y tal
pero los mimbres
ya los tienes
digamos
de cómo hacerlas
mira
vamos a hacer una cosa
lo de sincronizar
la nueva
base de datos
que me parece
bastante interesante
esto también
para que
hay gente que ha tenido dudas
con lo de middleware
y lo de sincronizar
de base de datos
el tema es que muchas veces
os voy a enseñar la forma
en cómo lo hace
facebook y twitter
que es bastante chulo
si os fijáis en twitter
que a lo mejor no sabíais
mirad
si os fijáis en twitter
si deja de cargar mierdas
cuando
joder
déjame tranquilo
fíjate que le voy a dar click
aquí
le voy a dar aquí
pam
vale
es que va muy rápido
va muy rápido
vamos a hacerlo más lento
vale voy a quitarlo
vale
veis
veis lo que ha pasado aquí
visualmente
visualmente
le ha quitado el like
cuando esto todavía
no había terminado
lo vais a ver ahora
más claro
le da
le voy a dar like
le voy a dar like
visualmente
tenemos ahí el like
vale
tenemos el like
y hasta que no termina
esto realmente
no
no ha guardado el like
o sea
que lo que está haciendo aquí
es como que tienes
dos estados
digamos
tienes el estado visual
del like
y tienes el estado
de la base de datos
¿qué pasa
para el usuario
que es lo mejor?
esto se le llama
una actualización
optimista
optimista
lo que quiere decir
es que
eso me hace sentir engañado
bueno
lo que quiere decir
es que
estamos siendo optimistas
de que todo va a ir bien
de que va a funcionar
y que
le vamos a dar
la impresión al usuario
de que todo ha funcionado
pero que si no funciona
lo que vamos a hacer
visualmente
es hacerle un rollback
no sé si lo habéis visto
alguna vez
a ver
voy a ver si soy capaz
de enseñaroslo
si lo ponemos offline
sin conexión
y le doy
vale
a ver
no lo quita
a veces lo hace
a veces lo hace
a ver ahora
vale
¿veis que lo pone
pero lo quita?
¿veis que lo pone
pero lo quita?
o sea
lo intenta
pero cuando da el error
cuando da el error
dice
ah
voy a hacer el rollback
voy a decir
vale
como ha ido mal
voy a volver
al estado anterior
porque ha ido mal
a esto se le llama
optimistic UI
son actualizaciones optimistas
de la UI
para que el usuario
sienta que todo va muy bien
pero luego en realidad
si funciona mal
pues bueno
le doy rollback
y ya está
pues algo así
se puede hacer
muy fácilmente
con Redux
y a mí me gusta mucho
porque mucha gente
tira muchas veces
de Zangs
y todo esto
para hacer algo
así parecido
y siempre que se pueda
se debería intentar evitar
porque es mucho más importante
que el usuario
en la UI
pues parezca
que todo funciona perfectamente
y luego poder hacer un rollback
y si por lo que sea
no podamos hacer el rollback
pues informarle al usuario
y ya está
por ejemplo
en este
claro nosotros no tenemos Twitter
¿vale?
pero para que os hagáis una idea
de cómo lo podríamos hacer
mira
voy a instalar
otra dependencia
que se llama
Soner
que está muy chula
que es una notificación
no sé si la habéis visto alguna vez
Soner
Soner Notification
está muy chula
vais a ver
qué bien queda
lo que vamos a hacer
¿veis?
son estas notificaciones
que aparecen aquí
aquí
son las notificaciones aquí
pues vamos a utilizar
este componente
que se utiliza súper fácil
y nos va a permitir
enseñarte exactamente
con la sincronización
de base de datos
cómo haríamos algo
como lo de Twitter
esto no es que sea avanzado
pero tampoco es una cosa
que se enseñe mucho
pero bueno
yo creo que está bien
que no estéis viendo
siempre cosas desde cero
y tal
y es un poco algo diferente
a lo que podéis ver
en cualquier lado
así que vamos a darle
que me gusta
venga
primero
en la app
vamos a utilizar
vamos a importar
el toaster
con rich colors
para que se vean bien
los colorcitos
importamos
toaster
de Soner
que es la dependencia
que hemos instalado
la dependencia
que hemos instalado
para las notificaciones
toaster es

toaster
vale
ahora que ya tenemos
el toaster
como ves
tú lo importas aquí
lo dejas ahí
y ya está
te olvidas
vamos a hacer otro
middleware
para que entendáis
del todo los middleware
porque a mí parece
lo más interesante
y lo más poco utilizado
vamos a llamarle
sync with database
lo bueno que tenemos
de aquí
de estos middleware
que por cierto
los middleware
se pueden tipar
que aquí no lo hemos tipado
por no sé por qué
pero te puedes traer
el tipo middleware
de aquí
type middleware
y así lo tipas
vale
y así lo tendríamos
tendríamos la store
el next
y el action
y ahora vas a entender
otra vez
el tema de
cada cual
qué es lo que significa
porque alguien me preguntaba
no he entendido
lo de next action
que se lee literal
es
haz la siguiente acción
que me está llegando
para que aquí te devuelva
podrías tener hasta
el resultado de la acción
pero bueno
esto no es necesario
mirad
primero vamos a tener
aquí un console log
que vamos a tener
el action
y vamos a tener
el state
del store
get state
vale
para ver
qué es lo que devuelve
y aquí tenemos que llamar
el next action
el next es una función
que recibe la acción
que ha hecho el usuario
de nuevo
os voy a explicar
en qué punto estaríamos
ay
he perdido
el flow este
os voy a explicar
en qué punto
tendríamos
la ejecución del middleware
vale
estaríamos
estaríamos aquí
en este punto
vale
estamos recibiendo la acción
y
qué es lo que hace
el next action
pues que
si nosotros
mira
vamos a hacer
vamos a hacer magia
aquí tenemos
nuestro middleware
middleware
vale
esto más pequeño
aquí tenemos
nuestro middleware
es como un peaje
es como que para aquí
claro
estamos llegando
del dispatch
estamos llegando aquí
aquí paramos
y hasta que no le decimos
que para que pueda ir aquí
para que pueda seguir andando
lo que tenemos que hacer
mira vamos a hacer así
para que pueda seguir andando
para que pueda seguir
lo que tiene que hacer aquí
es llamar al
next action
vale
y este next action
sería lo que está haciendo aquí
y este action
este action es el action
que le está llegando por aquí
cuando hacemos el dispatch
esto lo que hace
es el dispatch de la action
con el type
action
con el type
y con
¿ves?
este action que llega aquí
se queda aquí
y hasta
se queda aquí parado
hasta que nosotros le decimos
vale
next action
hasta que nos decimos
que siga
no lo va a hacer
entonces aquí tenemos
el middleware
pero también
una vez que llamamos
este next action
también vamos a tener
el middleware
aquí
¿vale?
también lo vamos a tener aquí
¿por qué?
porque este next action
lo que hace es que ocurra
todo esto que tenemos aquí
y una vez que ocurre
todo eso
volvemos a tener
la ejecución del middleware
y ahora lo vas a ver
más claro
¿vale?
esto sería
mira
te lo voy a poner
con numeritos y todo
para que veáis
madre mía
si no me gano el cielo
con los numeritos ya
yo no sé qué
esto sería el 1
y esto sería el 2
¿no?
pues fíjate
aquí estaríamos
en la fase 1
y aquí estaríamos
en la fase 2
así de sencillo
fase 1
next action
fase 2
o sea que
el código que hacemos aquí
esto es de la fase 1
fase 1
y el código que hacemos aquí
es de la fase 2
porque ahí ya ha ocurrido
la acción
que tenía que hacer
todo lo que ha ocurrido aquí
y ya tenemos el nuevo estado
por lo tanto
el estado que tendríamos aquí
state
el store
punto get state
este
sería
antes
de que
se actualice aquí
y este
sería
después
de que se actualice aquí
porque aquí estamos
en la fase 1
y en la fase 2
ahora ha quedado claro
¿cómo se sabe cuál es la acción?
pues para eso
nos tenemos el
para eso tenemos aquí
esta acción maravillosa
de la acción
tenemos el type
y el payload
y es que fíjate
gracias a esto
vamos a poder hacer
lo que vamos a poder
hacer ahora
se pueden tener
varios middleware
y esto que es amigo
middleware
y aquí
middleware
si es lo que estamos haciendo
justo uno al lado del otro
también cambia obviamente
el orden
en nuestro caso
no es importante el orden
pero puedes hacer
que uno se ejecute
antes del otro
pero claro que podemos tener
más de un middleware
de hecho lo vamos a tener
vamos a persistir
pero también vamos a sincronizar
de hecho fijaos
mira
vamos a poner
voy a poner los cuantos
console logs
más que nada para que lo veáis
console log
console log
de la fase 1
en la fase 1
el console log
del action
es lo mismo
pero bueno
vamos a ponerlo aquí
y este
este middleware
se va a ejecutar
con cualquier acción
así que vamos aquí
voy a borrar
yo que sé
este de aquí
vamos a abrir esto
voy a borrar
a este
al pato
vale
y fijaos que aquí
tengo unos cuantos
console logs
estos console logs
son estos que hemos puesto aquí
me ha llegado
tipo
y tenemos aquí
el tipo de la acción
que es users
barra
delete
user by id
o sea ya tenemos
ya sabemos cuál es el tipo
de la acción que se ha hecho
y además con el payload
o sea
esta información
es oro
porque no solo tenemos acceso
a toda la store
es que también sabemos
cuál es la acción
que ha enviado el usuario
imaginad
playholder
para que lo veamos clarísimo
para que lo veamos clarísimo
vamos a hacer la sincronización
con una base de datos
que sería haciendo un fetch
pero bueno
no pasa nada
playholder
json
este
al final
imaginad que hacemos esto
con un fetch
que tiene sentido
mirad
aquí tiene users
vale
users
vale
pues imaginad
que vosotros decís
vale
una vez que se ha hecho la acción
vamos a mirar
si el type
es igual a
users
barra
¿cómo era esto?
user barra
delete
delete
delete
a user
by id
si es este el tipo
aquí podríamos hacer
lo voy a poner aquí el fetch
a saco
pero bueno
podríamos hacer otro
de otra forma
method
delete
¿no?
method delete
y aquí en users
podríamos borrar
el usuario en concreto
que en este caso
sería el que nos ha llegado
en el payload
en el payload
nos ha llegado el usuario
que queríamos borrar
fíjate
que es este de aquí
y podríamos decir
vale
cuando tú has hecho esto
en la UI
en el estado de la UI
lo que puedes hacer es el fetch
de este
y podemos hacer
ah mira
esto es interesante
si la respuesta ha ido bien
si algo ha ido bien
le decimos que
llamamos el toast
este
que hemos instalado hace un momento
toast
from
sonar
sonar
creo que era
ahora si no se me quejará
vale
que bonito ha quedado
esta imagen
ha quedado bastante bonita
vale
si todo ha ido bien
llamamos al toast success
que además así
le vamos a dar
como un
valor añadido
al hecho de
informar al usuario
de que ha ido bien
pese a que visualmente
ya se lo habíamos dicho
pero bueno
solo para que tú
lo tengas más claro
esta fase 2
la quitamos de aquí
ya lo necesitamos
pero podríamos hacer esto
podríamos determinar
cuál es la acción
que tenemos aquí
de cada uno
de los tipos y tal
bueno
si es del usuario
que ha borrado esto
podríamos hacer esto
esto lo podríamos tener
separado en otro fichero
pero bueno
por ahora vamos a dejar así
y ya está
o sea podríamos hacer esto
esto podemos quitar
esto podemos quitar
y ya está
si el tipo de la acción
una vez que ya ha ocurrido
en la UI
es esta
hacemos esto
ahora os enseñaré más cosas
de qué pasa si va mal
porque vamos a querer
hacer un rollback
ahora lo veréis
vale
ahora lo veréis
vale
pues imaginad
yo que sé
que borramos
este de aquí
vamos a ver si
vale
ha habido un error
vamos a ver cuál es el error
porque
bueno porque hay un error
if rest ok
console error
vamos a ver cuál es el error
porque no me lo ha dejado muy claro
error
vale
a ver
porque es que esto ha ido bien
¿no?
respuesta encabezado
el dirita ha ido bien
el error es
error is not defined
es error
la madre que me trajo
error
vale
ah mira
toast.access
vale
esto es porque lo he puesto yo mal
soner
toast
toast.access
toast.access
pues esto
no hemos hecho bien
¿no?
toast.access
ah amigo
lo he escrito mal
podemos decir
usuario
con el payload
guardado
correctamente
esto lo estamos haciendo solo
no
esto no nos lo mostraríamos
al usuario
¿vale?
pero una vez que veáis esto
es que lo vais a ver
en tantas páginas web
que vais a decir
ah
así como se hace
en Spotify también lo hacen
es que lo hacen en casi todos sitios
porque tiene sentido
venga vamos a guardar
esto por aquí
añadimos este usuario
las dash dash
le doy aquí
¿vale?
vale
no sé si lo ves
usuario guardado correctamente
¿vale?
¿qué ha pasado aquí?
que esto ha hecho
la sincronización con la base de datos
ha guardado bien el usuario
y una vez que lo ha guardado
bueno pues lo que ha dicho es
bueno pues a una vez que lo he guardado
ahora solo lo tengo con el delete
¿vale?
solo lo he hecho con el delete
cuando añade usuario no lo he hecho
lo podríamos hacer exactamente igual
podríamos hacer esto
de que se sincronice
con haciendo un post y tal
pero bueno
ahora mismo
vamos a hacerlo solo con el delete
y te lo dejo como ejercicio
de que tú lo hagas con lo que
con todo
para que lo tengas en cuenta
¿no?
vale pues podríamos decir
eliminar
fíjate
que le das a eliminar
visualmente desaparece
pero mientras está ocurriendo esto
de hecho
mira lo vamos a poner en 3G lento
le doy a borrar
visualmente desaparece
pero esto está en pending
y tarda un rato
en aparecer que se ha guardado
correctamente la base de datos
o sea
hemos hecho que el usuario
visualmente
no lo veas
pero
sí que has visto
que
usuario
ah he puesto guardado
eliminado correctamente
entonces
al menos
la UI
se ha actualizado
de forma optimista
y en la base de datos
lo hemos hecho un poquito más tarde
esto es súper útil
porque es casi siempre
lo que vas a querer hacer
a no ser que
sea algo
realmente importante
que veas
que el usuario
necesita asegurarse
que lo que ve
es lo que hay en base de datos
pero esto
pasa
pasa a veces
porque le puedes dar el feedback
incluso más tarde
como lo estamos haciendo aquí
con el toast
pero imaginemos
que ha ido mal
imaginemos que queremos hacer
un rollback
podemos hacerlo
de un montón de formas
hay un montón de formas
de hacer esta
pero te voy a enseñar
una forma
sencilla
en la que lo podríamos hacer
podríamos ir aquí
en los slides
y podríamos incluso tener uno
que fuese
rollback
yo que sé
podríamos llamarle
deleted user
o rollback user
porque total
rollback user
donde la acción
el payload
que le vamos a pasar
va a ser un usuario
con ID
porque le tenemos que
volver a meter
el usuario con ID
y aquí
pues vamos a
vamos a recuperar
podríamos mirar
si el usuario
vamos a buscar
el usuario
en el estado
porque claro
si ya lo hemos metido
si por lo que sea
ya hemos hecho
un rollback
de este usuario
pues deberíamos evitar
volver a meterlo
no vamos a meter dos veces
vamos a asegurarnos
que si está en el usuario
ya está en el estado
vale
action.payload.id
o podríamos decir
some user
porque esto devuelve
is user already
already
already defined
vale
si ya está el usuario
si el usuario
si user
already defined
si ya está definido
pues no hacemos nada
hacemos un return
y ya está
o podríamos decirlo al revés
si no está definido
el usuario
entonces
lo que vamos a hacer
es meterlo
hacemos un return
state
y metemos el usuario
action.payload
metemos directamente
el usuario
ya está
con esto
pues ya lo tendríamos
hacer un return
de esto
y lo bueno es que
aquí no tenemos que hacer
un return
del state
porque en
reduce toolkit
funciona de una forma
diferente
y ahora veremos
justamente esto
que hemos hecho aquí
que te va a volar la cabeza
pero bueno
por ahora
esto podría ser una forma
de hacer un rollback
del user
así que cuando tengamos
un error aquí
imaginemos
aquí tenemos un error
claro
aquí lo habremos borrado ya
así que lo que tenemos
que recuperar aquí
como podemos
hacer algo
antes de la acción
podríamos tener aquí
el previous state
del store
punto get state
lo podríamos tener
el anterior
el anterior
y el usuario
que hemos eliminado
el usuario a eliminar
o user
to remove
podríamos
del previous state
el users
podríamos encontrar
ese usuario
user id
que sea igual
al payload
esto
lo vamos a meter
dentro del if
porque no tiene sentido
hacerlo fuera del if
porque solo eliminamos
solo nos aseguramos
eliminando un usuario
solo sabemos
que estamos eliminando
un usuario
dentro de este if
si lo hacemos fuera
imagínate
el payload
puede tener cualquier otra cosa
en otra acción
puede ser que estemos
enviando un objeto
en este caso
sabemos que le estamos
enviando el user id
en el payload
cuando estamos eliminando
el usuario
entonces aquí tendríamos
el usuario
que hemos eliminado
y ahora con este user
to remove
podríamos otra vez
hacer pues lo mismo
que hemos hecho
con el dispatch
como tenemos aquí
la store
store punto
dispatch
bueno
puedo decir
si tenemos el user
to remove
porque a lo mejor
no lo hemos encontrado
por beta saber que
store dispatch
y aquí
el rollback user
y le pasaríamos
el user to remove
el rollback user
lo podríamos importar
de aquí
si no me equivoco
porque como no te autocomplete
es un poco más complicado
y aquí
si no ha ido bien
podríamos hacer
throw new error
aquí decimos
error
al eliminar
el usuario
vale
y aquí le
podríamos enseñar
oye
toast punto error
error
error deleting
user
y le decimos
action punto payload
vale
o mira
podremos hacer
podremos hacer
mejor aquí
user id
to remove
esto sería el payload
le vamos a
renombrar
para que
se entienda
mejor
y así
lo podremos utilizar
más semánticamente
la constante
y con esto
ya podríamos hacer
oye
si ha habido un error
cuando lo estoy
sincronizando
con la base
de datos
lo que vamos a decir
es
ostras
pues esto
le voy a hacer
un rollback
el rollback
el rollback
de este usuario
solo va a tener sentido
cuando el usuario
no exista
por lo tanto
es aquí
que vamos a mirar
si el usuario
no está
como lo estamos
eliminando
pues vamos a decir
vale
pues lo devuelvo
para probar esto
podríamos
quitar
yo que sé
me voy a inventar esto
para que esto pete
vale
para que pete
y así lo podemos probar
vale
vamos a ver
vamos a poner
estos ilimitaciones
vale
a ver la consola
rollback user
en el slice
el rollback user
lo tenemos que exportar
que no lo estamos exportando
parece que funciona
hemos encontrado
dos children
con ass
vale vale
está bien
bueno vamos a intentarlo
le voy a dar a eliminar
vale
ves
vale
fíjate lo que ha pasado
se ha eliminado
lo hemos visto
que ha desaparecido
lo hace muy rápido
y luego lo que ocurre
es que como ha dado un error
y te pone ahí
error deleting
ves
vuelve a aparecer
lo volvemos a recuperar
lo podemos hacer
un poquito más lento
no sé si con la red
si le ponemos aquí
sin limitaciones
a ver
3G lento
a ver si vale
nada
es que claro
como peta esto
que podemos hacer aquí
para que pete
vamos a quitar esto
básicamente
es para comprobarlo
para que lo veáis
para que lo veáis
vale
sin limitaciones
y ahora ponemos
3G lento
borramos este
ves
está haciendo la sincronización
con la base de datos
oye
ha habido un problema
borrando esto
pues ahí
ahí lo tienes de nuevo
ahí lo
te lo recupero
hay un montón de técnicas
para hacer esto
porque por ejemplo
aquí es porque estamos
borrando un usuario
pero esto mismo
lo puedes hacer
cuando edites un usuario
puedes recuperar
el estado que tenías antes
y luego
volver a ponerlo
podrías tener hasta
una pila de cambios
en las que
lo que estás haciendo
es ir
apilando todos los cambios
que está haciendo el usuario
y luego hacer un rollback
de cada uno de ellos
o también incluso
mucho más bestia
sería guardar
todo el estado anterior
y luego machacar
todo el estado
con el nuevo
yo eso te lo
te recomiendo
que lo evites
porque es como
demasiado bestia
pero lo que está
súper chulo de esto
es que la potencia
que tienes es tremenda
porque lo que te permite
es que muy fácilmente
tengas una UI
optimista
y
cuando algo
haya ido mal
como por ejemplo
quiero borrar este
oye
ha ido mal
no he podido
no he tenido conexión
ha petado
oye ha habido un error
borrando este usuario
y en la UI
te lo dejo
porque no tiene sentido
como has dejado el estado
por lo tanto
te vuelvo a recuperar
el estado
que tenías antes
para que sigas viendo
ahí la UI
y esto es exactamente
lo mismo
que nos pasa muchas veces
con Twitter
que es lo que comentaba antes
cuando tú
haces un click
ah mira por cierto
he puesto esto
cuando tú le haces un like
y no tienes conexión
pero va a intentar
ves tú le das
claro está con esto
que parece que no carga
esto porque está cargando
la animación
pero no porque esté cargando
el like
pero ves
a lo mejor
no ha terminado
es que no ha terminado
todavía de hacer un favorite
pero te enseña ahí
que ha sido un favorite
entonces tú le das
mira vamos a hacer algo
vamos a hacer algo
vamos a hacer una cosa
3G
a ver
sin conexión
¿veis?
lo he dejado sin conexión
ha petado
y entonces me ha devuelto
cuando yo le había puesto
un like
dice no no no
te lo dejo con el like
porque al final
no has sido capaz
de hacer el like
realmente
o sea de quitarle el like
esto es un poco
una introducción
a React
con Redux Toolkit
lo último que es importante
que sepáis
que lo quería explicar
antes
pero no lo he hecho
es que una de las ventajas
de Redux Toolkit
muy interesante
es que no tenéis
por qué
generar un nuevo estado
sino que podéis
modificar
mutar
el original
¿qué quiere decir esto?
bueno pues que aquí podéis hacer
state.push
y aquí
empujar el nuevo
¿vale?
o sea podéis
mutar
el estado
con Redux Toolkit
¿por qué?
porque utiliza
por detrás
Imer
que ahora te explicaré
lo que es
pero esto lo que hace
es que tú directamente
hagas
puedes utilizar
mucho más fácilmente
el hecho de utilizar
un push
sin necesidad de estar
devolviendo
devolviendo
y generando
un nuevo estado
y esto es súper potente
esto vas a ver
que funciona exactamente igual
si esto
nos lo permite
¿vale?
esto debería funcionar
bueno
esto no va a funcionar
porque justo tenemos
el problema este
que estamos haciendo
lo del
pero yo que sé
si creamos aquí uno
esto funciona exactamente igual
funciona exactamente igual
esto es una cosa muy interesante
y es gracias
gracias y por culpa de
es que sería un poco polémico
pero por dentro
lo que está utilizando aquí
es
Imer
que son
actualizaciones
inmutables
que puedes hacer
esto es gracias
a lo que estamos haciendo
ya está dentro
de los reducers
y todo
no te deje preocupar
pero ten en cuenta
que esto viene con un coste
¿vale?
esto no es gratis
y el coste
por desgracia
es que
Imer
es una biblioteca
que bueno
pues ocupa 5k más
de lo que
sería sin biblioteca
por desgracia
entre Ria Redax
y Imer
que ya son otros 5 más
o sea Imer ocupa más
que Ria Redax
para que te hagas a la idea
esto hace que
ocupe lo suyo
¿vale?
que tenga un poquito
Redax Toolkit
pues quieras o no
pues entre una cosa y otra
pues ocupe
ocupe algo
que en temas de rendimientos
pues tiene su impacto
las cosas como son
no pasa nada
o sea
es solo para que lo sepáis
que esa magia
viene a partir de un coste
y que si ya que estáis
pues que utilicéis una
la utilicéis
lo bueno
es que ahora
en lugar de tener que hacer
estos pedazos de reducers
que tenéis que hacer
ahí a manija
pues se pueden hacer
cosas mucho más sencillas
como hacer un push
o decir
oye
en este índice
pues
le pones el punto don
y ya está
o sea
podéis mutar
estados
y despreocuparos totalmente
de tener que
generar uno nuevo
que muchas veces
es lo que hacía
que Redax
fuese muy complejo
de entender
con Zustan
hacer lo mismo con Umer
se podría utilizar
Imer también
bueno amigo
acabo de empezar
las prácticas de Damm
y me han metido
en un proyecto
de Drupal con PHP
¿podrías darme algún feedback?
que lo disfrutes
Drupal
PHP
tiene mucho trabajo
está súper bien
así que
a mi parece
que lo disfrutes
que aprendas
y que
si luego no te interesa
pues que luego
aprendas otras cosas
ya está
hay otras librerías
tipo Imer
hay un montón de librerías
tipo Imer
la más famosa es Imer
pero hay alternativas
de Imer
es mejor no mutar
el estado de Redax
en este caso
como os estoy explicando
no es que sea mejor
o no mejor
es que si no utilizáis
Redax Toolkit
no es que sea mejor
es que no lo podéis hacer
y no lo deberíais hacer
¿vale?
en el caso de Redax Toolkit
sí que lo podéis hacer
por suerte
porque
está utilizando Imer
por detrás
y en este caso
si estáis utilizando Imer
es incluso aconsejable
que lo mutéis
porque
normalmente
el código que genera
es mucho más corto
y Mutable.js
es otra alternativa
aunque creo que
es bastante más tocha
si no me equivoco
que
que Imer
Imer es
ahora el estándar de facto
¿vale?
¿dónde intercederían
las validaciones
en el server?
pues en el server
¿cuál sería la diferencia
entre los Reducers
y los Extra Reducers?
a ver
son dos cosas diferentes
¿vale?
los Extra Reducers son
como
una forma
de incrementar
los Reducers
que ya tiene por sí mismo
el Slice
que estás creando
¿no?
y que te permiten
responder
a otros tipos
de Action Types
o sea
los Reducers que tenemos
solo responden
a un Action Type
en concreto
los Extra Reducers
sería una forma
de poder responder
a acciones
externas
del propio Reducer
y de una forma
mucha más controlada
o sea descontrolada
poder acceder
y decir
bueno
si he recibido esto
de otra Action
que no tiene que ver
con mi pieza
pues voy a hacer algo
¿por qué?
porque hay veces
que puede ser que
a ver
es que yo intentaría
evitarlo a toda costa
pero bueno
imagínate que tienes
dos Slice
una de Usuarios
y otra que es de Post
por lo que sea
pues podría hacer
un Extra Reducer
pues para
yo qué sé
para que cuando
se lea algo
o cuando
de otro Slice
pues hacer
alguna cosa
en otro Slice
yo lo evitaría
porque me parece
como un poco
regulinchis
el hecho de poder
modificar
y no responder
a una sola Action
y a mí es que
la verdad
es que no se me ocurre
muchos casos de uso
a mí no se me ocurre
pero también es verdad
porque no soy un Power User
de Redux Toolkit
¿sabes?
no lo he usado tanto
como para decir
wow
le veo un caso de uso
súper claro
pero hay veces
que a lo mejor es eso
que quieres un caso
por defecto
en el caso de
un Extra Reducer
podría ser
mira
uno que se me ocurre
sería
en el caso
un caso por defecto
imagínate que no tienes
ninguna acción
que responda
a
o sea
no tienes ningún Reducer
que responda
a una acción
podrías tener
un Extra Reducer
que sería
la acción por defecto
ese es uno de los pocos
que se me ocurre
la verdad
no se me ocurren muchos
no se me ocurren muchos
¿no se podría utilizar
Structure Clone
y mutarlo?
esto hace algo parecido
por dentro
pero obviamente
no es lo mismo
porque
Imer
es mucho más óptimo
que Structure Clone
que puede ser muy costoso
de Structure Clone
porque esto
lo que está haciendo
es construirlo
desde una forma
ya inmutable
desde el principio
entonces
sea diferente
¿tratarías de evitar
Cruelita SyncZunk?
yo
a ver
opinión súper polémica
yo intentaría evitar
todos los Cruelita SyncZunk
y todo esto
yo intentaría sobre todo
gestionar el estado
con Redux
eso puede dar sentido
pero la lógica
y todo esto
sacarla fuera
y no tenerla metida
en mis
en mis
Reducers
ni en Thunks
ni nada de esto
sé que a veces
son necesarios
hoy no los hemos podido ver
porque es que es demasiado
pero
yo intentaría evitar
el problema es que
muchas veces
la gente lo que hace
es meter ahí
muchos Fetch
muchas APIs
y muchas cosas
y creo
que no
no es algo positivo
sinceramente
Redux Toolkey
viene a ser la herramienta
para manejar el estado
del usuario
del login
no
para manejar
estado global
de tu aplicación
puede ser los posts
las búsquedas
puede ser un carrito
de la compra
puede ser el usuario
puede ser cualquier cosa
que quieras que se pueda dividir
o sea que se pueda compartir
en cualquier sitio
¿vale?
bueno amigos
pues
nada
lo dejamos aquí
ahora subiré esto
en el repositorio
os dejo el repositorio
¿vale?
os dejo por aquí el repositorio
para que lo tengáis
lo tengáis controlado
¿qué podéis hacer
una vez que hemos hecho esto?
yo lo que os diría
es intentar editar
el usuario
por ejemplo
que se añadir
editar el usuario
pero podéis ir más allá
cualquier cosa
que se os ocurra
que podáis hacer
por ejemplo
pues podríais intentar
hacer más llamadas
a la API
cuando se crea el usuario
hacer la llamada
a la API
probar
en lo de la UI optimista
¡Gracias!
¡Gracias!