This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Y hoy vamos a hacer dos proyectos, dos proyectos más.
A ver, vamos a volver a tocar el último que hicimos.
No te preocupes si no lo viste porque te lo voy a explicar.
Y vas a ver cuál es la diferencia de lo que vamos a hacer.
Bueno, aquí tenéis todos los vídeos y hoy vamos a hacer una clase más para aprender.
Vamos a hacer paginación, infinity scroll, vamos a utilizar React Query, te voy a explicar.
React Query, para qué sirve, por qué vale la pena.
Y luego vamos a hacer mutaciones también y vamos a gestionar estados globales asíncronos.
Que parece muy difícil, pero es que es muy fácil.
Es muy fácil porque lo hace solo.
Así que nada, no se preocupen.
Ya tengo aquí el proyecto abierto, que es el mismo proyecto que tenéis aquí.
O sea, que si queréis empezar ahora, este mismo proyecto me lo he clonado.
Y aquí tengo todos los proyectos.
Pues el número 12, no, el número 12 no.
El número 12 estaba ya aquí.
Sí, ya está el número 12.
El número 12 lo hacemos después.
Entonces, ahora lo que vamos a seguir es con el 11.
Vais a ver, vamos a seguir el 11, pero un poquito.
No te preocupes si no estabas, no te preocupes, que yo te lo explico aquí en un momento.
El 11 lo hicimos la semana pasada y es que era un proyecto muy chulo, que era una prueba técnica.
Una prueba técnica que además te pagaban 55.000 euros al año de una empresa de aquí de Europa.
Y fijaos que podías ordenar por país, resetear el estado, podías borrar, colorear las filas, dejar de ordenar, filtrar por país también.
O sea, se podrían hacer un montón de cosas.
El tema de esta prueba y viendo un poco el código, mira, te voy a enseñar el código un poco para que veas el tema.
¿Qué pasa con esto?
¿Qué pasa con esto?
Bueno, le faltan unas cuantas cosas, ¿no?
Y entonces vamos a hacerlo, vamos a hacerlo juntos, las cosas que le vamos a meter a esta prueba, porque luego vamos a ver cómo lo podemos mejorar mucho más.
¿Qué es lo que vamos a hacer?
A ver, si miramos un poco la prueba, fíjate que lo primero, pega este salto que nada más entrar está aquí, no te pone nada, que está cargando, pum, y luego sale todo esto.
Luego, además, te carga 100 resultados de golpe, cuando esto no es necesario y sería mucho más interesante que solo cargase 10 y poder tener un infinity scroll o algo así, que le puedas dar a un botón y que te ponga más resultados al fondo.
¿Vale?
Pues esas cosas las vamos a hacer para que vayamos mejorando un poco la experiencia del usuario.
Este es el código, lo hicimos con TypeScript, pero bueno, nada complicado.
Oye, ¿por qué le dice unexpected token?
¿Por qué no le gusta este token?
¿Qué le pasa con ese token?
Type user.
Qué raro, ¿no?
Se le va aquí, bueno, no pasa nada, pero es raro, ¿no?
Es como un problema de parseo, parece del linter.
Es que parece del linter.
Vale, puede ser que haya algo del linter que esté mal configurado.
Ah, es que este no tiene linter ni siquiera.
Vale, vamos a instalarle un momento el linter, testestandard-d, ¿vale?
pnpm install testestandard-d porque es una dependencia de desarrollo.
Vamos a instalarle un momento el linter en el package.json.
Vamos a poner aquí, es lintconfig.
Vamos a poner que extiende, barra, no modules, ts, standard, el linter.json.
Le decimos dónde tenemos parser options.
Le tenemos que decir dónde está el proyecto de TypeScript.
Y con esto ya debería funcionar, ¿vale?
Ahora sí que parece que funciona.
Y, vale, no funciona todavía el linter.
Vamos a ver por qué.
Veis aquí que me da un error que me dice, eh, el linter no está.
Bueno, no pasa nada.
Está bien, porque así vemos cómo lo arreglamos.
Ah, dice, conflicted package.json con el problema del...
Claro, como estoy en un monorepo, ¿qué pasa?
Que como estoy en un monorepo, pues está...
Me está dando un conflicto entre los dos paquetes.
Me da bastante rabia esto de los monorepos, pero bueno, no pasa nada.
No pasa nada.
Lo voy a quitar por ahora de aquí.
Lo voy a quitar de aquí.
¿Ves?
Aquí está este y entonces se está quejando justamente de esto.
Luego me lo miraré para que todos convivan bien,
pero por ahora lo importante es que me funcione aquí, ¿vale?
Ahora dice que no puede aprendiendo reacttsconfig.json.
Ttsconfig.json.
Pero sí que está aquí.
A ver.
Nada.
Esto es por culpa de mezclar en un proyecto TypeScript con JavaScript y tal, ¿eh?
Pero bueno, lo arreglaremos en un momento.
No puede leer el archivo, no sé qué, no sé cuánto.
Aprendiendo reacttsconfig.json.
Vale.
Este sí que ya lo hemos puesto aquí.
Ttsconfig.json.
Vale.
Y usando project, projects, no sé qué, to include, file, no sé qué.
Es que estoy pensando, ¿el test estándar funcionará con todos?
Tenía ROM.
Ah, es verdad.
Puede ser que fuese, pues tenía ROM.
No lo sé.
A ver, si no, lo puedo ignorar, ¿eh?
Un momento.
Y luego lo arreglaré porque igual así dejamos de perder un poco el tiempo con esto.
Sí, es que ya he abierto el proyecto.
Ya he abierto antes el proyecto solo del 11.
Vale, ya está, ya está.
Esto es porque tengo en el mismo proyecto, tengo en algunos el linter de JavaScript y otro el de TypeScript y se está haciendo un poco un lío.
Entonces, claro, para evitarlo, pues tendríamos que ajustarlo bien.
Como hemos ido haciendo todos los proyectos uno detrás del otro, pues no hemos ido adaptando esto.
Lo arreglaré para que no os dé este problema y los tengáis todos arreglados.
Pero claro, lo ideal es que lo podamos arreglar para todos a la vez y no lo que hemos hecho de arreglar uno a la vez.
O sea, uno por separado.
Ya tenemos el linter funcionando.
Lo que he hecho, pues nada, es solo cargar este, abrir solo el editor en este proyecto y ya está.
Este es el código de este proyecto que teníamos por aquí, ¿vale?
De colorear las filas, ordenar por país y tal.
Te explico rápidamente qué es lo que hacía.
Bastante sencillo.
Teníamos un estado para los usuarios.
En el estado guardamos un array de usuarios.
Y lo que hacíamos en un useEffect era hacer un fetching de datos de usuarios random.
Y traíamos hasta 100 usuarios random.
Y aquí teníamos todo esto y todo esto es lo que estamos pintando realmente aquí.
Luego utilizamos otros custom hooks como puede ser el useMemo, useCallback y tal para optimizar el renderizado de nuestra página web.
Vamos a ver qué podemos hacer con esto.
El tema es que en nuestro proyecto que tenemos aquí, como puedes ver, estamos cargando demasiados resultados de golpe.
Son un montón.
Vamos a limitar el número de resultados que vamos a mostrar.
¿Por qué?
Porque los vamos a querer paginar.
Así que aquí que teníamos resultados 100, vamos a ponerle solo 10, ¿vale?
Solo ponemos 10 resultados y si volvemos, ¿ves?
Ahora solo carga 10.
Ya no hay más scroll.
Perfecto.
Ahora que tenemos esto, vamos a mejorar también la experiencia del usuario.
De que podamos mostrarle cuando está cargando.
Porque nada más entrar, fíjate que pega un salto, pero no se ve que esté cargando ni nada.
Así que mira, lo primero, en el index.css, creo que aquí debe haber un center en algún sitio.
Este de aquí.
Vamos a poner solo que justifique horizontalmente el contenido, ¿vale?
Para que no pegue ese salto.
Eso es lo primero.
Pero luego fíjate que aquí no tiene nada que renderizar y luego puede ser salto súper raro y tal.
Te voy a enseñar cómo hacer estados de carga cuando hago llamadas asíncronas, que es bastante sencillo, pero luego lo mejoraremos.
Lo importante es que necesitamos, por supuesto, un estado.
Así que setLoading, useState.
Lo vamos a poner por defecto false, porque nada más entrar hasta que no llega al useEffect, no estamos haciendo la llamada, ¿vale?
Y luego vamos a poner también una de error.
SetError, useState, false, ¿vale?
Tenemos ya un estado de carga y otro de error.
¿Dónde tenemos que cambiar esto?
Pues lo vamos a cambiar cuando hacemos la llamada.
Justo antes de hacer el fetch, le decimos que el setLoading pasa a ser true.
Y el setLoading deja de estar encargando cuando termine la promesa.
Lo vamos a poner aquí.
Aquí nos falta un puntito.
Esto no sé si lo conocías.
Hay gente que no lo conoce, hay gente que sí, pero las promesas tiene tres métodos que le puedes concatenar.
Una, el punto then, para cuando se resuelve la promesa.
El catch, para pillar los errores.
Y luego tendrías el finally, que se ejecuta siempre.
O sea, se ejecuta después de se haya resuelto o hayas tenido un problema.
Tienes el finally, que está súper chulo, porque lo que hace es que dice, bueno, pues ya está.
Y aquí lo tendríamos que pasar a false.
Así que si tenemos el setLoading lo pasamos a true y finally lo pasamos a false.
¿Por qué?
Porque si no tendríamos que repetir esto aquí y esto aquí.
Y en lugar de repetirlo dos veces, pues lo dejamos solo en un sitio.
Esto es una cosa que te va a servir en cualquier tipo de promesa que vayas a gestionar en tu vida.
¿Ok?
Así que tenlo en cuenta, porque mucha gente no conoce el método finally y es súper útil con las promesas.
¿Cómo se haría con Async Await?
A ver, siempre la misma pregunta de, ¿cómo lo harías con Async Await?
Pero es que es lo mismo.
Pues try, catch y aquí tendrías finally.
Ya está, será lo mismo.
Esto sería así, esto sería así, esto tendrías que poner esto aquí.
Y en el catch pondrías la parte del catch, que en este caso pondrías esto y tal, y ya está.
¿Cuál es mejor?
No hay una mejor que otra.
Depende de lo que queráis hacer.
Creo que a veces se abusa mucho de la Async Await y es un poco peligroso porque puede parecer que queda mejor,
pero a veces queda mejor porque os estáis saltando el control de errores.
Así que tened cuidado, ¿vale?
Esto es un poco raro porque esto no debería estar aquí.
Este Async Await no sé por qué se puso así, pero esto con esto...
¡Ah!
¡Ostras!
Dice, function the return problem must be Async.
¡Hostia!
Curioso.
Polémico también, ¿eh?
O sea, esto lo ha hecho automáticamente el linter.
Lo ha hecho el linter, ¿eh?
Lo ha hecho el linter.
Vale.
Pues ya tendríamos los estados de carga.
Vámonos ahora al tema este del loading.
Vamos a gestionar mejor esto.
Estos comentarios que habíamos puesto los vamos a quitar porque ya no necesitamos.
Y aquí vamos a mejorar un poco esto.
Vamos a decir, por ejemplo, si estás cargando, pues ponemos el cargando.
Si no estás cargando pero tienes un error, entonces vamos a poner que ha habido un error.
Si no tenemos usuarios que ya no están cargando y además no tiene un error y los usuarios, la longitud es cero, vamos a poner que no hay resultados.
No hay usuarios, ¿vale?
Y luego finalmente, si tenemos usuarios, ¿vale?
Si no está cargando, no tenemos un error y tenemos usuarios, lo que vamos a hacer es renderizar esto.
A ver, esto se puede hacer de otras formas, ¿vale?
Esto lo estoy haciendo para que lo veáis muy claro de lo que hace en cada punto, pero lo podríais hacer de otra forma, lo podríais gestionar mejor en un componente.
Esto es para que veáis lo que queremos hacer en cada paso, ¿vale?
Si está cargando, si no está cargando pero tiene un error, si no está cargando no tiene un error y no tenemos usuarios.
Si no está cargando no tiene un error y sí que tenemos usuarios, entonces mostramos el componente con la lista.
Esto es lo que queremos hacer.
Lo podríamos gestionar desde un componente y seguramente quedaría un poquito más limpio.
Y además podríamos hacer early return, o sea, podríamos hacer si loading, return, esto.
Y así sería mucho más fácil hacer los siguientes.
Entonces, ahora fíjate que cuando entramos y tenemos el cargando, o sea, que ahora funciona mucho mejor y da como un poquito de mejor sensación, ¿no?
O sea, al menos sale un cargando que tampoco es que es verdad que se vea mucho rato porque va muy rápida la página web, ¿vale?
Pero al menos tenemos algo.
Ya tenemos una gestión del loading que nos está ayudando un poquito.
También podríamos hacer el, probar el throw.
O sea, podríamos aquí hacer throw new error.
Error forzado.
Vamos a forzar aquí un error.
¿Ok?
Esto no va a llegar a este código, pero aquí le importa.
Y aquí, ¿ves?
No hay usuarios.
¿Vale?
No hay usuarios porque, vale, en el catch no lo hemos hecho el set error.
Así que metemos aquí el error.
Y luego aquí, cuando, antes de volver a hacerlo, vamos a poner que set error pasa a ser null.
Quitamos el error.
¿Vale?
Aquí nos dice que, bueno, pues ponemos false.
Vamos a poner false.
Y aquí en el set error veremos qué es lo que nos enseña.
¿Vale?
Ahora, cargando y cuando llega ha habido un error.
¿Por qué ha habido un error?
Porque yo aquí en esta línea estoy haciendo un throw de un error.
O sea, lo estoy lanzando yo directamente.
Aquí, ¿cómo es la forma correcta de mirar esto?
Hay mucha gente que aquí se confunde y aquí no lo estoy haciendo y es bastante interesante.
En el fetch, que es para hacer peticiones asíncronas a URLs, el tema para ver si tienes un error a la hora de hacer la petición no es esta.
No es esta.
Esta no es la manera correcta de tratar errores.
A ver, esta es la manera correcta de captar los errores que hayas tenido en el fetch en el sentido de que hayas perdido la conexión y tal.
Pero para realmente ver si has tenido problemas en el fetch, tendríamos que hacerlo aquí.
¿Vale?
Si no es ok, si la respuesta no es ok, o sea, que el status code es mayor a 299, entonces tenemos que hacer un throw del error de la petición.
¿Vale?
Se mira ahí.
No sé por qué.
Esto no lo mira mucha gente, pero es la forma correcta.
¿Vale?
La forma correcta sería aquí.
En el res.key, aquí miramos si la respuesta no es ok.
Lo pueden mirar fácilmente aquí.
Mira, res.key y res.status y res.status.text.
Vais a ver esto, que cuando hacemos la petición, si miramos en la consola, ¿ves?
Tenemos res.key es true, status code 200 y el status text es vacío.
Pero si esto fuese un error, por lo que sea, ¿vale?
Imagínate, yo qué sé, si ponemos aquí, me invento el endpoint, ahora debería petar.
Y ves, me pone res.key es false, ha dado un 404 y el status text es vacío.
Entonces, la forma correcta con el fetch de ver si te ha fallado una petición asíncrona es con esta línea de aquí, ¿vale?
¿Qué pasa?
Que mucha gente utiliza axios y axios sí que lo gestiona con el catch.
Haced la diferencia, solo que lo tengáis en cuenta, porque si no, la podéis liar para mí.
Pero bueno, esto lo hemos hecho para forzar el error, ya hemos visto que lo de los errores funciona, lo vamos a arreglar, vamos a hacerlo en res.key por si acaso, miramos aquí y ahora todo funciona correctamente.
¿Estás seguro que axios gestiona el res.key?
Sí, lo gestiona de forma interna.
Lo que esto, os lo voy a escribir en un momento en axios para que lo veáis, pero básicamente en axios directamente pondríais el catch.
Y aquí ya teníais el error, porque de forma interna ha gestionado la línea esta, ¿vale?
Así que esa sería la diferencia.
Vamos con la paginación y el infinity scroll.
Para hacer la paginación, que ahora tenemos los 10 resultados, lo primero que deberíamos necesitar es otro estado.
Otro estado que le vamos a poner current page y set current page.
Y aquí vamos a tener el user state y vamos a empezar con el 1.
Esto le vamos a poder pasar el query param aquí al random user.
Pero os voy a explicar un momento esto, porque este random user, que es una API muy chula, que os recomiendo si tenéis que hacer cualquier proyecto o practicar o lo que sea, está muy bien.
Pero en la documentación te explica una cosa muy curiosa y es esto de seeds.
Seeds significa semilla.
Y este concepto en programación de semillas lo que quiere decir es para cuando haces algo aleatorio, tener una semilla es para que siempre hagas eso aleatorio a partir de la misma semilla.
¿Y por qué es esto importante?
Bueno, porque fíjate que tú cada vez que entras a la API, si yo voy refrescando, ¿ves que siempre van cambiando los nombres?
Cada vez que lo refresco, pum, pum, pum, van cambiando los nombres.
Y el tema de la semilla, vamos a poner seed midudev.
La semilla lo que hace es que ahora siempre es el mismo nombre.
Utilizando la misma semilla, está de forma aleatoria, ha generado esto, pero como sabemos las semillas, siempre vamos a generar lo mismo.
Así que es importante que en este caso, que como es aleatorio lo que hace, le pongamos una semilla, ¿vale?
Así que así siempre tendemos los mismos resultados.
Y tiene sentido porque ahora cada vez que refresquemos aquí, siempre vemos los mismos resultados.
Pues tenemos luego la paginación, ¿vale?
La paginación la tenemos por aquí y nos dice que tenemos que ponerle el número de la página y ya está.
Pues eso es lo que tenemos que hacer.
Así que vamos a ello a ver cómo lo podemos hacer.
La paginación.
Vamos a añadir aquí un botón.
Vamos a poner aquí un botón, un button, un click, ¿vale?
Vamos a poner aquí cargar más resultados y que esto sea set current page, page o current, current page más uno, ¿vale?
Current page más uno.
Esto solo lo mostramos si no estamos cargando y no hemos tenido un error, ¿vale?
Porque no tiene sentido que mientras carguemos enseñemos el botón y que encima la gente le ve.
Y ya está.
Así que esto lo tenemos así.
Enseñamos este botón y vamos a subir la página un número más, ¿vale?
Como si fuese un contador.
Así es fácil.
Ahora bien, ¿qué tenemos que cambiar aquí?
Pues en el useEffect este, lo que tenemos aquí en las dependencias es que, claro, esto ahora lo vamos a querer ejecutar cada vez que cambiamos la paginación.
Así que cada vez que cambie el current page vamos a querer que de nuevo vuelva a paginar.
Así que ahora aquí el page le vamos a poner current page, ¿vale?
Entonces, ¿qué va a ocurrir con esto?
Lo que va a ocurrir es que nada más entre en nuestra página web, en el primer efecto que se ejecuta, porque ya sabéis que el useEffect la primera vez que se ejecuta es al montarse el componente.
El current page va a ser uno.
Entonces va a hacer esta petición con la página uno y hará todo esto que tenga que hacer, ¿vale?
Y lo encontrará.
O sea, que esto funcionar, debería funcionarnos exactamente igual.
Si refresco, ¿ves?
Entonces funciona perfectamente.
Solo que ahora me ha puesto, no sé si lo verás, pero si no lo subo un poquito para arriba, me ha puesto este botón de cargar más resultados.
Pero ahora fíjate que vamos a tener un problema.
Y es que cuando le doy al cargar más resultados, se refresca todo, ¿vale?
Lo que ha hecho es quitarlos, quitarlos y volverlo a ponerlos.
¿Por qué?
Porque aunque está paginando, mira, vamos a mirar la network, vamos a mirar la red.
Aunque está paginando, o sea, yo le voy a cargar más resultados, ¿ves?
Está paginando porque está cargando nuevos resultados.
Pero el problema que tenemos aquí, ¿ves?
Ha ido a la página dos, la página tres, es que los está machacando.
Bueno, no pasa nada, pero el problema es nuestro.
¿Por qué?
Porque en esta línea lo que estamos diciéndole es, vale, cada vez que hago un fetch, voy a recuperar los resultados.
Que lo tenemos aquí cuando se resuelve la promesa.
Tengo aquí los resultados.
Y lo que hago es machacar los resultados que me han llegado.
Esto no es lo que queremos hacer.
Lo que queremos hacer es que se vayan concatenando.
Así que vamos a calcular con el estado previo que teníamos de los usuarios.
En lugar de machacarlo, vamos a concatenar el estado, o más que prep state, voy a poner prep users.
Los usuarios anteriores que teníamos, los vamos a concatenar.
Y esto es un método de los arrays que lo que sirve justamente a juntar dos arrays, ¿no?
Y lo que te está haciendo es, pues, concatenarlos.
Vamos a concatenarle los resultados, ¿ok?
Por ahora vamos a dejar así y vamos a ver ahora si esto funciona.
Volvemos aquí, le damos a cargar más resultados.
Vale, y me ha vuelto a petar.
No me ha hecho lo que tenía que hacer.
¿Qué ha pasado?
¿Qué ha pasado aquí?
Vamos a ver qué ha pasado aquí.
Me está haciendo...
Ah, vale, vale.
Vale.
¿Qué está pasando?
Vale, vale.
Ahora ya decía yo.
¿Qué es lo que está pasando?
Están pasando dos cosas, ¿vale?
Están pasando dos cosas.
Lo primero es el tema del loading, ¿vale?
Lo primero es el tema del loading.
El tema es que este loading, lo que está pasando aquí es que como estamos cambiando el estado a loading cada vez que se ejecuta este efecto,
fíjate que lo que estábamos haciendo aquí es que aparece lo de cargando.
Por eso, claro, ya decía yo, por eso está haciendo como ese salto.
Pero sí que los está cargando, en realidad.
Sí que podemos ver que los está cargando.
Lo que pasa es que ese momento es porque está desmontando el componente y lo está volviendo a montar.
Esto es súper importante porque esto es un error muy típico en React.
Mucha gente lo comete.
Yo lo acabo de cometer y, bueno, no pasa nada.
Pero mira, fíjate.
Yo cambio la paginación cuando le doy al botón.
Se cambia el valor de esto y el problema es que estoy cambiando tanto este valor como este valor.
Esto hace que cambie el estado, vuelva a renderizarlo y al llegar aquí, fíjate que tiene el loading y pone cargando.
Entonces, se carga esto, pero este no entra.
A este no entra.
Por lo tanto, esto lo desmonta.
¿Qué quiere decir desmontar?
Quiere decir que no renderiza este componente de user list.
Por eso vemos que desaparece de la vista.
Pero fíjate que da como un salto súper grave.
Y el problema de desmontar un componente es que esto tiene un impacto no solo a la experiencia del usuario, como estamos viendo,
sino que además también tiene un impacto en el rendimiento.
Aquí, lo que vamos a hacer aquí en este caso es que vamos a evitar, mira, vamos a cambiar esto.
Vamos a poner esto arriba, que tiene más sentido.
Vamos a ponerlo aquí.
Da igual si está cargando o no, porque a nosotros lo que nos importa es que si tenemos más usuarios,
o sea, si tenemos usuarios que mostrar, los mostramos.
Independientemente si está cargando o no.
Porque ahora sabemos que el estado de carga puede venir después.
Puede venir aunque tengamos usuarios.
Así que ahora sí, si guardamos esto, ¿vale?
Y ahora le damos a cargar más resultados, ¿vale?
Puedes ver que ahora sí que los está concatenando.
Y el cargando aparece, pero aparece aquí.
Aparece muy poco.
Pero ves, ha aparecido el cargando y los va poniendo justo debajo.
Está paginando, porque estamos poniendo aquí, como si fuese un Infinity Scroll.
Estamos paginando en cada una de las páginas.
De hecho, lo vamos a hacer esto a ver si soy capaz.
¿Ves?
Estamos ya en la página 6.
Página 6 y tal.
Y ahora sí que está funcionando correctamente.
Lo que hemos hecho es asegurarnos que el componente UserList no lo desmonta nunca,
aunque cambie el estado, ¿vale?
Voy a limitar la red para verlo más despacio.
Vale, os lo enseño, ¿eh?
Os lo enseño con lo de la red para que lo veáis.
Pero bueno, básicamente le voy a dar aquí.
Vais a ver que sale cargando, ¿ves?
Descargando y cuando termina de cargar.
La verdad, esto que hemos hecho, esto lo utilizan un montón, pero un montón de páginas web a la hora de paginar y enseñarte más resultados.
Ya puede ser que utilicen algún tipo de custom hook para detectar el final y que entonces te los carga automáticamente.
Para esto podríamos utilizar un Intersection Observer.
Pero sería una forma bastante correcta de hacerlo y no nos estaremos complicando nada.
Vamos ahí paginando, vamos enseñándolos, se van concatenando y ya lo tendríamos.
Tendríamos que cambiar alguna de las cosas, por ejemplo, aquí el Original Users.
Aquí deberíamos poner, por ejemplo, esto lo podríamos hacer dentro del custom hook.
Hay de custom hook, de la actualización del estado, ¿vale?
Podríamos tener new users, estos son los prefusers concat resresults, estos nuevos usuarios que serían todos porque estábamos concatenando los antiguos con los nuevos.
Y esto sería lo que tendríamos que devolver para actualizar el estado.
Y con esto pues ya lo tendríamos.
Y tendríamos aquí nuestro estado de carga y estaríamos cargando resultados como si hubiera mañana.
Fácil y rápido.
Bueno, es necesaria la validación si no está cargando cuando mostramos el error, ¿no?
Bueno, a ver, lo que pasa es que como hemos puesto aquí justamente el loading y el error, sí que lo podríamos quitar.
Podríamos quitar esto de, si tiene un error, pues que muestre el error y ya está.
Esto lo podríamos hacer así.
Si no tiene usuarios, esto igual, ¿no?
Que si no tiene usuarios también lo podríamos hacer.
Si no tiene error, no tiene usuarios.
Podríamos hacer ahí unas cuantas cositas, ¿vale?
Ya tenemos todo lo que es el infinity scroll y todo esto.
Te voy a enseñar una refactorización para que mejores tu código.
Porque muchas veces una cosa que nos pasa es que dejamos los códigos así y...
¿Cómo hacerlo sin botón?
Sería muy fácil.
Mira, podrías utilizar este custom hook.
Lo que pasa es que no lo voy a hacer porque si no, no me va a dar tiempo a terminar la clase hoy.
Y estaría aquí todo el día.
Pero puedes utilizar este custom hook que detectaría cuando llegas al final y hacerlo automáticamente.
Yo la verdad es que hacerlo automáticamente no recomiendo siempre que lo hagáis.
Es porque la experiencia a veces es un poco ñe, pero bueno, que lo tengáis un poco en cuenta.
Utilizáis este custom hook, le decís, use intersection of server, le decís en qué elemento tienes que detectar que ha llegado al final o que sea.
Y ya está.
Cuando sea visible, pues ejecutad lo que quieras y ya está.
Esto lo puedes hacer en el use effect y ya está.
Fácil.
Fácil y rápido.
De hecho, tengo un vídeo por ahí que lo hacemos.
¿Ves?
Aquí lo hicimos.
En este lo hicimos.
En este lo hicimos.
Para el tema de los GIF que tenía sentido porque era justamente lo mismo.
Muy bien.
Pues ahora que ya tenemos todo esto, vamos a refactorizarlo y así podremos empezar con React Query que es bastante chulo.
Y que vas a ver cómo simplificamos muchísimo el código.
Mira, lo primero que vamos a hacer, voy a sacar aquí una función que voy a llamar fetch users.
Que se le pase la página, que es un número.
Y este fetch users es justamente esto que hacemos aquí.
Pero ojo con esto porque esto es un error que mucha gente hace y que yo recomiendo que no cometáis.
¿Vale?
O sea, si vais a extraer una función que se hace en peticiones a una app y bla, bla, bla, bla.
No pongáis aquí dentro las actualizaciones del estado.
¿Vale?
No pongáis aquí un set, resolves, no sé qué.
No le paséis por parámetro el actualizar el estado.
No tiene por qué saberlo.
Lo importante es que esto devuelva a los usuarios que queréis traer.
Punto.
Ya está.
No necesitáis otra cosa.
O sea, que no le paséis un parámetro para actualizar el estado.
Hacedlo al revés.
La actualización del estado la podéis hacer dentro del componente.
Así que tendríamos aquí, en lugar de ahora hacer todo esto que hacíamos aquí, vamos a tener esto así.
Fetch users, punto den, users y ya está.
Tenemos aquí los usuarios, users, fetch users y a esto hay que pasarle la página que era el current page y ya está.
Vale.
Ya hemos pasado, ya hemos hecho un refactor sencillo.
Vemos que todo funcione bien, que no lo hemos liado.
Vale.
Voy a quitar esto para que vaya sin limitaciones.
Ha habido un error.
Vale.
Pues sí que la he liado.
Current page is not defined.
Vale.
Porque aquí esto es page, que le he cambiado el nombre.
No sé por qué le he cambiado el nombre.
Vale.
Pero ya funciona perfecto, cargando resultados.
Venga.
Primera refactorización hecha.
Siempre que refactoricéis, no esperéis a...
Lo mejor sería tener test.
Pero no esperéis a hacer todos los cambios para ver si las cosas siguen funcionando, que os conozco.
Bueno, al menos ya tenemos esto aquí, que lo hemos separado.
Vamos a seguir refactorizando y lo vamos a refactorizar llevándolo a otro nivel, ¿vale?
Para ello vamos a utilizar una cosa que se llama Tanstag Query, o se llama React Query.
Lo puedes llamar como quieras, aunque ahora el nombre oficial es Tanstag Query.
Pero mucha gente lo conoce de forma histórica como React Query.
¿Qué pasa con React Query? Es una forma de manejar estado asíncrono que funciona en React, en Solid, Svelte, con TypeScript, con JavaScript, con lo que sea.
Tienes otras alternativas que también puedes probar.
Entonces, no me empieces a llenar en el chat, ¿por qué no SWR? ¿Por qué no Redux Query?
¿Por qué?
Porque hay un montón, ¿vale?
Hay un montón de alternativas que son muy similares.
Te pueden funcionar igual de bien.
Lo importante es que cosas que aprenderás en una te pueden servir en la otra.
Hay bibliotecas que sirven exactamente para lo mismo.
En este caso, vamos a utilizar Tanstag Query, ¿vale?
Tanstag Query es muy importante esto porque mucha gente se cree que es simplemente una biblioteca para hacer fetching de datos.
Y no es eso.
No es eso.
No tiene nada que ver.
De hecho, podrías no hacer fetching de datos con Tanstag Query.
Tanstag Query es una biblioteca para manejar estados asíncronos.
Punto.
Eso es lo que es.
Lo que pasa es que, ¿cómo trabajamos con estados asíncronos normalmente?
Pues haciendo una petición a una API.
Por eso normalmente utilizamos, parece que están muy relacionados, ¿ok?
Pero ten en cuenta que no es para hacer peticiones de datos.
Manejo y administración de estados asíncronos.
La documentación no está mal.
Tampoco es para tirar cohetes.
Pero bueno, al menos sí que tienen algunos ejemplos por aquí.
No te preocupes porque nosotros vamos a hacer un ejemplo desde cero, poco a poco, y ya está.
Y vas a ver que lo simplifica mucho y hace que no necesites cosas como Redux.
¿Vale?
Esto hace que elimines la necesidad total de utilizar.
Bueno, total no, pero te quita mucho del uso de Redux.
Y lo vas a ver, que es muy interesante.
Porque te da un estado global, te da persistencia, te da facilidad de evitar hacer llamadas asíncronas dos veces.
O sea, un montón de cosas.
Y es una maravilla utilizarlo.
Mira, vamos a hacerlo poco a poco y vas a ver todas las ventajas y todas las mejoras que tiene.
Mira, vamos a instalar aquí pp install, tanstack, barra, reacquery.
De nuevo, tanstackquery piensa que se puede utilizar con Svel, por ejemplo, y con otras bibliotecas.
Lo instalamos como una librería exacta, con la versión exacta.
Vale, ya la tenemos instalada.
Lo primero que tenemos que hacer, como tiene un estado global, pues va a tener que utilizar un contexto.
Así que si utilizan contexto, necesitamos un provider.
Lo primero, importamos el query client provider.
Y esto lo hacemos de tanstack reacquery.
Y este provider es el que va a envolver nuestra aplicación.
¿Vale?
Los providers en reac, ¿qué es lo que hacen?
Pues lo que hacen es que lo que envuelven le está inyectando normalmente un contexto, cierta información para poder acceder dentro de los componentes.
Y es justo lo que está haciendo.
Vale, fíjate que ya se me queja.
Se me dice, oye, que esto le falta algo.
Me dice que la propiedad client falta.
Por cierto, si no tienes esta extensión de TypeScript, te la recomiendo un montón.
Normalmente los errores de TypeScript se ven así.
¿Vale?
¿Ves que se ve así?
Pero si bajas, mira qué bonita se ve esta.
Se lee mucho mejor y es mucho, mucho más fácil de entenderlo.
Fíjate que tienes la flechita y dice la propiedad client, falta en el tipo children element, pero está requerido.
Entonces, se lee mucho mejor.
Así que te la recomiendo un montón la extensión.
Se llama TypeScript Pretty, ¿me parece?
Pretty?
Pretty TypeScript.
Es esta.
Está súper chula.
Vale, nos falta un cliente.
Para crear el cliente nos traemos query client y lo creamos aquí.
Vamos a poner aquí client igual new query client.
Lo creamos así.
Aquí podríamos aceptar pues algunas opciones y algunas cosas.
Nosotros no vamos a utilizar, pero si le quieres echar un vistazo a la documentación de todas las oportunidades que tienes ahí,
pues que lo sepas que lo puedes utilizar.
Vamos a llamarle query client y se lo pasamos aquí.
¿Vale?
Como cliente en las props query client.
Esto sería la configuración mínima que necesitáis para empezar a utilizar React Query o Tamstack Query, como le quieras llamar.
¿Para qué sirve realmente Tamstack Query?
¿Qué nos va a quitar?
Pues nos va a facilitar y nos va a simplificar un montón del código que teníamos aquí.
Lo primero que vamos a hacer, pues importar el hook use query de Tamstack React Query.
¿Vale?
Y este use query lo vamos a utilizar por ahora, lo vamos a poner aquí.
¿Y cómo funciona el use query?
El use query necesita como mínimo dos parámetros.
Uno, que sería la key, que se lo tenemos que decir en forma de arrays, ¿vale?
De un array.
Esta sería la key.
No es una cadena de texto, fíjate que se me queja.
Sería la key, se la tenemos que poner con un array, ¿vale?
Así que se la ponemos así.
Con un array le ponemos la cadena de texto users.
¿Por qué un array?
Porque en realidad puedes seguir poniéndole más cosas.
Por ejemplo, el current page se lo podrías poner para indicar que esa query tiene el ID que es de users de la página 1, de la página 2, de la página 3.
Aunque ya verás que esto no tiene mucho sentido.
¿Vale?
Esto es como para identificar la query.
Y verás más adelante que es importante identificar la query porque las queries se cachean.
Y por lo tanto, cuando se cachean y además te las mantienen en un estado global, va a utilizar esta ID para que seas capaz de recuperar esa información desde cualquier sitio.
Así que eso es una de las cosas para las que necesitas la ID.
Y además de la ID, necesitas indicarle cómo tiene que recuperar la información.
Mira, le tienes que pasar un método, una función, que le indica cómo tiene que recuperar la información.
Por ahora, le vamos a decir que tenemos esta función aquí y vamos a poner fetch users.
Y le vamos a pasar la página 1.
Le pasamos la página 1.
Luego veremos cómo hacemos la paginación con React Query.
Pero por ahora, lo único que quiero es que esto funcione.
¿Qué nos devuelve useQuery?
Pues esto nos devuelve un montón de información.
Por ejemplo, nos devuelve si está cargando.
Nos devuelve si ha habido un error.
Nos devuelve los datos.
¿Vale?
Ya tenemos tres cosas.
Y estas tres cosas, fíjate, que hace que podemos quitar este estado, este estado y este estado.
Ya quitamos tres estados.
¿Por qué?
Porque internamente useQuery ya está cambiándolo cuando está haciendo el fetching de datos y tal.
Luego veremos que hay todavía más.
De hecho, hay un montón de información que podríamos sacar del useQuery.
Pero bueno, al menos ya tenemos ahí alguna información.
Nos está diciendo que no lo estamos utilizando.
Es totalmente normal.
Vamos a ver cómo lo podemos traer.
En lugar de utilizar loading y todo esto, pues lo vamos a poner aquí.
Aquí vamos a poner en lugar de users.
Vamos a sacar el users.
Hay que sacarlo de data.
Vamos a cambiarle el nombre a users.
Vamos a decir que por defecto sea un array vacío.
Data será users porque es lo que devolvemos justamente en el fetch users.
Y el isLoading este, vamos a cambiar por aquí.
IsLoading.
Lo cambiamos aquí.
Lo cambiamos aquí.
Aquí el isError.
Aquí el isError.
Vamos a cambiar ahí el nombre.
Y por aquí, fijaos aquí que teníamos un montón de cositas que hacíamos el fetch cada vez que cambiaba el current page y todo esto.
Bueno, pues todo esto lo vamos a eliminar también.
¿Por qué?
Porque la gestión, el fetch y todo esto ya lo estamos haciendo directamente aquí.
Ya de forma interna, ya está haciendo la petición y luego veremos cómo cambiar y hacer la petición cada vez que encaminemos la página.
Pero por ahora no necesitamos ya un efecto.
Este efecto se va fuera.
No necesitamos cambiar el loading.
Todo esto ya lo hace de forma interna.
Y ya está llamando a la petición cuando lo tenga que cambiar.
Vamos a quitar por ahora estos, que no los vamos a editar.
¿Vale?
Y que esto era por cómo funcionaban antes el delete y eso.
Por ahora los quitamos.
Y el original users también.
Pues lo vamos a quitar por ahora.
Vamos a quitar por ahora esto.
Y ahora mismo lo único que queremos ver es que siga funcionando como esperamos.
Vale, aquí dice que users puede ser...
Ah, que tiene el filtro de que users es...
Vale, que es any.
Podemos tiparlo, ¿vale?
No hay ningún problema.
Aquí podríamos decir que esto es user.
¿Era user?
Sí, user.
Y que es un array de users.
Y así lo tendremos tipado.
Y ya no se me quejará de que esto es any y tal.
Sino que ya cuando usemos user ya lo detectará correctamente.
Bueno, pues con este cambio todo lo que hemos hecho...
De hecho, mira, vamos a hacer una cosa.
Para que veamos el antes y el después.
Esto es para que veamos luego las diferencias y los podamos comparar, ¿vale?
Vale.
Pues nos hemos quitado el useEffect.
Hemos quitado tres estados.
Y ya tenemos esto aquí.
UseQuery.
Aquí le estoy indicando el tipo.
Le estoy diciendo la key de lo que estoy intentando cargar.
Users, puedes poner el nombre que quieras.
Pero tienes que ser un nombre que entiendas.
Que entiendas o que te haga sentido con lo que estás haciendo.
Estamos haciendo aquí cómo traer la información.
Y aquí tenemos la key de la información o de la query.
O de la query.
Vale.
Pues con esto, si volvemos a la página y volvemos a refrescar,
podemos ver que ya funciona correctamente.
De hecho, ¿ves que pone ahí cargando?
Pone que no hay usuarios.
Este no hay usuario.
Lo tenemos que cambiar.
No hay usuarios.
¿Dónde está?
No hay usuarios.
Esto es si no está cargando.
Y ya está.
¿Ves?
Tenemos el cargando.
Y luego nos aparecen ya los resultados.
O sea, por ahora ya tenemos al menos que nos hemos ahorrado.
Fíjate.
Estos son 117 líneas.
Y este que teníamos antes eran 140.
O sea, hemos quitado 30 líneas de código.
Lo hemos simplificado.
Y además nos está dando un poquito más de claridad sobre las cosas que está haciendo.
Pero es verdad que nos falta todavía el tema de paginar.
Que lo vamos a hacer ahora.
¿User es para div checking del RIA?
No en caso de que cambios para que detecta.
No.
El user no es para div checking.
El users, este que tenéis aquí.
Esto es para la llave para identificar esta parte del estado o la query que estamos haciendo.
No tiene nada que ver con el div checking.
¿Tiene una función en su query para solicitar nuevamente los datos?
Sí.
De hecho, tienes la posibilidad de utilizar...
No sé por qué no tengo el autocomplete.
Ah, mira.
Pero tienes refetch.
¿Vale?
Podríamos utilizar el refetch.
¿Veis que teníamos aquí el reset?
Podríamos utilizar el refetch aquí para hacer el reset.
Y el refetch lo que hace es que justamente vuelve a pedir los datos que le habíamos dicho.
¿Cómo podemos hacer el tema de la paginación?
Para hacer la paginación, vamos a tener que cambiar un poco el fetch uses.
O sea, además, fijaos que hemos podido quitar aquí el use effect.
Solo quitar el use effect y pensar de una forma mucho más declarativa.
Es tan increíble.
Me encanta.
Vamos a tener que cambiar cómo funciona el tema de la paginación.
¿Qué queremos?
Queremos que cada vez que le demos aquí al cargar más resultados, cargue la siguiente página.
Para eso, necesitamos saber en qué página estamos.
Ahora mismo, no sabemos en qué página estamos.
Y sí que tengo aquí un estado.
Podría cambiar el estado, pero sería como muy complejo cambiar el estado, pasar el estado al use query, no sé qué.
Lo mejor y lo más fácil es que normalmente en las APIs como esta, fíjate que tenemos aquí en la info que te dice en qué página estás.
Casi todas las APIs te dicen en qué página estás y tal.
Hay diferentes estrategias con las que podríamos hacer esto.
Pero en este caso y en casi todos los casos, lo mejor es que seamos capaces de que la API nos informe en qué página nos encontramos, si todavía tenemos resultados que mostrar, cosas así.
Vamos a cambiar un poco aquí lo que devuelve este fetch users y en lugar de devolver directamente los usuarios, vamos a devolver un objeto.
Los objetos son lo mejor del mundo porque son súper extensibles.
O sea, primero puedes devolver solo la propiedad users, pero siempre puedes decir, ah, pues ahora voy a extenderlo y agregar una propiedad más o lo que sea.
Así que vamos a tener aquí users, que es res.results.
Results, pero ahora vamos a tener la posibilidad de decirle, vale, quiero saber qué página es en la que estoy ahora.
Así que aquí no vamos a decirle la página, vamos a decirle cuál es la siguiente.
La siguiente página sería res.info.page, ¿no?
Porque tenemos aquí res.info.page, es la 1, ¿vale?
Pues la siguiente página sería más 1.
No, yo sé que el page este no es lo que crees.
Vamos a sacarlo aquí.
Page number res.info.
A ver si esto le gusta.
Page.
Ah, espérate.
Esto.
Vamos a ponerlo aquí.
Next cursor.
A ver si esto le gusta y no nos da la murga.
Next cursor.
Esto por aquí.
Y esto lo devolvemos aquí como un objeto.
Esto cierra aquí.
Esto cierra aquí.
Esto cierra aquí.
Punto page.
Esto es el punto page, ¿vale?
Lo que estoy haciendo aquí es transformar el res.info.page en un número, para que se asegure que es un número.
Y entonces ya teníamos ahí el siguiente cursor.
Por lo tanto, cuando la API nos devuelva la primera página, nos dirá página es 1.
Devolvemos la página 1.
Y aquí calculamos la siguiente.
O sea, aquí esto será 2 en la primera.
¿Vale?
Muy bien.
Ahora, en el fetch users, me pasamos aquí el page como number y tal.
Esto ahora mismo no le llega, pero luego le haremos que le llegue de alguna forma.
¿Vale?
Muy bien.
¿Qué más tenemos por aquí?
Tenemos que hacer cambios en nuestro componente porque el useQuery no está pensado para que tengáis este tipo de paginación infinita.
Tenemos que utilizar otro hook que tiene React Query que te permite hacer paginaciones totalmente infinitas.
Así que aquí le vamos a traer que se llama useInfinityQuery.
¿Vale?
Lo usamos y ya ves que parece igual, ¿no?
Parece exactamente igual, aunque ya se me está quejando aquí un poquito el useInfinityQuery.
Me está diciendo, oye, que no encaja los tipos con lo que tenías antes.
¿Por qué no encaja?
Por diferentes cosas.
Lo primero es que ahora hemos cambiado los tipos.
Los tipos ahora no devuelve solo los usuarios, sino que tendríamos aquí el nextCursor, que esto debería ser un number,
y el users, que sí que es el array de users.
¿Vale?
Así que ahora los tipos los hemos adaptado para que detecte que lo que devolvemos aquí es exactamente lo que estamos metiendo en la query, en la data.
¿Vale?
Aunque la data también va a tener que cambiar porque la data ahora es un objeto.
Así que este data, vamos a sacar aquí el data, vamos a sacar users, data, y luego veremos cómo hacemos esto.
¿Vale?
Cómo sacamos los usuarios del data.
Vamos a poner un console.log del data por ahora para que lo veas.
¿Qué más cosas nos ofrece?
Tenemos el isLoading, tenemos el isError, tenemos el data, el refetch, pero ahora tenemos más información.
Por ejemplo, el fetch nextPage para que haga un fetch directamente de la próxima página y también que nos informe si tiene una nueva página.
¿Cuándo vas a ver si tiene una nueva página?
Vas a ver si tiene una nueva página siempre que sepa que este nextCursor está informado.
¿Y cómo lo decimos que sabe de dónde tiene que sacar este nextCursor?
¿Cómo sabe que tiene que utilizar esta propiedad?
Pues porque nosotros le vamos a informar cómo tiene que recuperar el parámetro de la página.
Así que le vamos a añadir una opción más aquí, ¿vale?
Que es un objeto.
Aquí le podríamos pasar un montón de opciones.
Por ejemplo, configurar cuánto tiempo va a tener que hacer un refetch,
de dónde va a sacar el nextParam,
si vamos a desactivar el tema de que se sincronice.
Un montón de opciones que le podéis pasar por aquí.
Bueno, pues vamos a decirle getNextPageParam y aquí le tengo que pasar una función que le recibe dos parámetros.
El lastPage, que esto tiene la última página que hemos recibido,
y pages, que son todas las páginas que se ha descargado hasta ahora.
Y en la última page va a ser la respuesta de la última página que ha cargado.
O sea, cuando entremos en nuestra página la primera vez, vamos a tener este resultado de results
y vamos a tener el nextCursor a 1.
O sea, que en el lastPage, o no, a 1, lo vamos a tener a 2.
En el lastPage vamos a tener esta información de aquí, ¿vale?
Así que en el lastPage tenemos que sacar lastPage, la información.
Fíjate que he hecho punto y aquí sé que tiene el autocomplete,
porque ya sabe que la información que le estoy diciendo que va a sacar de este fetch
es justamente esta de aquí.
Así que cuando le ponemos punto, le dice, vale, pues nextCursor.
O sea, el PageParam siempre va a ser el nextCursor.
Y el nextCursor es el que estamos pasando por aquí.
Ya ves que aquí esto lo podrías sacar de otros sitios.
O sea, tú aquí puedes hacer lo que quieras.
Puedes sacarlo de, yo qué sé, de las queries de la URL.
Lo puedes sacar de un servicio, yo qué sé.
Lo puedes sacar del local storage, lo puedes sacar de donde quieras.
Nosotros lo estamos sacando de aquí porque sabemos que la API
ya nos está devolviendo la siguiente página.
Pero de nuevo, esto puede utilizar, puede utilizar.
Claro que puedes utilizar.
Esto es una función de JavaScript.
Puedes hacer lo que quieras.
Así que no estás obligado a sacarlo del lastPage.
Yo lo estoy sacando del lastPage porque sé que me lo está devolviendo.
Pero aquí sácalo de donde tú quieras, ¿vale?
Así que lastPage.nextCursor y ya lo tenemos.
Aquí le estamos diciendo dónde tiene que sacar el parámetro de la página,
del lastPage.nextCursor, que lo estamos recuperando, de aquí, ¿vale?
¿A qué te refieres con pensar de forma declarativa?
Eso es muy básico respecto a cómo es React,
pero imperativo sería decir todos los pasos que tienes que hacer.
Y, por ejemplo, en el useEffect, estamos diciéndole todos los pasos.
Tenemos que decirle, hace el setLoading antes de hacer la llamada.
Cuando hagas la llamada, entonces setErro.
Es muy imperativo.
Declarativo es aquí porque le estamos indicando directamente.
Así se hace el fetching de datos.
Esta es la key.
Dime si estoy cargando, si tiene un error y tal.
Entonces, mucho más declarativo, ¿no?
Entonces, ya hemos dicho cómo sacamos la siguiente página,
the nextCursor.
Para poder recuperar el page param, este que nos está llegando aquí,
tenemos que cambiar nuestro fetch user porque no lo podemos hacer así.
Fijaos que aquí el fetch user, yo siempre estoy pasando el 1.
En el fetch user, para que esto funcione, vamos a cambiar esto
y le vamos a decir directamente que utilice fetch users.
O sea, que utilice directamente la función de fetch users.
Fíjate que ya se me queja, me dice, oye,
es que los tipos no son exactamente los mismos.
¿Por qué?
Cuando tú le pasas la función aquí de fetch users,
ya directamente React Query le está inyectando los parámetros
que necesita para que funcione.
Así que aquí vas a poder recuperar, por ejemplo, el page param, ¿vale?
Vas a tener el parámetro de la página.
Aquí hay un montón de cosas que podríais sacar.
Podréis sacar todo el contexto de las llamadas.
De hecho, los podéis ver por aquí, si nos ponemos encima,
tenéis un montón de información que podéis acceder
como llamadas previas, paginaciones, lo que sea.
Nosotros solo necesitamos el page param.
Así que vamos a utilizar page param, page param.
Vamos a decir que por defecto va a ser la página 1,
que llegar va a llegar, pero bueno.
Y vamos a decir que esto es un número.
Ya tenemos ahí el page param, así que lo podemos utilizar aquí directamente.
Y aquí es donde deberían llegar nuestros parámetros de búsqueda, ¿vale?
El page param nos debería llegar aquí y ya está.
No sé por qué se me queja de esto igualmente.
Porque dice que page param...
Ah, yo creo que es por esto, ¿puede ser?
Sí, porque es opcional.
El page param puede llegar o no.
Es undefined también, ¿veis?
Ahora ya no se me queja.
Vale, pues con esto...
Bueno, este de pages es porque os lo quería explicar para que veáis.
Por ahora vamos a poner esto.
Esto lo voy a dejar por ahora.
Luego los utilizaremos.
Todavía no hemos terminado porque quedan un par de detallitos.
Y porque es importantísimo que entiendas
cómo nos devuelve la información React Query.
Vamos a ver el data.
Esto nos va a petar, no nos va a funcionar porque hay cosas que están mal.
Vamos a ver el data, este console.log que tenemos aquí.
Vamos a verlo para que veáis un poco cómo funciona.
¿Vale?
Page params, pages...
Vale.
Fíjate que tenemos aquí page params, que esto es un array que nos pone que ahí está en define, ¿vale?
Y por aquí nos dice el next cursor, nos pone un 1 y aquí tenemos los usuarios.
Pero fíjate que tiene una propiedad pages.
O sea, ya sabemos que este data, si hacemos aquí punto, ¿ves?
Ya tenemos pages.
Vale.
Vamos a volver a ver esto.
Vamos a refrescar.
Vale.
Hace un momento había funcionado.
No sé si por el users...
Voy a poner el users que sale un array vacío.
Users has any...
Sí.
Vamos a poner que esto es user tal.
Que no sé si...
Vale.
Vale.
Es que es porque me peta, ¿vale?
O sea, no salía porque el data petaba,
porque estamos intentando más abajo acceder al users.
Entonces, no seguía ejecutando la llamada y tal, ¿vale?
Pero aquí lo tenemos.
Aquí tenemos pages y page params.
Ahora sí.
Entonces, fíjate que tienes dos parámetros.
O sea, dos propiedades del objeto data.
Page params, que es un array que ahora está en define, y pages.
Y en pages tienes el next cursor, que es uno,
y tienes todos los usuarios, ¿no?
Tienes aquí users y tal.
Pues, esto es importante...
Oye, no estoy haciendo el más uno, ¿no?
Ah, amigo.
Aquí tenemos que poner el más uno porque en realidad el next cursor debería ser dos.
¿Vale?
A ver ahora...
Next cursor ahora es dos.
Vale, ahora sí.
Vale.
Pues, fíjate que aquí tenemos todos los usuarios.
Pero, ¿qué pasa con esto?
Que lo que va a hacer React Query es que nos va a poner todas las páginas por separado.
O sea, vamos a tener la página como un elemento de un array.
Y ahora lo vas a ver más claro.
Mira, imagínate que llamamos al fetch next page,
que esto lo que hace es traernos la siguiente página.
Vamos a recuperar aquí también los usuarios.
Vamos, users, esto viene de data, pages, punto.
Y vamos a acceder al menos al primero, ¿vale?
Vamos a acceder a la primera posición del array, que sabemos que esto debería tener users.
¿Vale?
Y si no, vamos a poner que es un arribacio.
Y ya está.
Y así al menos intentamos acceder a data, pages, la primera posición, users.
Y si no, arribacio.
Y al menos ahora sí que tenemos la primera página.
Pero vamos a querer tener las siguientes páginas también.
Para eso, cuando hagamos clic en este botón de cargar más resultados,
vamos a darle al fetch next page este.
¿Vale?
Así que, vamos aquí.
¿Ves que aquí cambiamos el estado este?
Ahora no queremos nada de esto.
Ahora lo único que queremos es que nos traigan la siguiente página, punto.
Parece un tema de TypeScript.
Me imagino que es una buena práctica.
No he terminado ahora ahí muy bien de entender por qué lo quiere.
Pero por ahora lo vamos a quitar.
No floating promises.
¡Ah!
Devolviendo esto.
Ah, bueno.
Pues ya está.
Pues hacemos void para que no devuelva a nadie.
Ya está.
Void, por si no sabíais, es un operador que lo que hace es que cualquier cosa que tenga a la derecha devuelva undefined.
¿Vale?
Entonces tú puedes poner, por ejemplo.
Está bastante curioso.
Void 2.
Y esto lo que hace es que no devuelve el 2.
Devuelve undefined.
¿Vale?
Tú le puedes poner a la derecha lo que tú quieras, que siempre va a devolver eso.
Al darle al cargar más resultados, llamará al fetch next page, recuperará a la siguiente página y vamos a ver qué es lo que pasa.
¿Vale?
Le he dado y lo que podemos ver es que sí que parece que se están cargando.
¿Ves?
4, 5.
O sea, se están cargando las siguientes, pero no las vemos.
¿Qué está pasando aquí?
Bueno, lo vamos a ver perfectamente en el...
Mira, nos podemos quitar ya el estado de las páginas.
¿Qué está pasando?
Pues lo que está pasando es el data.
Vamos a poner data.
¿Vale?
Ahí tenemos data con pages, tal.
Cuando yo le doy a cargar más resultados, el data ahora tenemos dos páginas.
Y en cada página tenemos los 10 usuarios.
Y fíjate que ya me dice que el siguiente cursor es el 3.
Le doy y otra vez más datos.
Y ahora tenemos tres páginas, pero en cada página tenemos usuarios.
Y entonces ahora vamos a hacer una cosa que os va a volar la cabeza.
Porque es una de las pocas veces que he visto que este método de array tenga sentido.
Y aquí tiene todo el sentido del mundo.
Y te va a llamar mucho la atención porque nos lo facilita un montón.
¿Qué es lo que tenemos que hacer aquí?
Ya hemos visto que tenemos aquí como un montón de arrays de cada página.
Tienes los arrays de los usuarios.
Claro, para simplificar esto podríamos hacer un for each, acceder o mapear los datos.
Pero lo más fácil que puedes hacer aquí es decir, mira, de las páginas quiero que me hagas un flat map.
Y de cada página me sacas los usuarios.
Y esto me lo aplanas.
Y al aplanarlo, lo que nos va a dejar esto es un solo array con todos los usuarios.
Y ahora sí, cuando nosotros empecemos a hacer esto y le digamos cargan más resultados, ¿ves?
Nos carga todos los resultados.
Y ahora ya sí que tenemos el infinity scroll de una forma súper sencilla.
Con el flat map lo que hacemos es aplanar.
No te preocupes.
No has entendido el flat map, te has perdido, no te has enterado.
Bueno, no pasa nada.
Mira, tenemos las páginas, ¿no?
Y las páginas, fíjate, vamos a hacer el console.log del data para que se parezca lo máximo posible.
Tenemos un array y en cada array, pues tenemos aquí, por ejemplo, users.
Y tenemos un, dos, tres.
Y aquí tenemos más users.
Tenemos cuatro, cinco, seis, ¿no?
Bueno, pues lo que puedes hacer aquí justamente sería decir, bueno, voy a aplanar todos los usuarios.
Porque estos son, o los podrías concatenar, podrías hacerlo de un montón de formas.
Pero lo que puedes hacer aquí es decir, pages, ¿vale?
Quiero que los pages, fíjate que en cada uno de los elementos tengo user, user, y en cada uno tengo también un array, ¿vale?
Pues los quiero aplanar porque en realidad me interesa esto, pero quiero aplanarlos y que estén en el mismo nivel.
No que sean arrays que están anidados o que están separados.
Así que vamos, en lugar de hacer un map de cada uno y decir p, p users, ¿vale?
Que con esto, fíjate, lo tendríamos así.
Si yo sacase los usuarios de cada uno, ¿ves?
No lo tendría aplanado.
Tendría un array para cada uno de los elementos y un array dentro de cada uno.
O sea, cada elemento tendría un array dentro de un array.
Bueno, dos arrays dentro de un array, en este caso.
¿Ves cómo quedaría?
Pero con el flat map lo que le estamos diciendo es que nos lo aplane.
Como solo es un solo nivel le decimos, oye, quiero que todos los elementos de los arrays que vas a tener me los aplanes en uno solo.
Y así tenemos todos los usuarios en uno solo.
Es muy chulo, es un tema muy interesante que no se suele hablar mucho.
Y aquí pues tenéis un caso de uso bastante claro.
O sea, esto es un tema claro de dónde utilizar un flat map.
Bueno, pues con esto ya tendríamos el tema de la paginación.
Hay un problemita, nada grave, ¿no?
A ver, handle reset, handle reset, await.
A ver si ponemos aquí void.
Esto así podemos hacer.
Vale.
Hay un problemilla.
Hay un problemilla, no es nada grave, tampoco es que sea un problema.
Pero el tema es que esto no termina nunca.
O sea, nosotros estamos aquí y siempre, siempre, siempre está apareciendo el cargar más resultados.
O sea, es como que no tiene fin, ¿vale?
No tiene fin y ¿qué pasa aquí?
Podemos decirle que tenga fin.
Por ejemplo, imagínate que solo queremos que tenga 10 páginas como máximo.
Podemos decir, current page, lo detectamos así.
Y podemos decir que el next cursor sea el current page.
Si el current page es mayor de 10, entonces que sean defined.
O sea, ya no hay next cursor.
Y si no, más uno.
Lo bueno de esto, lo bueno de, ah, este current page, ¿qué ha pasado aquí?
Ah, por el, ah, porque esto era, vale, porque he puesto que esto era number, vale.
Hostia, de verdad, ayuda muchísimo esta extensión, ¿eh?
Porque me hubiera costado mucho más ver el error.
El error es que el next cursor puede ser undefined, ¿veis?
Y entonces me decía, se estaba quejando, pero claro, se estaba quejando un montón de muchas cosas.
Pues ahí tienes el next cursor, cuando tú le pongas undefined, voy a ponerlo más pequeño para que se vea, ¿vale?
Voy a poner que después de la 3 ya no me ponga más.
Entonces, cuando tú le das cargar más resultados, cargar más resultados, cargar más resultados, me va a aparecer aquí, me aparece, pero si le doy, fíjate que le doy click y no me carga más resultados.
Para hacer que desaparezca el botón, porque no hay más resultados, porque hemos detectado que hemos llegado al final, que eso es un trabajo que obviamente es solo la app y es capaz de saberse y no tiene más resultados, tenemos este hash next page.
Es un boleano que será true si el next cursor es un número y será, o sea, será false en el caso de que el next cursor sea undefined.
Así que con esa información ya nos podemos ir aquí al botón y entonces si tenemos una siguiente página, entonces podemos seguir cargando.
A ver, ¿por qué esto no me gusta?
En aspecto no me gusta, vale, si esto es true, vale, entonces nos muestra el otro.
Y ahora sí, si recargamos, nos va mostrando el botón, le damos click, ya nos muestra el botón, nos muestra el botón, ya nos muestra el botón.
Lo podríais poner, ya no hay más resultados, por ejemplo, yo qué sé, que eso es una cosa, hash next page, no hay más resultados, ¿vale?
Y ahora cuando le deis tres veces, pues vais a ver qué te dice ahí, eh, no hay más resultados.
Ya habéis hecho con esto un infinity scroll, súper sencillo, es súper fácil de mantener porque ya es súper declarativo.
O sea, ya tenéis ahí toda la información y ya no os tenéis que preocupar de cómo se hacen las llamadas y tal.
Además, otra cosa que es muy interesante de todo esto que hemos hecho, podéis separar esto en un custom hook y que sea totalmente transparente para lo que estamos haciendo.
Podríamos hacer aquí un hook y decir aquí que sea useusers.ts, ¿vale?
Sacamos este fetchusers, que bueno, este fetchusers lo podríamos sacar hasta, mira, en un servicio, services, y vas a ver cómo de fácil queda el componente, ¿vale?
Users, ts, esto export, const, fetchusers, y esto en useusers, importamos el fetchusers, ¿vale?
From, services, users.
Vamos a crear aquí nuestro custom hook y de nuevo, súper fácil los custom hooks.
Solo sacamos esto de aquí, ¿vale?
Y ahora aquí, return, isLoading, isError.
Podríamos aquí transformar los usuarios si quisiéramos, que tiene sentido.
FetchNextPage, hasNextPage.
UseInfinityQuery, lo tenemos que importar, ¿vale?
Import, useInfinityQuery, de TansTagQuery, no sé por qué me sale ese, ¿vale?
El user lo tenemos que importar, el tipo user, tipo user.
¿Midus y la API requiere un token de autorización donde se configura usando ReactQuery?
No tiene nada que ver, no tiene nada que ver, tío.
O sea, de verdad, tenéis que cambiar el chip.
No tiene nada que ver con ReactQuery.
Da igual.
Mira, ReactQuery no sabe dónde hacen la llamada.
No lo sabe, no lo necesita, ¿sabes?
No lo necesita.
Fíjate que fetchusers no lo sabe.
No tiene ni idea.
Mira, entonces, tú aquí puedes hacer lo que quieras.
¿Dónde tendrías que pasarlo?
Pues lo tendrías que pasar aquí.
Pero si utilizas Axios, pues igual lo tendrías que hacer de otra forma.
Y aquí en headers, pues tendrías el content no sé qué.
Y aquí x, api, api key, por decir algo.
Pues lo pondrías aquí.
Pero ReactQuery no lo sabe, no lo sabe.
Esto puede ser Axios.
Esto puede ser leer en el local storage.
Esto puede ser lo que vosotros queráis.
Por eso es importante.
ReactQuery no es de hacer fetching de datos.
No lo sabe.
Él no sabe cómo hacen los fetching de datos.
Lo único que sabe es que le vas a devolver los datos de forma síncrona.
Punto.
Ya está.
Lo harías aquí.
Esto lo podrías sacar del env, si quieres.
Enf.
O punto meta.
Punto env.
Public, bit, api key.
Yo qué sé.
Lo que sea.
Pero no tiene nada que ver con ReactQuery.
¿Vale?
O sea, no es una pregunta de ReactQuery.
Al final, es otra cosa que es más de cómo harías tú un fetching normal y corriente.
Y eso es lo más bonito que tiene ReactQuery, justamente.
Porque no te tienes que preocupar de cómo lo hago y tal.
Porque lo haces desde otro sitio.
¿Vale?
Vale.
Entonces, con este useUser, fíjate lo chulo que ahora quitaríamos todo esto.
Aquí ponemos useUsers.
Aquí ahora soltemos users.
Esto lo quitaríamos de aquí.
Y ya está.
O sea, tenemos una línea.
Una línea donde tenemos ya todo lo que queremos y ya está.
¿Sabes?
O sea, ya tenemos aquí todo.
Y además lo tenemos tipado.
Sin ningún problema.
De cómo recuperar nuevas páginas.
Y todo esto.
A ver.
Pero si devolvemos aquí una rey.
Es que, claro.
Esto me lo ha hecho iHackoPilot.
Y me ha hecho aquí una cosa rara.
Porque yo creo que debería ser así.
Ahora tiene sentido.
Vale.
Ahora está arreglado.
¿Vale?
Pues con esta línea.
Solo con esta línea.
Fijaos todo lo que tenemos.
Solo con estas líneas.
Tenemos estado de carga.
Errores.
Los datos.
Poder hacer un refresh.
Poder recuperar la siguiente página.
Y saber si tiene una siguiente página.
Todo esto.
Paginación.
Infinity Scroll.
Solo en este Custom Hook.
Pero lo mejor de todo esto.
Lo mejor de todo esto.
Es que además.
Además.
Acabamos de hacer sin darnos cuenta.
Un estado global.
Y te lo voy a enseñar.
Que esto es bastante.
Bastante chulo.
Mira.
Imagínate.
Que tenemos otro.
No sé.
Aquí un componente.
Que le voy a llamar.
Results.
¿Vale?
Results.
Vamos a poner aquí.
Results.ts.
Por const.
Results.
Normalmente.
Sería súper complicado.
Hacer esto.
Bueno.
Imagínate.
Que quieres saber.
Cuántos usuarios.
Ya tiene la lista.
Eso lo podrías calcular.
De muchas formas y tal.
Pero.
Imagínate.
Que lo tienes.
En un sitio.
Totalmente separado.
Y te gustaría tener como un estado global.
Para adquirir esa información.
Porque realmente tú ya sabes.
Y ya lo has hecho.
Esto normalmente sería bastante difícil.
Porque tendrías que estar creando un estado global.
Tendrías que asegurarte que no haces dos veces la llamada.
Para recuperar la misma información.
Pues eso.
React Query.
Te lo hace automáticamente.
Mira.
Aquí vamos a poner un Results.
Ah.
Claro.
Que este Result no puedo.
Ah.
Se me ha olvidado el TSX.
Vale.
Vale.
Ya está.
Un momento.
Un momento.
Ahora sí.
Vale.
Ahora sí.
Ahora sí.
Que se me había olvidado la extensión.
Results.
Y aquí.
Pues.
Users.
¿Vale?
Imagínate.
Es un componente sencillo.
Y este componente lo queremos mostrar aquí.
Justo debajo.
De prueba técnica.
Pero fíjate que yo no le paso ninguna prop.
Lo que hago es tirar del Custom Hook de Users.
Y solo recupero los usuarios.
Punto.
No estoy haciendo nada más.
¿Vale?
Fíjate.
Diez.
Y se sincroniza automáticamente.
Automáticamente.
Estos resultados que tenemos aquí.
Detecta cuántos resultados hay aquí.
Y los ponemos aquí.
Pero no se lo estoy pasando por prop ni nada.
Sino que lo que está haciendo.
Es que de estos datos.
Que además ya los tiene cacheados.
Lo está mirando.
¿Y por qué sé que está cacheado?
Pues porque fíjate.
En la red.
Si miramos aquí en la red.
Fíjate que solo hace una llamada.
No está haciendo dos llamadas.
Porque estamos llamando dos veces a esto.
Y si doy a cargar más resultados.
Bueno aquí.
Ah bueno.
Ahora os explicaré.
Porque ahí sí que aparece que.
Parece que lo ha hecho dos veces.
Pero no.
Fíjate que yo cargo los resultados.
Te estoy en la página 4.
Aquí me aparece esa información.
Pero no está cargando dos veces los datos.
Estamos teniendo aquí efectivamente.
Un estado global.
Después de hacer una petición asíncrona.
Estamos compartiendo los datos.
O sea.
Internamente ha sido capaz de decir.
Ostras.
Lo que estoy haciendo es.
Haciendo una petición a una API.
Me guardo esto en mi estado global.
En un estado global mío.
En caché.
Y voy a compartir la información.
Allá donde quiera.
Y esto lo puedes hacer tantas veces.
Como te dé la gana.
O sea.
Ya sea.
Recuperar una parte de los usuarios.
Lo que sea.
Lo tienes aquí.
Y lo puedes sacar.
Y punto.
¿Vale?
Hay una cosa que no os he comentado.
Pero fíjate que cada vez que hago clic aquí.
Y voy a.
Y hago clic aquí otra vez.
¿Veis que hace una petición?
Eso es porque automáticamente lo que hace React Query.
Y esto lo hacen un montón de herramientas de ese tipo.
Es que cuando recupera el foco la página.
Vuelve a hacer un fetching de datos de toda la página que esté tratada con React Query.
Para asegurarse que la información que le muestras al usuario.
Es lo más actualizada posible.
Porque tú imagínate que un usuario se va.
Yo que sé.
A una página.
Bla, bla, bla.
Y de repente vuelve aquí.
Y dice.
Ostras.
Esto es de ayer.
Bueno.
Pues lo que hace automáticamente.
Fíjate.
Cuando yo vuelva.
Pum.
Me acaba de hacer otra petición.
En este caso.
A lo mejor no tendría sentido.
Y de hecho lo podéis desactivar.
Podríais decirle.
Oye.
No quiero que hagas el fetching.
Esto lo podéis desactivar aquí.
Refetch.
Window.
On Window Focus.
¿Vale?
Lo podéis hacer a false.
Y entonces esto lo desactivaría.
Pero es muy interesante que a veces.
¿Ves?
Ahora no pasaría.
Ahora se queda con una.
Cuando yo me voy y vuelvo.
No vuelvo a hacer el fetching de datos.
Hay que tener cuidado con el fetching de datos este.
Es bastante peligroso.
Porque imaginad que yo he paginado unas cuantas veces.
¿Vale?
Yo he paginado.
Aquí.
¿Ves?
Cuatro páginas.
Y me voy.
Y vuelves.
Y fíjate que hace el fetching de datos de las cuatro páginas.
Tened cuidado con esto.
Porque he visto muchos casos de gente que no tiene cuidado con esto.
Y luego cuando vuelve el usuario.
Se pone a hacer ahí una de fetching de datos.
Y puede ser bastante bestia.
Lo bueno es que internamente React Query entiende que ya tenía datos.
Y fíjate que no enseña la pantalla de carga.
Podríamos mirarlo.
Podrían mirar.
En lugar del isLoading.
Tienes otro que es isFetching, por ejemplo.
Para mirar si está haciendo un fetching de datos y tal.
O sea, podrías llegar a mirar.
O enseñar algo al usuario.
Como por ejemplo le podrían enseñar una notificación.
De que está sincronizando los datos o lo que sea.
Pero ten cuidado.
Solo que lo sepas.
En este caso.
En este ejemplo.
Yo creo que no tiene mucho sentido.
Porque al final dices.
Bueno.
Que más da.
Que salga la lista antigua.
Y ya está.
Pero con que lo sepáis que lo hace.
Pues perfecto.
Otra cosa que tiene.
Que es brutal también.
Y que os va a llamar un montón la atención.
Son las Developer Tools.
Las Developer Tools.
Hay que instalarlas aparte.
No vienen con el paquete.
Hacemos un PNP install de TAMSTAC.
No de React Query.
Sino React Query DevTools.
¿Vale?
Y le ponemos.
Esto puede ser en modo desarrollo.
Bueno.
Podría ser en modo desarrollo.
Pero lo vamos a poner en modo exacto.
¿Vale?
Con el menos E.
Nos volvemos al main.
¿Ok?
Aquí al main.
Importamos la React Query.
React Query.
React Query DevTools.
Aquí la tenemos.
Y esto lo cargamos aquí.
No hace falta que envuelva nada.
Lo tenemos que poner por aquí.
Y si volvemos a nuestro proyecto.
Vale.
Fíjate aquí.
Al lado de esta chica.
Que ha aparecido esto de aquí.
Pues si le das clic.
¡Pum!
Te aparece esto.
Que está bastante chulo.
Mira.
Cuando recargamos.
Pues ya nos sale aquí las peticiones que ha hecho.
Es un.
Es algo sencillo.
En nuestro caso.
Pues solo estamos haciendo una petición.
Pero.
Está bien.
Porque mira.
Le das a cargar más resultados.
Y aquí vamos viendo las peticiones que ha haciendo.
Como lo está haciendo.
La key que está mirando.
Y aquí tenemos los diferentes estados.
¿Qué pasa aquí?
Pone fresh, fetching, pause, stale, inactive.
¿Qué significa stale?
Lo que quiere decir de stale.
Es como que los datos es como si estuviesen caducados.
Y esto quiere decir que siempre que tenga la oportunidad.
Por ejemplo.
Cuando te vas de la pantalla.
Y vuelves.
Si no lo tienes desactivado.
Va a intentar hacer un refreshing de datos.
Porque entiende que son antiguos.
Lo bueno.
Es que lo podéis configurar también.
O sea.
Podríamos ir aquí al use user.
Y si no me equivoco.
Por aquí.
En el stale.
¿Ves?
Le podéis decir el tiempo.
En el que sea stale.
¿Vale?
Que los datos.
Digamos que.
Ya son viejos.
Bueno.
Podéis poner infinito.
Y entonces que nunca.
¿Ves?
Ahora siempre los datos son frescos.
¿Qué es lo interesante de esto?
Pues que le podéis decir.
¿Cuánto es el tiempo que consideráis?
Por ejemplo.
Podéis decir.
Pues 24 horas.
Igual es un poco exagerado.
¿Vale?
Podéis hacer algo más.
Pues eso sea un minuto.
Esto sea un minuto.
Podéis hacer 5 minutos.
¿Vale?
Esto serían 5 minutos.
¿Vale?
Pues 5 minutos.
Si han pasado 5 minutos.
Mira.
Ahora son frescos.
Pero cuando pase.
Mira.
De hecho.
Podemos hacer que lo veamos en vivo.
Vamos a poner 10 segundos.
¿Vale?
10 segundos.
Bueno.
3 segundos.
¿Vale?
Hacemos aquí el fetching de datos.
1, 2, 3.
¡Pum!
Y pasan a ser datos ya que están stale.
O sea.
Que ya han pasado de moda.
Digamos.
Esto lo podemos hacer y lo podemos controlar nosotros.
Y es muy chulo.
Porque depende de los datos.
De cómo de críticos sean los datos.
Podríais mirar de que sean datos.
Si son muy críticos.
Oye.
Que caduquen muy rápido.
Si no son tan críticos.
Os da igual.
Que tengan tiempo infinito.
Y que nunca caduquen.
Pero aquí tenéis los diferentes estados.
Fresh.
Fetching.
Pause.
Stale.
El fetching.
No lo vemos.
Pero es muy sencillo que lo podamos ver.
Si aquí.
Y para que veáis que esto es súper fácil de timar.
Si hacemos algo así.
Ponemos un delay.
¿Vale?
Y aquí vamos a hacer un delay de un segundo.
¿Vale?
Vamos a hacer que tarde un segundo en hacer el fetching de datos.
Pues si nosotros refrescamos.
Stand fetching.
Pasa un segundo.
Fresh.
Le damos aquí.
Stand fetching.
Pasa un segundo.
Fresh.
Y además aquí podéis ver en qué estado se encuentra cada una.
Podéis ver ahí el colorcito.
Luego podéis vosotros forzar.
Y esto está súper chulo.
El hecho de que podéis forzar el estado.
Podéis decir.
Oye.
Hace un refetching.
Entonces vuelve a hacer un fetching.
Invalidar los datos para que se queden en stale.
Resetearlos.
Borrarlos.
Hacer.
Forzar un trigger del loading.
¿Ves?
Entonces ahora se pone a cargar.
Un trigger del error.
Esto está súper chulo porque podéis probar vuestra aplicación súper fácil de cómo
se comporta en diferentes estados directamente aquí dándole a diferentes acciones.
¿Vale?
Así que le dais a cada uno.
Invalidar.
Reset.
No sé qué.
Y ya lo tendríais.
Y aquí podéis ver toda la información.
Todo el resto de información de cómo está funcionando.
Por ejemplo.
Qué tiene en el estado.
Si lo está intentando más de una vez.
Otra cosa que no os he comentado y que está muy muy chula.
Lo vamos a mirar.
Vamos a poner aquí el delay.
Y vamos a poner aquí.
Vamos a forzar un throw.
¿Vale?
Para que haya un error en la petición.
Si vamos aquí a la página.
¿Vale?
Y refresco.
Fijaos que está cargando.
Cargando.
Parece que está cargando.
Y está haciendo fetching.
Y sigue cargando.
Y sigue cargando.
Y sigue cargando.
A ver.
Vamos a ponerlo un poquito menos.
El delay.
Vale.
Cargando.
Y es raro porque dices.
¿Cómo que está cargando?
No tiene mucho sentido que esté cargando.
Si realmente no está cargando.
Porque ya he visto que está fallando.
Y de repente.
¡Pum!
Ha habido un error.
¿Qué es lo que está pasando aquí?
Pues lo que pasa es que está haciendo los retries.
Aunque en el fetching está intentando constantemente.
¿Ves?
Retrier.
O sea, lo ha estado intentando hasta que al final ha dicho.
Oye, no funciona.
O sea, esto es muy interesante porque automáticamente cuando detecta que una petición falla.
Que él no sabe si está haciendo una petición o una API o una base de datos.
Lo que sea.
Cuando falla, hace un retry automáticamente.
Y también esto, por supuesto, lo podéis configurar.
Podríais el retry, retry delay.
O sea, podéis intentar decir que tiene que hacer un retry.
O cuánto tiempo debe esperar para volver a intentarlo.
¿Vale?
Y eso también lo hace automáticamente.
Y no os tenéis que preocupar de que lo hagáis vosotros ni nada.
Pues esto serían un poco las developer tools.
Que en este caso es bastante sencillo.
Pero cuando tenéis aquí un montón de llamadas es brutal.
Porque las oportunidades que tienen son tremendas.
Y poder ver cómo se ha ido llamando.
Cómo ha funcionado cada cosa.
Pues está genial.
Ver si se ha quedado alguna penchada.
De por qué se ha fallado una de estas.
Cambiar el estado.
Lo que sea.
¿Vale?
Os voy a enseñar el tema de las mutaciones.
Hasta ahora solo hemos visto cómo pedir datos.
Cómo preguntar datos.
Pero también a veces queremos mutar datos.
O sea, queremos cambiar datos en una API.
Pues vamos a ver el proyecto 12.
Proyecto 12.
El de Common React Query.
Este.
Es un proyecto que tengo empezado pero no he hecho la mutación.
¿Vale?
Así que vamos a levantarlo para que lo veáis.
Ya os enseño un poco el código y os lo explico.
¿Vale?
Es este proyecto.
Bastante sencillo.
Muy tonto.
No tiene ninguna historia.
Lo que tenemos aquí es que podemos escribir comentarios, ¿no?
Y al enviar el comentario deberíamos verlo aquí.
Pero no lo está haciendo.
¿Por qué no lo está haciendo?
Porque si miramos el código.
Vamos aquí al formulario.
No.
Formulario no.
A la aplicación.
¿Qué pasa?
Pues que el formulario cuando hace submit en el handle submit aquí no está haciendo nada.
¿Vale?
Pero sí que es una aplicación que ya está utilizando Use Query donde está recuperando los comentarios.
Y para recuperar los comentarios llama a esta función de Get Comments.
Este Get Comments, para que lo veáis, hace un fetch a esta URL de aquí.
¿Vale?
Hace un fetch a esta URL de aquí.
Y esto, vale.
Necesitamos la API key.
Pero esto lo que hace es devolvernos.
Bueno, no sé si conocéis JSON Bean.
Os lo voy a explicar un momentito porque es que está súper chulo este proyecto.
Es gratuita.
Tiene una capa gratuita que es de 10.000 requests al mes.
Y esto lo que os ofrece es tener como un JSON en la nube.
Y os crea una API.
Es súper genial.
O sea, lo recomiendo un montón.
¿Ves?
En este caso tenemos esto.
Aquí tengo mi base de datos, mi JSON, digamos, en la nube.
Y tenéis aquí las API keys para que las podáis utilizar.
Y así poder traeros la información, cambiar la información, borrar la información.
Y no tenéis que hacer nada.
Y entonces tenéis una API súper rápida.
Aquí podéis ver el que yo estoy utilizando.
¿Ves?
El primer comentario o la gente del chat es este.
Primer comentario o la gente del chat.
Y lo que quiero es que al utilizar este formulario nos añada aquí otro más.
¿Cómo lo hacemos?
No es muy importante, pero te lo voy a explicar.
Tenemos aquí un método que se llama post comment.
Por cómo funciona esta API es un poco rara porque siempre hay que enviar todo el JSON.
Pero lo que estamos haciendo es recuperar todos los comentarios.
Creamos una idea para el comentario y pasándole el título y el mensaje.
Hacemos un fetch a la API nuestra.
Le decimos que queremos poner datos.
Le pasamos la API key.
Y en el body le pasamos el título y la descripción.
El título y el mensaje del comentario.
Y nos lo añade.
Así que lo importante es que sabemos que tenemos que llamar a este método para hacer una mutación.
Una mutación no es que te va a aparecer lo vez no y le van a salir las garras.
¿Vale?
Una mutación tampoco es que te va a salir una tercera oreja ni un tercer pezón ni nada.
Una mutación es cambiar datos en algún sitio.
Puede ser una base de datos, local storage.
Es cambiar los datos, ¿vale?
Mutarlos significa cambiarlos.
Punto.
Mutar se le llama mutar porque estamos cambiando el estado previo en el que se encontraba.
Estamos como mutándolo al hacer esa transformación.
¿Ok?
Por eso se llaman mutaciones.
Y por eso muchas veces hablamos de mutar un objeto.
Porque estamos hablando de que lo estamos modificando.
¿Cómo haríamos una mutación?
¿Cómo llamaríamos para añadir ese comentario a nuestra base de datos?
Que en este caso llamamos esto, pero esto, de nuevo insisto, aquí podríais hacer lo que queréis.
Llamar a un GraphQL, llamar a una API, a un local storage, a hacerlo en memoria.
Podéis hacer lo que queráis, ¿vale?
O sea, esto al final es una caja negra para React Query.
O sea, que no os tenéis que preocupar para nada.
¿Qué tendríamos que hacer?
Lo primero, tendríamos que traernos el hook useMutation.
UseMutation.
¿Vale?
El hook useMutation justamente nos permite hacer mutaciones.
Así que vamos a ejecutar el useMutation.
Y le tenemos que pasar primero cuál es la función de mutación.
La función de mutación que ejecutaremos es postComment.
Que es la que hemos visto aquí, ¿no?
Esta es la que hemos visto, que le tenemos que pasar el comentario.
Esta es la que queremos que se ejecute cuando queramos ejecutar la mutación.
Por ahora voy a dejarlo así, porque no quiero liarlo mucho.
Por ahora lo dejamos así.
Y vamos a recuperar mutate, ¿vale?
Este useMutation le tenemos que pasar cuál es la función de mutación,
que es la que vamos a ejecutar, cuando llamemos a este mutate.
Este mutate, ¿dónde lo tenemos que llamar?
Pues lo tenemos que llamar en el handleSubmit.
Este handleSubmit lo que deberíamos hacer es recuperar todos los datos que tenemos en el formulario.
Vamos a recuperar aquí, con el formData, new formData, bueno, más que formData, vamos a ponerle aquí data, ¿vale?
Y mirando, tendríamos en el formulario, tenemos el message y el title, ¿vale?
Pues vamos a traernos el message, message, ¿vale?
Así que esto sería el message y el title.
Esto, claro, esto podría ser cualquier cosa.
Entonces vamos a poner que es un toString y que si no, es una cadena de texto vacía.
Si tenemos título o si el título, vamos a hacer eso, si el título es diferente a string vacío
y el mensaje es diferente a string vacío, entonces llamamos al mutate para mutarlo,
para que nos envíe este comentario a la base de datos.
Con esto ya lo tendríamos, o sea, ya deberíamos, solo con esto ya estamos llamando a la mutación
y ya todo debería funcionar correctamente.
Pero vamos a ver qué pasa con esto.
Vamos a ver, si volvemos a nuestra página y le digo aquí comentario 1,
y quería comentar que el chat mola mucho, ¿vale?
Y le damos a enviar comentario, no ha pasado nada, no ha pasado nada.
Y si miramos aquí en el bin y refresco, ¿vale?
Vamos a ver aquí y aquí resulta que sí que ha pasado, ¿vale?
Aquí sí que tenemos el comentario, pero aquí no he visto.
Ahora sí.
¿Por qué ahora sí que ha aparecido?
Porque había salido de la ventana y he recuperado, he vuelto a la ventana,
ha hecho un refetching de los datos y ahora sí que ha aparecido.
¿Qué es lo que está pasando?
Lo que está pasando, y lo vamos a ver más claro aquí,
si yo pongo comentario 2 y vamos a ver si esto funciona,
y yo le doy aquí a enviar comentario, joder, es que siempre me va a hacer el refetch,
pero bueno, obviate esta, que esta es el refetch que ha hecho por volver a tener el foco,
le damos a enviar comentario, ¿vale?
Fíjate que está haciendo la petición, ha hecho la petición,
está haciendo aquí la petición, pero no me lo muestra aquí,
no está haciendo un refetching de los datos.
Si yo salgo y vuelvo, ahora sí que hace el refetch de los datos y sí que aparece.
Esto lo tenemos que arreglar, obviamente, ¿no?
Porque estamos dando una mala experiencia al usuario,
no le estamos, no estábamos como indicándole al usuario
de que realmente lo ha escrito, ni siquiera ve que lo esté escribiendo, ¿no?
Entonces, vamos a ir por partes.
Uno, primero, los loading.
Para saber si está cargando la mutación, si realmente se está haciendo,
podríamos hacer loading, is loading mutation, ¿vale?
Podríamos hacer un loading solo de la mutación.
Y así podríamos desactivar el formulario.
Por ejemplo, en el handle submit este,
podríamos decir, no, si se está haciendo una mutación,
si realmente se está haciendo una mutación,
pues no hagas nada de lo demás,
no permitas que la gente empiece a darle y se le vuelvan locos.
Lo mismo aquí podríamos hacer para que visualmente
se pueda ver que la opacidad es menor, ¿vale?
Y también, para evitar más problemas,
vamos a poner esto por aquí,
para evitar más problemas, si esto...
Ah, vamos a ponerlo con una ternaria que no le gusta, ¿vale?
Y esto mismo que hemos hecho aquí lo podríamos poner con el botón.
O sea, podemos decir que es disabled si está cargando la mutación.
Incluso el texto, podemos decir que se está cargando la mutation,
podemos decir, enviando comentario, ¿vale?
O sea, que al menos vamos a darle un poco de indicación a usuario
que algo está pasando, ¿vale?
Solo sacando uno, que es el is loading mutation.
Fíjate que yo no estoy gestionando ningún estado de nada,
que esto lo está haciendo automáticamente.
Lo mismo podríamos hacer con errores, ¿eh?
Pero también podré sacar aquí el error.
Podrías tener el error, mirar si tiene un error y tal.
Eso te lo voy a dejar de deberes para que lo hagas tú.
Vale, ahora vemos que sí, que primero carga,
tenemos los comentarios y aquí, pues, vamos a comentar.
Dime algo bonito, le damos a enviar comentario.
Fíjate que ahora sí que podemos ver que visualmente está pasando algo,
pero cuando termina, se queda esto aquí y aquí no aparece nada.
Te voy a explicar tres formas de cómo arreglar esto
y te voy a explicar de la menos favorita a la más favorita, ¿vale?
Y tú decides cuál es la que te guste más y tal.
Una, aquí podéis tener un unsuccess,
o sea que cuando todo ha funcionado correctamente podéis hacer algo, ¿no?
Una forma que podéis hacer, podríais actualizar el caché,
el caché de React Query manualmente.
Para eso tendríamos que acceder a la Query Client,
podríamos traernos aquí Use Query Client,
esto no me acuerdo si es con dos o con una,
bueno, vamos a verlo.
Es que no me da el autocomplete, a ver.
Es que ahora, sí, sí, sí, es así, vale, perfecto.
Query Client.
Bueno, pues tenemos aquí el Query Client
y lo que podríamos hacer es como setear manualmente la caché,
o sea, decir, vale, cuando ha sido success,
se lo enseño al usuario, ¿no?
Hago un Query Client, punto, set Query Data
y sabiendo cuál es la key, que es esta, ¿vale?
Esta es la key, esta es la key,
podemos decir, vale, pues la key de comments,
lo que quiero que hagas con el all data que yo tenía por aquí,
vamos a cambiar el all data,
vamos a añadir, bueno, primero, si el all data es null,
entonces devuelvo directamente un array con el nuevo comentario, ¿vale?
El new comment, que esto nos lo tiene que devolver el onSuccess, ¿vale?
El new comment lo tenemos aquí, ¿vale?
Y si ya teníamos datos, pues nada, lo concatenamos
y al menos lo vamos a poder ver.
Lo veremos mucho más rápido, no tenemos que estar preocupados ahí.
Esto tenemos que poner aquí una sync, ¿vale?
Ahí la wait.
Este all data que nos dice que no sabe lo que es,
esto es, debería ser esto de aquí,
es un array con los comentarios con la idea,
de que se queja, porque esto puede ser undefined, ¿vale?
Esta sería una forma, ¿vale?
Esta sería, número uno,
actualizar el cache de React Query manualmente.
O sea, esto, lo que debería hacer,
si lo hemos hecho todo bien,
todo bien, sí o no, ¿vale?
Enviar comentario,
es que cuando termina, manualmente, lo ponemos aquí.
Lo que hemos hecho es evitarnos
tener que hacer un refetching de datos,
sino que como tenemos toda la información que necesitamos,
pues nada, lo mostramos ahí y ya está.
Así, mucho más fácil,
nos despreocupamos y ya lo tenemos.
Segunda forma que se podría hacer,
y depende, claro, ¿cuál es la perfecta y tal?
Es que depende, depende de
si puedes tener toda la información
para mostrarse al usuario.
La segunda sería hacer otra vez
un refetch de la query, ¿sabes?
En lugar de actualizar tú manualmente los datos,
porque imagínate que la API,
cuando creas el recurso,
tiene alguna información que tú no tienes en el cliente,
pues bueno, le dices,
oye, Query Client,
quiero que invalides las queries
que tiene la query key, la de comentarios, ¿vale?
Cuando tienes los comentarios estos,
cuando ha terminado la mutación y ha sido con éxito,
quiero que invalides las queries
que tengan la key de comments.
Y esto, ¿qué es lo que hará?
Pues que ahora hace refetch, ¿vale?
Si quitamos esto aquí, ¿vale?
Enviar comentario, hace el fetching de datos, ¿vale?
Aquí vemos que está enviando la información.
Y ahora cuando termine,
lo que vemos es que ha vuelto a hacer un fetching de datos
y esto lo ha traído de la API.
Si vemos la respuesta aquí,
veremos que en este récord
tenemos ahora, ahora hace refetch,
se lo ha traído de la API directamente.
Que no está mal, o sea, está, tiene sentido, ¿vale?
Esta sería la segunda forma de hacerlo.
De nuevo, no hay una perfecta y otra regular,
es que depende de bastantes cosas.
Y luego estaría la tercera,
que sería, claro,
porque como podéis ver, tarda bastante.
O sea, es que hacen la petición
y entonces después es que se enseña y tal.
Habría una tercera,
que es el hecho de hacer actualizaciones optimistas.
O sea, ser optimista de que todo va a ir bien
y rápidamente enseñarle al usuario
de que, oye, vamos a ponerle el nuevo comentario ahí
sin ningún tipo de problema.
Así que lo que podemos hacer aquí
es que cuando lo vamos a mutar,
pues decir, vale,
vamos a cancelar primero todas las queries,
vamos a cancelar todas las queries de comentarios,
las de refetching,
porque puede entrar si no en problemas.
O sea, si tú, mientras haces la mutación,
estás haciendo un fetching de datos,
a lo mejor hay algún tipo de que va a haber
una cosa diferente el usuario.
O sea, vamos a cancelarla
porque si no, la podemos liar.
Cancelamos el refetching de datos
y esperamos para después de la mutación.
Aquí podemos tener los comentarios previos,
los recuperamos del query data.
Esto sería leer la caché
para tener los comentarios anteriores.
Tenemos los comentarios anteriores
y luego hacemos lo que habíamos hecho aquí.
En lugar de hacerlo aquí,
lo hacemos a la hora de la mutación,
antes de hacer el fetching de datos.
Así que ahora, visualmente,
el usuario verá rápidamente de,
ostras, qué bien que estoy teniendo aquí
la información rápidamente.
De hecho, este set query data
ni siquiera hace falta
porque esto lo sacamos de aquí
y previous comments,
a ver qué dice aquí,
previous comments,
método an iterator.
Ah, porque esto en realidad,
claro, esto en realidad
es lo que vamos a devolver.
Esto no lo vamos a usar así,
esto lo vamos a usar aquí,
old data, ¿vale?
Y este old data
es el que vamos a usar aquí, ¿vale?
Y este old data
pero qué raro, ¿no?
Otra vez se me queja aquí.
Tiene que devolver type
más bien iterator.
Ah, este type script.
Vale.
Esto, ¿esto por qué lo hacemos?
Esto lo hacemos
para guardar el estado previo
por si tenemos que hacer
un rollback.
Porque imagínate que
todo optimistamente,
optimísticamente,
todo va bien,
le cambiamos la UI
y luego falla algo.
Pues entonces la vamos
a liar parda.
No sé por qué aquí
esto me falla.
Comment with id.
No sé si lo tenemos
que tipar exactamente.
Pero ves que no me está
tipando exactamente
esto igual.
A ver, argument,
updater,
pues undefined.
Is not as new type,
type undefined.
Porque creo que aquí,
claro,
porque aquí
cuando se muta
el new comment
es del tipo comment.
O sea, esto
no tiene la idea.
Pero igualmente
tampoco le gusta.
Bueno, vamos a ver
si funciona
y luego miraré
a ver cuál es
el problema del tipo.
Porque yo juraría
que esto debería funcionar bien.
Bueno, esto sería
antes de hacer
el fetching de datos,
antes de llegar
a la base de datos.
O sea, le vamos a actualizar
los datos al usuario
antes, ¿no?
Ahora, ¿qué pasa?
Que imagínate
que hay un error,
por lo que sea peta
o yo qué sé.
Pues lo que puedes hacer
con esto
es acceder
a los comentarios anteriores.
¿Ves que estos comentarios
los estamos devolviendo aquí?
Esto va directamente
a una cosa
que se llama context
y está chulo
porque aquí
cuando tengas el error
puedes decir, bueno,
si el error
es diferente
a null,
vamos a mirar aquí.
Bueno, a ver,
el error
lo vamos a tener seguro.
O sea, que vamos a poner
console error error.
No sé si esto
se quejará
por el typescript.
No, vale.
Si ha habido un error,
pues lo que podemos decir
es, oye,
pues nada,
vuelve a poner
en la caché
los comentarios
que teníamos
del context.
En el context,
¿ves que tenemos aquí
el previous comments?
Pues este context
vamos a poder acceder
justamente a esto.
Le ponemos esto
porque esto puede ser null
por si no ha pasado por aquí
y ya está.
Si tenemos previous comments,
de hecho,
podemos hacerlo así.
Si tenemos previous comments,
porque podríamos tener
otro tipo de error,
entonces
vamos a decir
que esto sea
diferente a null.
¿Es posible?
Ah, claro.
Esto sí.
¿Vale?
Different animal,
previous comments.
Y ya está.
Con el onSuccess
también lo que podríamos hacer
para asegurarte
que estás enviando bien
la información,
en el onSettle,
cuando ya terminamos del todo,
podríamos juntarlas todas.
Entonces ya podríamos hacer
la invalidación
que habíamos hecho antes
para asegurarnos
que estamos teniendo
la información
de la base de datos.
O sea,
visualmente el usuario
ha visto que todo se ha cargado,
pero luego
hacemos el refetching
sin que se dé cuenta
para asegurarnos
que todo ha ido bien.
Seqquery no lleva
la way midu.
Etc.
Seqquery.
Pues es verdad
que no devuelve una promesa.
Por ahí puede tener sentido.
Bueno,
vamos a ver si chuta.
Vamos a ver si chuta.
Vale.
Vamos a ver si chuta.
¿Chutas?
¿Chutas o no chutas?
Envía el comentario.
Vale, ¿veis?
Ha sido inmediato.
Lo vemos ahí.
Esto está terminando aquí.
O sea,
todavía está haciendo
el fetching de datos.
Ha terminado el fetching de datos
y ha mantenido esto aquí.
Vamos a mirar aquí.
Esto habrá cambiado
porque ahora tendrá
bastante más información.
Vamos a quitar
la información esta.
Vamos a volver
a reiniciar esto.
Vale.
Lo ponemos por aquí,
por aquí.
Update bin.
Ahora cuando volvamos.
Esto debería hacer un fetching.
Ahora eso tenemos este.
¿Veis?
Que ha hecho
el refetching de los datos.
Vamos a ver si chuta.
Chutas.
Le doy a enviar comentario.
Visualmente ya lo tenemos aquí
pero está todavía terminando
de hacer peticiones aquí
para hacer la revalidación
y lo mantiene
porque es justamente
lo que ha encontrado
la base de datos.
Y esto está muy chulo
porque, a ver,
esto podríais hacer
un montón de cosas.
Por ejemplo,
en lugar del disable
y tal que hemos hecho,
en lugar de desactivarlo,
lo que podríamos hacer
es mostrar aquí
el toaster este,
el somar,
toast,
este que me gusta.
Joder,
qué buena pinta tiene todo esto.
Ahora no me acuerdo
cómo se llama
esta tostada de...
No me acuerdo.
Yo creo que es Sommer.
Pero bueno,
podéis buscarlo
para enviar las notificaciones
y que cuando le deis
pues se ve.
Esto es
actualización optimista
de la UI
y cómo lo ve
un cliente de última opción
si hay un error.
Si hay un error,
claro,
¿cómo podríamos hacerlo
del error?
Porque hemos hecho
esto del refetch.
A ver,
podríamos hacer fácilmente aquí
de hacer un throw new error,
¿no?
Throw new error
y aquí decir
not implemented...
Vamos a poner
not implemented yet
por decir algo.
Chuta.
Chuta.
Ni siquiera lo pone.
No lo pone
porque no le da tiempo.
Si ponemos un delay,
vamos a ver
si podemos poner un delay.
A ver si lo vemos.
A ver si poniendo un delay
somos capaces de verlo.
Esperamos mil
y luego tal.
Vale.
Cargando.
Ponemos esto por aquí.
Vale,
¿ves?
¿Lo ves?
Ya no lo ves.
¿Lo ves?
Ya no lo ves.
¿Por qué?
Porque ha habido un error.
Parece que iba a ir bien,
te lo muestra ahí.
De hecho,
te lo muestra ahí
y podrías hacer un montón de cosas
para que lo muestre de otra forma.
Por ejemplo,
imagínate que quieres que se vea
como que es temporal.
Pues cuando ponemos aquí
el nuevo comentario,
cuando ponemos el new comment
aquí,
podríamos poner
new comment to add.
¿Vale?
Vamos a poner un structure clone
de new comment
y vamos a poner
que el new comment
to add
preview
le ponemos true.
¿Vale?
True.
Esto le falta tipos,
¿vale?
Porque es normal,
porque se lo estoy añadiendo aquí
a saco
y no tiene la interfaz esto.
Pero ahora
vas a ver una cosa
muy chula
que puedes hacer
y que queda brutal
y le quita un montón de magia
cómo funcionan
un montón de cosas
en internet.
A ver,
cuando tenemos aquí
los resultados
en el data,
en el data
estos resultados
debería
tener ahora
un preview
y por lo tanto
nosotros
vamos a hacer esto.
Vamos a decirle
que si el article
punto preview
es igual
a true,
vamos a poner
que esto
sea gray
¿Vale?
Y si no
vamos a poner
que es white.
El article
preview
true
no sé qué
no sé cuánto.
Esto por acá,
esto por acá.
Vale.
Me falta
en algún sitio
esto
es que esto
es lo malo
de aquí.
Vale.
Ya está.
Article punto preview
bueno,
article se me va a quejar
de que no tiene
el preview
pero es por los tipos
de datos.
¿Vale?
Article
no sé qué.
Vale.
Vale.
No le ha gustado
un poco.
¿Por qué?
Ah,
porque es comment
no es article
perdón.
Es comment.
Comment.
¿Vale?
Comment.
Vale.
Pon
uno.
Vale.
¿Ves que tenía
otro fondo?
Tiene un fondo
diferente
porque hemos sido
capaces
de alguna forma
de decirle
bueno,
si por lo que sea
yo lo añado
mientras
¿ves?
Tiene un fondo
diferente
que le puedes
poner ahí
que es preview
que está cargando
puedes poner una animación
puedes hacer lo que tú quieras
y que entonces
espere
que una vez
que aparezca
pues se quede
y le cambie el fondo
o que no se lo cambie
y así
pues queda bastante chulo
porque puedes
visualmente
indicarle al usuario
oye
esto te lo pongo aquí
que es como va a quedar
pero todavía no está
esto es una cosa
que hace por ejemplo
Twitter
¿ves?
Y ahora cuando ya sé que está
entonces cambia
esto está tremendo
porque al final
lo que tienes aquí
es una forma
súper potente
de indicarle al usuario
de oye
esto es como va a quedar
esto es lo que está haciendo
pero todavía no está del todo
¿vale?
Así que ahí lo tienes
como los mensajes de Slack
también cuando nos envían
exactamente lo mismo
pero no vuela la cabeza
cómo cambian las cosas
en ese sentido
de que habéis sido capaces
como de
quitarle esa magia
porque muchas veces
es que también nos quejamos
de que hacemos contenido
siempre para aprender
siempre desde cero
siempre no sé qué
y hacemos estas cosas
y luego entonces nos asustamos
decimos
no es que no es muy difícil
o lo que sea
y yo creo que es súper interesante
porque tampoco es tan difícil
hay que tener un poco de paciencia
para entender algunas cositas
pero creo que vale mucho la pena
porque son luego las cosas
que marcan la diferencia
y lo que no es simplemente
a las cosas
ind aspectivas
entonces
todo creo que es algo
así el tema
ahora
sino
también
ha ido
por nosotros
ya
pero