logo

midudev


Transcribed podcasts: 167
Time transcribed: 5d 15h 37m 28s

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

¿De qué va a ser la clase de hoy?
Bueno, nuestro curso va sobre Next.js,
pero ya dijimos que íbamos a empezar a utilizar también Firebase,
sobre todo para el tema de la base de datos,
para crear nuestro clon de Twitter.
Así que la clase de hoy vamos a empezar a ser capaces de crear tweets,
que nosotros le llamamos Debits, ¿no?
Porque nuestra aplicación se llama Depter,
y lo que vamos a lograr es crear los tweets y mostrarlos.
Hoy vamos a hacer que la clase, vamos a ver si no dura dos horas,
va a ser un poquito más cortita, ya que estamos de vacaciones
y así todo el mundo se lo toma más ligero.
Pero vamos a hacer esto.
Entonces, aquí tenemos el repositorio
donde está todo el código de todas las clases.
Cada clase que hemos hecho de este curso de Next.js,
tenemos el primero, el donde hicimos el login con GitHub,
el tercero que creamos un poquito más la página de la Home
y configuramos Slint y Prettier e hicimos un repaso súper exhaustivo.
Y hoy vamos a hacer Firebase para utilizar Cloud Store.
¿Cloud Store? ¿Cómo es esto?
Ahora era Cloud Store o ahora no me acuerdo cómo se llamaba.
Cloud Store, ¿no?
A ver, Firebase Cloud Store.
Eso, Cloud Store.
Ay, Cloud Store no, es Cloud Fire Store, ¿vale?
Le he cambiado el nombre.
Ya decía yo que no me sonaba Cloud Store.
Es que Cloud Store se lo he puesto en la imagen y ya me ha liado.
Es Cloud Fire Store.
Esta base de datos, digamos que hay dos bases de datos en Firebase.
Una es esta y otra es la de Real Time Database.
La de Real Time es la más antigua y esta es la más moderna.
Tiene algunas diferencias, las iremos comentando.
Pero por ahora lo importante es que sepáis que aquí tenéis todo el código.
Podéis mirarlo en mi GitHub, en midu.dev.
Me podéis seguir y ahí vais viendo todos los repositorios que tengo,
pero este es uno.
Si es un poco raro, pues también podéis ir a mi web midu.dev
y aquí también tenéis todas las clases que hemos ido haciendo, ¿vale?
Y tenéis también todos los enlaces, también tenéis el enlace del repositorio y tal.
Así que vamos a ver si empezamos ya con la clase porque tenemos un montón de cosas que ir arreglando
que se han quedado a medias.
Así que vamos a arreglar algunas cositas antes de empezar a utilizar esta base de datos.
Así que vamos a ir al proyecto y lo que voy a hacer, esto, aquí tengo mi terminal.
Voy a cerrar esto por aquí y vamos a ver, voy a cerrar esto por aquí.
Voy a abrir mi editor, que yo utilizo Visual Studio Code, pero el que queráis.
Vale, ya lo tenía abierto por aquí.
Entonces, lo primero que voy a hacer, voy a seguir las clases como si cualquiera de ustedes
pues quisiera seguir la clase.
¿Qué es lo que deberíamos hacer?
Vale, lo que deberíamos hacer es ir a GitHub, os clonáis el repositorio y tal,
y vais a la última rama de la clase, o sea, la anterior a esta.
En este caso, la 3.
Así que esta, que es 0.3, addlin, bla, bla, bla.
Esta sería la rama.
Vamos a volver a nuestro proyecto y lo que vamos a hacer es hacer un git checkout
de esta rama, que es 0.3, guión, addlin, amplitude and bold.
Así vamos a estar justamente donde se quedó la clase anterior.
Ahora ya aquí tenemos nuestro proyecto.
Pues lo que vamos a hacer es un MPM RAM para ver todos los scripts
y ya vemos que tenemos el modo desarrollo.
Pues MPM RAM DEV.
Y con esto nos va a levantar el entorno de desarrollo de nuestra aplicación.
Y vamos a ver cómo lo dejamos, cómo se quedó y todo esto.
Vale, ya se ha compilado.
Vamos a ver cómo estaba.
Vamos al puerto 3000.
Voy a quitar por ahora las herramientas de desarrollo.
Y esta es nuestra aplicación, ¿vale?
En este caso, pues, si os acordáis, hicimos un approach mobile first.
Todo el diseño va a ser primero mobile.
Aquí nos faltaba un enlace para ir a la home,
porque habíamos creado ya la página home, aunque lo que estábamos enseñando en la home
no era del todo correcto, ¿no?
Es muy parecido a Twitter, pero por ahora no se ve casi nada, ¿no?
Y además hay algunos fallos de maquetación.
Esto es lo primero que vamos a arreglar hoy para dejar esto que todavía se vea mucho mejor.
Entonces, os quiero agradecer, bueno, le quiero agradecer a alguien que hizo una pull request
porque os comenté de si alguien se animaba que arreglase estos problemas.
Entonces, Agusazar se animó, Agustín, se animó desde Argentina
y nos hizo, pues, un fix para el header y tal.
Y la verdad es que tiene cosas interesantes, pero vamos a hacerlo de una forma distinta.
Aún así, la pull request está aquí, por si le queréis echar un vistazo
y queréis ver cómo lo propuso Agustín, ¿vale?
En nuestro caso lo vamos a hacer un poco distinto
porque vamos a seguir haciendo el sticky
y yo creo que debería funcionar bien.
Así que alguien me pregunta, ¿tiene gripe?
No, no tengo gripe.
El tema es que en el hotel en el que estuve en mis vacaciones
el aire acondicionado estaba roto
y estaba como a 19 grados.
Entonces, durmiendo allí, el caso es que me...
Bueno, no sé, tengo un resfriado y tal.
Tengo la voz un poco pillada.
Pero no tengo fiebre, no tengo absolutamente nada,
no tengo corona Voldemort, estoy bien, estoy bien.
Entonces, no os preocupéis que estoy bien.
Solo estoy así como pillada la voz por el frío que pase.
Por más que me tape, no veo forma.
Vale, entonces, vamos con esto.
Vamos a ver si arreglamos un poco el estropicio este.
Que el header no quedaba bien.
Bueno, el header al final sí quedaba más o menos,
pero además aquí se puede ver que la parte de abajo
también estaba mal.
Bueno, pues vamos a ir arreglando cosas, ¿vale?
Tanto la redirección a la home, cuando uno se loguea,
que es lo que dijimos que es lo que hace Twitter, ¿no?
Cuando en Twitter entras, directamente te lleva a la home.
Aparece un momento ahí como lo del Twitter
y luego carga y te lleva.
Está haciendo la redirección parece que en el cliente.
O sea, que vamos a hacer algo similar.
Entonces, vamos a empezar por ahí.
Vamos a hacer la redirección a la home,
que esto es muy sencillo.
Y luego seguimos con lo otro.
La redirección de la home la tenemos que hacer
en el index.js.
Aquí lo que deberíamos tener es si tenemos el usuario
y todo esto, ¿vale?
Y aquí mirábamos si teníamos el usuario, ¿vale?
Hacíamos el on out state change.
Entonces, cuando cambiaba, que esto viene de Firebase,
cambiamos el estado.
Aquí lo que podríamos hacer simplemente es añadir otro efecto.
De forma que cuando cambie el usuario,
pues, utilizaremos el router para redirigir al usuario
fuera de la home, ¿no?
Si ya, de esta forma, esto ya no tendrá sentido.
Esto que mostramos aquí, pues, ya no tendrá sentido.
Pero, bueno, le redirigimos a un sitio que tiene más sentido,
va, al usuario, ¿no?
Entonces, vamos a hacer esto.
Que si el usuario, si tenemos un usuario
y este efecto debería ejecutarse cada vez que cambie el usuario,
¿vale?
Si tenemos un usuario, vamos a utilizar el router
y vamos a reemplazar la ruta.
Y la vamos a reemplazar para que vaya a barra home.
¿De dónde aparece este router, no?
Pues, esto lo vimos en la primera clase.
Y es que Next.js ya el router lo tiene incorporado, ¿no?
No tenemos que instalar RealRouter ni nada.
Porque las rutas vienen por este sistema de archivos de las páginas.
Así que el router lo vamos a conseguir utilizando el useRouter,
que es un hook que tiene Next.js.
Así que lo importamos de next barra router.
Y tenemos que utilizar este hook para conseguir este router.
UseRouter, lo ejecutamos aquí.
Y ya tenemos este router que podemos llamar para hacer un replace
de la URL que estamos viendo.
Solo si tenemos usuario.
¿Qué pasa?
Si no está logueado el usuario, esto será undefined,
como podemos ver aquí al principio, es undefined,
cuando no sabemos si el usuario se ha logado o no.
Y luego, si no está, si por lo que sea se desconecta lo que sea
o parece que no está logado, será nul.
Así que, en este caso, lo que vamos a hacer es solo cuando sea truci,
que en este caso sería un objeto, y nos reemplazaría la URL.
Sería como una redirección del cliente, ¿no?
Reemplazar en lugar de hacer un push.
Y iríamos a la home.
Vamos a guardar los cambios, a ver si esto funciona como esperamos.
Vale, ya podemos ver que lo ha hecho, ¿no?
Así que vamos otra vez aquí a la home para verlo rápidamente.
Pero si intentamos ir a la home, cuando aparece el avatar,
pues nos redirecciona.
Esto sería un poco lo que hace Twitter, ¿no?
Que en cuanto nota que ya es un usuario que está logado,
pues lo que hace es mandarte a la home.
Pues esto mismo, lo que podemos hacer es darle un poquito más de gracia, ¿no?
O sea, en lugar de utilizar el avatar este, lo que voy a hacer,
porque, claro, esto ya no tiene sentido.
Lo que podríamos hacer aquí, en lugar de esto,
es que si no sabemos si el usuario está logado,
pues enseñar el cargando.
Creo que Twitter hace algo similar.
Bueno, ahí lo veis, ¿no?
Que ha habido un momento ahí que hace un cargando, ¿no?
Lo que podríamos hacer es, si no, el usuario no está logado,
enseñamos el botón para que se logue.
Y si es undefined, que todavía no sabemos si está logado o qué,
que es como el estado inicial que tenemos,
aquí podemos enseñar, pues, un loading.
A ver, esto lo podemos hacer así,
podríamos tener un spinner, podríamos tener un montón de cosas.
Vamos a verlo aquí otra vez.
Vale, sale el loading, ahí se ve muy poquito, es súper rápido.
Me he preparado por aquí, me he preparado por aquí un spinner, ¿vale?
Y me lo voy a poner aquí en public para utilizarlo.
Es este spinner, es el típico.
Y este spinner lo vamos a utilizar aquí, ¿vale?
Como has podido ver, lo he movido a la carpeta public,
porque esta carpeta public es especial en Next.js,
que lo que hace es que estos estáticos los tienes disponibles
ya desde la raíz.
O sea, si yo aquí ahora en Image,
hacemos un source y hacemos barra spinner.gif
y ya borramos todo esto para que quede así directamente, ¿vale?
Vamos a poner esto aquí que se lea un poquito mejor, ¿vale?
Guardamos los cambios y aquí, pues, si vamos a la home,
pues veremos, bueno, se ve muy poquito, ¿vale?
Se ve muy poquito, pero aquí, por aquí abajo, se ve, ¿vale?
Bueno, por ahora lo vamos a dejar así y más adelante seguramente
haremos algún cambio más, haremos alguna transformación
para que la home, pues, salga el logo en medio y solo el loading
y dependiendo si está logado o no, que haga una animación
para mostrar la home que es para iniciar la sesión
o directamente que traiga al usuario a la home, ¿vale?
Y así, pues, será un poquito más interesante.
Esto lo dejamos aquí así, ¿vale?
Porque ya tenemos este replays, que es la redirección
para nuestro usuario y ya está.
Hay una cosa aquí que se nos quedó, que este era cuando hacíamos
el login con GitHub, que hacíamos, resolvíamos la promesa
y hacíamos un set user.
Esto como tal ya no es necesario porque si miramos el login
with GitHub, veremos que aquí ya no necesitábamos hacer esto
porque en realidad ya estábamos escuchando el evento
de cuando cambiaba la autentificación.
Y cuando eso lo hacía, lo estábamos haciendo aquí,
ya estábamos haciendo el set user, así que ahí no lo necesitamos.
Así que vamos a guardar los cambios quitando eso y fuera.
Vamos a arreglar el problema del header, ¿vale?
Lo primero que voy a hacer para que salgan todos los problemas
que tiene este layout, lo primero que voy a hacer es en la API,
aquí es donde teníamos todos los tweets de prueba
que estábamos mostrando estos tres.
Los voy a volver a copiar y voy a hacer que aparezcan un montón, ¿vale?
Porque de esta forma vamos a ver el scroll,
a ver qué problemas nos aparecen y tal.
Así que voy a guardar los cambios, son los mismos tweets pero repetidos.
Hacemos aquí un refresh y, bueno, ya podemos ver que aquí hay
un montón de problemas. ¿Por qué?
Porque lo que queríamos era que este contenido se quedase dentro,
pero podemos ver que esto lo está reventando,
se está quedando por fuera.
Tiene muchos problemas este layout.
Es verdad que cuando se hace chiquitito, pues ya no se nota, ¿vale?
Pero sí que no está funcionando bien.
Así que lo tenemos que arreglar.
Así que antes de pasar a arreglarlo, voy a leer vuestros comentarios
y seguimos nada en un momentito.
Vamos a ver qué me estáis comentando.
Pupi Martí, ¿es más óptimo un GIF, un SVG o un DIF con CSS para el spinner?
Muy buena pregunta.
Lo cierto es que, bueno, depende, depende un poco de la animación.
En este caso seguramente sería mejor, por ejemplo, un CSS
y quedaría mucho más bonito y se podría hacer tan grande como quisiéramos.
De hecho, podríamos hacer que fuese con spans y entonces con animaciones,
porque este GIF, si lo hacemos un poquito más grande,
pues empezaría a perder calidad, se vería bastante mal.
Además, no tiene mucho sentido utilizar una imagen
para algo que sea de cargando.
¿Por qué?
Porque cuando mostramos la imagen, la imagen se tiene que cargar
y entonces se pierde un momento en el que se muestra la imagen.
Mientras se descarga la imagen no puede mostrarse.
Entonces, normalmente, es mejor utilizar HTML en este caso.
Pero ¿qué pasa?
Que hay veces que queremos animaciones muy complejas.
Pues entonces es posible que queramos utilizar SVG en este caso.
En este caso, mi recomendación no es utilizar GIF,
pero he considerado que íbamos a ir mucho más rápido si poníamos ese GIF.
Quizá más adelante lo cambiamos por un CSS,
si lo vemos así interesante.
Pero bueno, por ahora era para no enfocarnos tanto en el problema de spinner
y no perder tiempo en eso, ¿vale?
Entonces, Cracks4 dice, ¿y el Stream Deck?
Mira, aquí lo tienes, el Stream Deck.
Aquí lo tienes, aquí lo tienes.
Míralo.
¡Ay, ay, ay!
Al final la voy a leer.
Aquí está, el Stream Deck, ¿vale?
Todavía no lo tengo muy configurado, ¿vale?
Pero estoy encantado.
Bueno, ahora me lo he cargado.
Porque esto va con una base como para que quede, ahora ya está,
para que quede mirando a ti y poder darle a los botoncitos.
Pero es una maravilla, mira.
Le doy a los botones súper rápido y va cambiando.
¡Pum, pum, pum!
Genial.
Muchas gracias, Cracks.
Y muchas gracias a todos los que habéis contribuido.
Claro, aquí me comentaba Brian, me dice,
¿podrías hacer algún ejemplo en XGS con Firebase algún día?
Saludos desde Uruguay.
Pues, Brian, estamos haciendo justamente eso.
Bueno, a ver, ahora vamos a arreglar los estilos de la app para que quede bien.
Pero, nada, en cuanto terminemos eso,
lo que vamos a hacer es utilizar Firestore para guardar los tweets
y luego para leerlos.
Así que quédate porque yo creo que es interesante.
Y ya utilizamos Firebase en esta serie de vídeos para hacer el login con GitHub.
Vamos a utilizar Firebase siempre que podamos.
Más adelante lo vamos a seguir usando, ¿vale?
¿Dejaste de usar el Magic Mouse?
Pues, sí, me han dejado un nuevo mouse que me prometieron que iba a ser increíble,
que es el Razor Death Adder, no sé qué.
Es como de gaming y yo la verdad es que juego bastante.
Y me gusta, está bastante bien, pero he hecho de menos todavía los gestos.
No estoy del todo todavía acostumbrado.
Así que por ahora sí, por ahora sí.
¿Qué más?
¿Qué más se está diciendo por aquí?
No te has perdido nada, Ricardo, tranqui.
Esto estamos aquí empezando casi.
Y, ¿qué más?
Vale, Diego Artiles dice,
Midu, yo cuando veo una variable que es igual a null y en otro lado esa misma variable,
igual a define, siento que se puede mejorar.
Siempre tiendo a usar la negación variable para homologar estas condiciones.
¿Está bien eso?
Pues, me parece muy interesante lo que comentas, Diego.
Realmente sí que se podría mejorar el código que tenemos.
Por ejemplo, mira, vámonos aquí.
Y no lo vamos a hacer, pero te explico lo que se podría llegar a hacer y que creo que podría ser interesante respecto a lo que comentas.
En lugar de utilizar null y undefined, que semánticamente tienen sentido, ¿vale?
Porque undefined es como que no está definido y, por lo tanto, no sé qué valor es.
No es un valor porque no está definido.
O sea, sintácticamente hablando sobre el usuario que sea undefined tiene sentido.
Luego, null sí que es un valor, solo que es nulo.
O sea, que sí que es un valor.
O sea, semánticamente tiene sentido.
Un usuario que no está logueado es nulo porque no tiene información.
O sea, que tendría sentido y luego puede ser un objeto.
Entonces, es verdad que, aunque semánticamente, pensando en eso, tiene sentido, se le podría dar una vuelta a todo esto.
¿Esto qué quiere decir?
Que en lugar de undefined podríamos ser más, ¿cómo decirlo?
Que esto pueda ser más legible.
Entonces, de esta forma podríamos tener aquí un user state, por ejemplo.
Que sea not logged, pues esto que sea el null, por ejemplo.
Y el I don't know, por ejemplo, o not known, ¿sabes?
Que no lo sabemos, que sea el undefined.
De esta forma, lo que podríamos llegar a hacer es que fuese más legible, ¿no?
Porque podríamos decir que no lo sabemos y luego el user state aquí, cuando hacemos este igual, se le iría mucho mejor.
Si viene un compañero nuestro, pues podríamos decir user states punto y aquí decir el null es que no está logado.
Pero ya no vemos el null, ya no tenemos que doble pensar.
Y ahora se lee mucho mejor.
Una vez que ya tenemos definidos estos estados, pues es mucho mejor, más fácil.
Ay, esto sería not known, ¿vale?
¿No lo sabemos?
Pues estamos cargando.
Que no está logado, pues enseñamos el botón.
Que sí que está logado, pues entonces cambiamos los estados.
Y de esta forma, pues creo que se puede leer mejor.
Y esto lo mejoraría.
Entonces, sobre el que dices de utilizar el no, puede tener sentido a veces, cuando sobre todo confía mucho en el truci y en el falsi.
Pero en este caso no lo podemos hacer porque, como he dicho semánticamente, un undefined y un null para nosotros tiene diferentes sentidos o contextos, ¿no?
Pero con esto, pues ya te lo evitarías, ¿no?
Sería mucho más explícito respecto a qué te refieres cuando estás haciendo esta comparación, ¿no?
Decir, oye, cuando el usuario no está logado, hago esto.
Y creo que sería seguramente la mejor forma de hacerlo, ¿eh?
Tener así como un enum donde te pueda ayudar a hacer esto.
No sé si esto ha contestado tu pregunta.
Lo vamos a dejar así.
De hecho, vamos a probar que no he roto nada, que soy capaz.
Pero sí, parece que funciona bien.
Por aquí irían un poco los temas.
César dice, una imagen sería lo menos óptimo y aquí te hace una request.
Y es verdad.
No sería mi recomendación, la verdad.
¿Vale?
Vale, vale.
Pues, ¿qué más aquí?
¿Qué más me comentáis?
¿Qué piensas de soluciones como React Query?
Pues que es súper interesante.
Joe Sudame.
Me parece muy, muy, muy interesante.
¿No vas a ver el partido de Barcelona?
No creo.
La verdad es que el fútbol, le he perdido bastante toque al fútbol, ¿eh?
Ya no lo veo tanto.
NextYes puede trabajar 100% como una SPA.
Puede trabajar como una SPA sin ningún problema.
De hecho, aquí está trabajando como una SPA sin ningún tipo de problema.
Ya vimos cómo hacerlo porque hay que utilizar el NextLink y todo esto.
¿Vale?
Vale.
¿Qué más?
Diego Artiles dice, tengo consulta sobre React.
¿Por qué siento que cuando hay un onclick function,
dicha function se ejecuta al iniciar el componente,
pero si lo pongo así, siento que no lo hace?
Perfecto.
Gracias por la explicación.
Vale.
A ver.
No se ejecuta.
Supongo que lo dice.
Vamos a ver si tenemos aquí algún onclick.
Este onclick aquí.
Lo que se refiere Diego se refiere a este onclick y tenemos este handleclick.
Esto no se está ejecutando cuando se inicia el componente,
lo cual tiene sentido, ¿no?
Porque le estamos pasando la función, no la ejecución.
Si hiciésemos esto, sí que lo estuviéramos ejecutando y estaría mal,
porque estaríamos ejecutando el handleclick cuando se renderiza el componente.
Esto está mal.
Lo que le estamos pasando aquí es la referencia de la función,
la función como si fuese una variable.
Esta es la función que tienes que ejecutar.
No la estamos ejecutando.
Así que tienes que tener en cuenta que no se está ejecutando al iniciar el componente.
No se está ejecutando.
En realidad esto es como si diciésemos esto.
Es lo mismo.
Aquí le estamos pasando a la función, pues imaginemos que esta función la tenemos una constante
que se llama handleclick.
Así que es lo mismo, ¿vale?
Y vale, aquí he dejado esto.
Perfecto.
Pues creo que más o menos he intentado hacer en diagonal, he leído por ahí.
Vamos a seguir, vamos a seguir.
Vamos a arreglar ahora sí los estilos, porque el header este, pues obviamente no puede quedar así.
¿Dónde habíamos dejado?
Estos estilos estaban en la home.
Vale, aquí.
Pues vamos a darle aquí.
Vamos a arreglar este header.
Lo primero es que esto está muy pegado.
Esto sería una tontería.
Esto es el H2 que dejamos aquí.
Esto lo arreglamos en un momento con el padding left este.
Perfecto.
Fácil.
Así queda un poquito alineado.
Luego, lo que veo aquí es que este salto lo hicimos intentando que el header quedase
bien y no sé qué.
Bueno, esto creo que es esto y esto lo podemos eliminar sin ningún problema.
Otro problema es este que, claro, no le habíamos puesto background al header.
Esto es bastante obvio.
Así que le vamos a poner que sea...
Vamos a hacer algo con esto, ya que le vamos a poner que sea blanco y por darle un detallito.
Vamos a hacer que sea sensiblemente un poco... que tenga un poquito de opacidad.
Que, bueno, queda así, pero le podemos hacer el truco este del back, drop, el filter.
Y esto le va a hacer un efecto...
¿Hay filter?
Sí.
No, filter, backdrop, blur.
Es blur, no, filter.
Vale.
Y a ver ahora si esto...
No, no es backdrop.
A ver, backdrop, backdrop.
A ver cómo era esto.
Backdrop.
Claro, es que como no tengo lo autocompletado, es backdrop, backdrop, filter.
Creo que es así.
Vale.
Ahora sí.
Vale.
Lo que podemos ver con esto...
Bueno, no se ve casi.
Igual vamos a bajarle un poco más la opacidad para que se vea.
Pero bueno, hace el efecto blur este, ¿no?
Este efecto blur de Apple.
Bueno, por darle un detallito.
Así se nota que está pasando por encima.
Si preferís este o si preferís directamente de la opacidad, pues opacidad ya está.
Esto sería para la top bar.
Vale.
Y además el border bottom este que hemos dejado aquí tan oscuro, lo vamos a dejar un
poco más claro.
Y esto lo vamos a hacer con todos, porque también el nap creo que aquí también tenía
este color, que casi no se ve, por eso estoy haciendo zoom, ¿eh?
Pero es bastante oscuro.
Vamos a simplificarlo y todo lo vamos a poner como EEE.
De hecho, aquí también lo tenemos, pero es azul, es un poco raro.
Pues también vamos a ver aquí en debit y vamos a poner que sea EEE, que yo creo
que es más parecido a como lo tiene Twitter, ¿vale?
¿Vale?
Pues bueno, esto ya pinta mejor.
El problema todavía, bueno, veo que el de inicio sí que parece que, claro,
que va bien, porque al final no hay ningún problema, pero vemos que aquí esto sí que
se rompe por todos los lados.
Bueno, esto es, bueno, en principio fácil.
Vamos a ver lo que ocurre.
Lo primero que vamos a hacer es que vamos a quitar el scroll que tenemos tanto en el
body, en el HTML y los estilos globales, para perder este, digamos, este scroll que
tenemos aquí y lo vamos a pasar en el main, que digamos que es el contenido.
De esta forma nos enfocaremos en tener el scroll directamente ahí y no tenerlo fuera.
Esto yo creo que nos va a simplificar la vida, porque si no podemos tener como doble
scroll y cosas así.
Así que nos enfocamos primero en este.
Luego, aquí vemos que todavía sobresale, ¿no?
Pues esto lo vamos a arreglar también.
Esto era, ¿esto dónde es?
Porque este es el main, ¿puede ser aquí?
Creo que es aquí.
Vamos a verlo.
Le decimos que cuando es el scroll es vertical, ¿vale?
Que es el eje de la I, ¿vale?
Que sea automático.
Entonces, esto lo que debería hacer, vale, aquí, es ponernos un scroll si por lo que
sea el contenido sobresale al espacio que hay, por lo que hace es ponernos un scroll.
Ya tenemos un scroll y es, hombre, esto ya empieza a quedar un poquito
mejor.
Y ahora, lo que sí que tenemos es que aquí el nav, ¿no?
Este era como la navegación que en Twitter está abajo del todo también.
Cuando se hace muy chiquitito, bueno, no se puede ver.
Bueno, si lo podemos poner en modo móvil lo veremos, ¿eh?
Vale, aquí podemos ver, ¿no?
Pues este.
Esto también lo tiene abajo del todo y ese es el que vamos a dejar abajo.
Y vamos a hacer que, claro, también lo mismo que antes, que tenga un fondo porque si no
tiene el fondo.
Así que vamos a poner en background y vamos a poner que es el blanco.
Y al menos, pues, que se quede ahí.
Por ahora no vamos a hacer nada con eso, pero lo dejamos ahí y más adelante, pues,
ya lo iremos arreglando, le vamos poniendo los botones con los iconos y todo esto.
Ya hemos arreglado el header, ya hemos puesto más contenido, ya tenemos arreglado esto.
Vamos a ver si lo hacemos más pequeño, pues, no se nota nada.
O sea, tenemos el scroll y no se nota la diferencia.
Lo mejor es aquí, ¿no?
Que cuando tengo más grande, pues, se queda el scroll donde tiene que ser y, bueno,
se queda más recogido.
Ya tenemos esta arregla.
Vamos a pasar a lo siguiente.
A ver, sí, ¿qué es lo siguiente?
Pues, crear el tweet, ¿no?
Lo que queremos es empezar a crear tweets y poder recuperarlos y estos que están de
prueba, pues, dejar de utilizar estos y empezar a utilizar algunos que sean de verdad.
Para eso, lo primero que vamos a hacer es crear la página.
Entonces, en Twitter, cuando le damos aquí al botón de tuitear, este, te abre una nueva página.
Aunque, en este caso, claro, como tiene modo desktop, pues, enseña una modal.
Igual, más adelante hacemos eso también, ¿eh?
De que tenga una modal en desktop.
Pero, tiene una URL totalmente que esté esta.
De hecho, puedes acceder directamente a hacer un tweet.
O sea, que tiene una URL.
Eso significa que necesitaríamos hacer una página.
Así que, vamos a crear una página directamente que tenga también, pues, con el truco que os dije.
A ver si no estoy encima, ¿no?
Vale.
Vamos a crear una página con la misma ruta.
Compose y tweet.
Así que, ¿qué hacemos?
A ver, aquí.
Compose.
Que va a ser la primera ruta.
Luego, tweet.
Y luego, index.js.
Vamos a ver esto un momentito.
En páginas, lo bueno que tiene Next.js es que tiene el router como integrado dentro, ¿vale?
No estamos utilizando real router ni nada.
Lo que utiliza es el file system.
Más adelante, veremos que, aparte de los estáticos, de utilizar estructuras estáticas,
de forma que, cuando tú creas la carpeta Compose, pues, tienes la ruta Compose.
Si dentro tienes el subdirectorio tweet, pues, ya tienes tweet.
O sea, lo que estamos haciendo es crear esta estructura, este path, pero con directorios.
Pues, más adelante veremos, sobre todo cuando entremos en los debits, en los tweets que nosotros crearemos,
podremos hacer clic y entraremos en un tweet en concreto.
Para hacer esto, claro, necesitaremos tener una estructura un poco más especial.
Y veremos que se pueden hacer segmentos dinámicos, ¿vale?
O sea, podemos hacer un segmento que entienda que es una idea y capturar esa idea que tenemos.
Por ejemplo, cuando vamos a Twitter y vamos a un tweet, por ejemplo, vamos a ver, a darle a este.
Pues, vamos, vemos que aquí pone el nombre del usuario, status y el ID del tweet, en nuestro caso del debit.
Pues, esto nosotros también lo haremos.
Pero, claro, no podemos hacer este número y ponerlo aquí.
Pues, hay una forma de hacerlo y eso lo veremos en el próximo vídeo,
porque ya empezaremos a tener URLs para cada uno de los tweets, ¿vale?
Así que, vamos a ponernos manos a la obra para hacer este formulario para crear tweets.
Ya tenemos esto así.
Vamos a ver, he creado este fichero, ¿no?
El compose tweet y tenemos el index.js.
Pues, aquí lo que podría hacer ya es crear, al menos, aunque sea vacío, pero más o menos,
then function, un compose tweet, que por ahora no le llega ninguna prop.
A esta página está totalmente así.
Hacemos un return y aquí, pues, podemos hacer, a ver, vamos a poner el text area,
porque lo vamos a necesitar.
Y vamos a poner, está el JSX y aquí, pues, vendrán los estilos del text area.
Por ahora, pues, nada, tenemos esto.
No tiene gran cosa.
Vamos a ir directamente, porque por ahora no tengo ningún botón para ir.
Vale, por ahora está así.
No es que sea lo más bonito del mundo, pero ya vemos que le faltaría un poco el layout que tenemos.
Y es que en las páginas, por ahora, lo que estamos haciendo es un componente,
que se llama app layout, que es el que está como envolviendo cada una de las páginas
para tener siempre el mismo layout en nuestra aplicación.
Esto lo hicimos así, pero creo que más adelante lo vamos a cambiar para simplificarlo
y tenerlo, en lugar de tenerlo en todas las páginas dentro,
lo que vamos a hacer es ponerlo, como vimos en la primera clase,
que podríamos tener el archivo especial y en bajo app.js, pues, seguramente lo pondremos ahí.
Pero, bueno, por ahora, como lo tenemos así, y no me quiero enfocar tanto en eso,
quiero que avancemos con el tema del tweet, lo vamos a hacer así.
Vale, por ahora nos lo ha dejado así.
Al menos ya vemos lo que es el layout de la app, sí que está.
Esto está horrible, pero, bueno, podemos empezar a poner lo que realmente queremos que aparezca.
Para empezar, le vamos a poner el playholder este mítico de Twitter.
¿Qué está pasando? ¿No?
Que es lo que siempre en Twitter, cuando tú quieres escribirte, dices, ¿qué está pasando?
Que es como, no sé, ¿qué está pasando? Solo quiero publicar un tweet, tampoco está pasando nada.
Vale, esto por un lado y vamos a poner luego el botón.
Más adelante podríamos poner el avatar y todo esto, pero, no sé, debitear, le llamamos,
en lugar de tuitear, debitear.
Este button lo vamos a importar, que es nuestro componente que ya estamos utilizando, ¿vale?
Y por ahora, más o menos, vamos a ver cómo va quedando esto.
Bueno, pues más o menos.
Ya veo aquí que el textarea, pues necesitamos un poquito de trabajo de estilos.
Así que vamos a ver cómo lo podemos ir mejorando, porque ahora mismo no queda muy bonito.
Vamos a ver, ¿qué cosas le podemos poner?
Uy, guay, no.
Uy, 100%.
Luego, el font family, esto lo deberíamos poner a lo mejor en global, en lugar de tenerlo aquí.
Porque es una cosa que nos gustaría que tuviesen, sí, lo vamos a hacer en el otro, ¿vale?
Porque si no estilamos el textarea, podemos ver que nos pone un monospace aquí, que es un poco raro.
Entonces, vamos a estilar el app layout, ¿vale?
En esta, aquí, no, lo tenemos en esta app layout.
En los estilos tenemos todos los estilos globales, que lo vimos en la segunda clase, ¿vale?
Y aquí, pues bueno, en todos los estilos globales, vamos a hacer que el textarea y también el input, porque creo que tiene sentido, tenga el font family este.
Que lo estamos recuperando de fonts.base, esto porque tenemos guardada esa información, la tenemos en el theme, ¿vale?
Así fácilmente en un sitio cambiamos la familia de la fuente y así lo tenemos en todos nuestros proyectos, en toda nuestra aplicación, en todos nuestros componentes.
Vale, entonces, ahora sí que esto ha quedado un poquito mejor.
Vamos a seguir aquí a darle cariño un poco a esto.
El border tampoco me parece que tenga.
Luego, esto necesitaría un poco de padding, que no sé, vamos a poner 15 por todos los lados, más o menos.
Vamos a quitarle el resize ese, porque si ves ahí en la esquinita, aquí, en esta esquinita, sale este resize, que yo creo que en Twitter no lo tiene, porque lo puedes tomar y hacer más grande o más pequeño.
Pero bueno, esto no lo vamos a necesitar.
Así que lo dejamos por aquí.
Luego el botón también lo deberíamos poner...
El botón en Twitter lo ponen en el header.
El top bar lo podríamos separar y por ahora lo vamos a dejar así, pero es verdad que podríamos separar la top bar y reutilizarla.
Por ahora solo la tenemos en la home.
Más adelante seguramente la sacaremos y la reutilizaremos, ¿vale?
Entonces, este dip que tenemos aquí en el botón, pues también le vamos a dar un poquito de padding.
Bueno, ¿qué está pasando?
¿Qué está pasando?
Ah, y veo que no tengo el box sizing, este box sizing aquí, porque me...
A ver, está saliendo.
Sí, está saliendo.
Este box sizing está saliendo.
Bueno, no pasa nada.
Igual también vamos a cambiar, porque si miramos en Twitter yo creo que tampoco tiene eso de que...
Exacto, o sea, no tiene el focus ese que tenemos nosotros.
Así que seguramente le podríamos poner el online 0 también y ya está.
Nos faltarían cosas, por ejemplo el avatar, pero claro, ahora veremos qué problemas.
Más o menos, por ahora más o menos nos faltaría la top bar para ir para atrás y todo esto.
Por ahora lo vamos a dejar así y así nos enfocamos más en lo interesante que sería tener el formulario, ¿vale?
Así que le ponemos el formulario, el text area, el botón y todo esto lo ponemos dentro del formulario.
Y lo que vamos a necesitar aquí son diferentes cosas, son un montón de cosas.
Ah, mira, ahora me lo ha hecho más pequeño cuando lo he puesto en un formulario.
Vamos a poner que tenga como mínimo, no sé, 200 píxeles más o menos.
Vale, luego lo seguiremos arreglando, el estilo y tal.
Ahora lo que vamos a hacer es, vamos a empezar a tener un estado, ¿no?
Para ser capaces de guardar el mensaje y todo esto.
Y el usuario, claro, el usuario también lo vamos a editar.
Porque el usuario, useState, el usuario es el que va a tener su username, su avatar y todo esto.
Y eso es información que vamos a tener que guardar.
Y luego veremos por qué lo guardamos un poco en Firestore y qué nos implica esto, ¿no?
El utilizar este tipo de base de datos.
Por ahora podríamos extraerlo en un hook.
El tema del usuario que lo tenemos ya en otra página.
Lo vamos a hacer en copy-paste, pero más adelante seguramente en otra clase lo vamos a solucionar, ¿vale?
Porque ya veo aquí, por ejemplo, todo esto del userState, ahora que he hecho aquí.
Venga, va.
Hacemos el hook.
Venga, os leo en vuestros comentarios.
A ver si queréis que haga hook o lo copio.
Lo que vosotros me digáis.
Comentádmelo en el chat, a ver qué hacemos.
Y mientras os voy leyendo, ¿vale?
A ver, a ver.
Voy que, uf, es que habéis escrito aquí un montón.
¿Se puede hacer un deploy en Vercell usando Express en nuestro proyecto?
Creo, déjame pensar.
Creo, sí, yo creo que sí.
Claro, si soporta proyectos con Node.
Estoy seguro que con Vercell puedes hacer un proyecto con Express.
Sí, sí.
No hay ninguna duda.
Puedes hacer un proyecto con Express y deployarlo.
Sin ningún problema, ¿vale?
¿Qué más?
¿Qué más por aquí?
En un promiseAll, en la cual function retorna un objeto y function otro objeto distinto,
¿cómo tengo el valor de cada función?
Tension.
Bueno, pero esto, Brian, a ver.
Esta pregunta es un poco tricky ahora, ¿eh?
Me has cambiado de términos totalmente.
Pero a ver.
Si tienes una promise, así.
Y tienes, y el promiseAll, esto es un array.
Y tienes una función 1.
Y tienes la función 2.
Y aquí el then, pues lo que hace es devolverte un array.
También el then, ¿vale?
Así que tenemos el then una función, ¿vale?
Y el then te vuelve un array.
Y en la primera posición tendrás el resultado de la función 1.
Y el segundo tendrás el resultado de la función 2.
Y ya está.
Ahora, ¿qué dices que el primero retorna un objeto?
Bueno, pues entonces puede ser que tengas resfung 1.name.
Y el segundo dices otro objeto distinto.
Bueno, pues otro name, porque es distinto.
Otro name.
Y ya está.
Esto sería así.
El punto then devuelve un array.
Y en el primer elemento tiene el resultado de la función 1.
Y el otro está.
Pues eso.
Espero que te haya ayudado, Brian.
¿Qué más?
¿Qué más?
Tendría sentido conectar Tilewin CSS con Style Components.
La elegibilidad de componentes páginas usando Tilewin se hace muy difícil con todas las clases.
Felicidades por la estrella y por tu canal.
Muchas gracias, Guillermo.
Tendría sentido.
La verdad es que es lo que dices.
Tilewin está muy bien para prototipar.
Bueno, yo creo que está muy bien para prototipar.
Y puede ser que esté bien para ciertos proyectos.
Pero funciona a base de clases.
Entonces, mezclar las dos cosas, pues no sé.
Ya si te metes con Tilewin, igual tiene sentido quedarte con eso, ¿no?
Y no tirar tanto de Style Components porque si no es un poco lío, en mi opinión.
Pero bueno.
A ver, ¿qué más?
Xavi Wu dice, siguiendo tus vídeos, NextGest, tenía problemas cuando se lanzaba la función
onOutStateChange en la home cuando el estado pasaba de Undefined a Null.
Intentaba hacer el mapeado del user.
Mira, a ver, Xavi, que no tengas en algún...
De hecho, había un problema que en la primera clase y lo arreglamos en la segunda.
Mira a ver si van por ahí los tiros.
Porque, claro, a veces se intentaba hacer el mapeo de un Null y entonces no funcionaba.
Y había que hacer un renderizado.
O sea, había que hacer una eternaria.
No decir, oye, si esto es Null, pues no intentes hacer eso y devuelve Null directamente.
Échale un vistazo, ¿vale?
Vale, hooks, hooks.
Vale, vale, ya veo que es hook, hook, hook.
Esto, carita sonriente, hooks.
Bueno, pues hacemos el cast on hook, ¿vale?
Obvio, obvio, vale, vale, vale.
¡Ostras!
Vale, vale.
Y lo hacemos, lo hacemos.
Lo hacemos, lo hacemos.
Lo hacemos, vale.
No sabía que...
Última pregunta y pasamos a hacer el cast on hook.
Con React, ¿qué recomiendas?
¿Usar TypeScript o PropTypes?
Bueno, a ver.
En mi opinión, seguramente intentaría al principio utilizar PropTypes.
Y una vez que veas realmente que las PropTypes te están causando un problema, pues a lo mejor, si ves que tienes un problema y TypeScript te lo soluciona, pues utilizaría TypeScript.
Pero no sé, por ahora, por ejemplo, en este curso estamos trabajando componentes y por ahora no hemos tenido ningún problema de ese tipo.
No hemos echado de menos TypeScript en esa parte.
Quiero decir, TypeScript es bastante potente y es muy interesante, pero empezar desde cero a hacer un montón de componentes con TypeScript hay que ver el valor que te da porque al final también te añade cierto trabajo.
Que también te añade tranquilidad, puede ser, pero habría que ver si esa tranquilidad no la puedes ganar con las PropTypes, por ejemplo.
O con JSDoc para que te lo... para que te diga el tipo de los datos y tal.
Al final las PropTypes cuando estás desarrollando te sale en warning.
O sea, que no sé, si estás muy cómodo en TypeScript y ya te encanta, pues haz TypeScript desde el principio.
Pero yo lo que te diría es que consideres también un poco el coste que puede tener, en mi opinión.
Vale, pues ya que habéis dicho user, entonces vamos a hacer el custom hook, ya que estamos por aquí.
Vale, hacemos el custom hook.
El custom hook, la idea sería hacer un useUser, ¿no?
Y aquí que nos devolviese el user.
Por ahora sí, sería algo así, ¿no?
Así que vamos a crear una carpeta aquí dentro de Pages, ¿no?
Aquí, que le vamos a llamar hooks y creamos uno que sea useUser.js.
Entonces, lo que queríamos extraer aquí era en el de la home...
No, en el index, que es como el índice de nuestra página, ya teníamos este userStates y todo esto.
Así que este userStates ya me lo voy a traer para aquí porque lo vamos a necesitar.
De hecho, vamos a exportarlo porque seguramente será interesante.
Ah, incluso ya que hacemos esto, podemos hacer algo interesante con esto.
Vale, así que esto fuera.
Nos lo llevamos al custom hook.
Luego este useState, esto va a ser la gracia justamente del custom hook.
Así que hacemos un exportDefaultFunction, useUser, que por ahora no recibe ningún tipo de parámetro.
Y ya nos pide que importemos el useState.
UseState from React.
Vale.
Entonces, ahora, seguimos con lo nuestro.
Aquí, ya que estamos, vamos a hacer que esto sea user y esto ya utilice el useUser.
Vale.
Me ha hecho el import automático arriba.
Lo digo por si luego dice, pero si no le ha importado.
¿Veis?
Aquí ya ha detectado que he utilizado el useUser y me la ha importado.
Vale.
Este efecto exactamente igual.
También lo copiamos y lo vamos a pegar aquí.
Y aquí, en principio, podríamos hacer diferentes cosas.
Una sería devolver el user y ya está.
Por ahora vamos a hacer esto.
UseEffect.
Y vamos a importar también este onOutStateChange.
Esto lo importamos desde el cliente de Firebase.
Venga.
FirebaseClient, que aquí ya habíamos hecho esta función.
Así que ahora lo tenemos encapsulado aquí en un custom hook.
Básicamente el estado para saber si es usuario o no.
Y cuando cambie el out, pues cambia este estado.
Y esto es lo que nos está devolviendo el usuario y ya estaría.
Un problema, entre comillas, que tenemos aquí, básicamente,
bueno, no es un problema tampoco, ¿eh?
Aquí estaría bien este useUser porque estamos haciendo aquí
que si el usuario es truci, o sea que no es nulo o no es undefined,
pues hace el replace, ¿no?
El problema ahora está en esto, ¿no?
Este userState y tal.
Por ahora vamos a hacerlo así.
Aquí no lo vamos a liar.
Vamos a hacer un export const porque aquí lo que podríamos hacer
también es exportar métodos para ver si el usuario está logado,
si no sabemos su estado, si y tal.
Podríamos tener un montón de funciones que nos ayuden.
Por ahora vamos a dejarlo así y más adelante seguramente
las añadiremos.
Exportamos el const de esto y así, pues,
ya podemos importar aquí este useUser y tener el userState.
Y de esta forma, pues, esto debería seguir funcionando perfectamente.
Si vamos a la home, vamos a la home.
Y vamos a ver si esto sigue funcionando o se está petando algo.
Vale, pues, esto parece que funciona correctamente.
Ha utilizado el custom hook y no nos ha dado ningún problema.
Ahora, este custom hook es el que podríamos utilizar también aquí, ¿no?
Este user, en lugar de copiar, que es lo que iba a hacer yo,
pero que no me habéis dejado, que está muy bien que no me hayáis dejado,
pues, ya tenemos este user aquí, ¿vale?
Entonces, con este user ya podemos empezar a hacer cosillas.
Estoy pensando que también puede ser interesante que esto es una cosa
que también hace Twitter, ¿no?
O sea, es verdad que la home sí que es visible para una...
Bueno, la home como tal, no.
Un timeline así como random, ¿no?
Pero si no estamos logueados en Twitter, ¿no?
Si yo voy a Twitter e intento acceder aquí a home,
vamos a ver qué pasa.
Un momento.
Vamos aquí y vamos acá.
¿Ves?
Me manda directamente al login.
Pero si veis un momento, si os fijáis, sí que parece, ¿eh?
Que voy a...
Me sale aquí explorar, configuración.
O sea, intenta hacer algo, ¿no?
Y aquí podemos ver otra vez el ejemplo este de que lo está haciendo
el cliente y me envía al iniciar sesión en Twitter.
Pues, podemos hacer algo así.
Por ahora no tenemos una página que es de login específicamente,
pero ya que hemos hecho el custom hook,
igual es interesante hacer algo parecido a lo que hemos hecho en la home, ¿no?
Que sea que cuando cambia el user,
miramos que si el user es...
El user state es not log,
por lo que podríamos hacer directamente,
oye, este usuario tiene que pasar por la home para loguearse, ¿no?
O sea, que si no estás logueado,
pues algo parecido a lo que hemos hecho en el otro sitio del router, punto...
En este caso, a lo mejor sí que haríamos un push
y que vaya a la home.
Bueno, a la home, al índice, no a la home.
Es que el nombre es verdad que no está muy bien escogido, ¿vale?
Así que nada, vamos a hacer your router, from next router.
Y así, pues esto que tenemos ya arreglado, ¿no?
El router, use router, utilizamos el router.
Y de esta forma hacemos el efecto que el usuario cambia y deja de estar logado,
o no está logado ya de primeras, pues, pum, fuera de aquí.
Y lo llevamos al índice para que vea lo que tiene que hacer, ¿no?
Para loguearse.
Podríamos probar, ya que hemos hecho unas cuantas cosas,
vamos a probar esto.
Y application, voy a limpiar el site.
A ver si con esto tengo suficiente.
Vale.
Claro, aquí puede pasar otra cosa.
Y es que esto a lo mejor también lo hacemos de otra forma más adelante.
Pero por ahora el problema seguramente que pasa es que en la home
no estamos utilizando el use user, ¿no?
O sea, este es un poco el problema que comentabais de rutas protegidas.
Entonces, en la próxima clase vamos a hacer algo para simplificar esto.
Vamos a hacer algo que nos ayude a que todas las rutas que queremos que sean
protegidas en el file system lo mire sin necesidad de tener que tirar
del custom hook.
Vamos a intentar hacer algo al respecto.
Porque si no, ahora lo podríamos arreglar así.
Hacemos un use user aquí.
Y, bueno, en realidad ni siquiera necesitamos,
no sé si esto se puede hacer.
Sí, se puede hacer así.
Guardamos los cambios.
Y, claro, ahora que sí que llamamos al custom hook,
ahora sí revisa si está el usuario registrado o autentificado.
Y si no lo está, te manda a la home.
Ahora volvemos a hacer lo mismo.
Vamos a la home.
Durante un momento lo vemos, ¿vale?
Pero luego podremos hacer cosas para que ni siquiera cargue esos datos.
Como hace Twitter, ¿no?
Que intenta hacer algo, pero instantáneamente dice, no, fuera.
En este caso lo arreglaremos.
Diremos, vamos a tener aquí el user, ¿vale?
Y este fetch, pues sería así, ¿no?
Si tenemos el usuario, pues entonces sí hace el fetch.
Y de esta forma ya ni siquiera vería los debits.
De esta forma, cuando va a la home, pues ahora sí, ¿no?
Saldría vacío.
Ni siquiera vería nada.
Y de esta forma ya estamos empezando a evitar que tenga cierto acceso, ¿no?
Sí que lo carga, pero al final estamos haciendo una ruta protegida
porque está intentando acceder manualmente a una ruta que no debería
y ya lo estamos sacando de ahí o no estamos mostrando la información
que él quiere ver, ¿no?
Porque de alguna forma está protegida y tal.
Y de hecho, este fetch o estas cosas podríamos hacerlo incluso
que funcionase con el token para evitar que si no tienes el token
ni siquiera si lo hicieses manualmente el fetch lo pudieses ver.
Pero bueno, por aquí pueden ir un poco los tiros el tema del user.
Vamos a hacer el login para ver si funciona un poco el custom hook que he hecho.
Vale, he hecho el login y ya me ha enviado al inicio.
Pero veo que no me ha cargado esto, ¿no?
Cuando me ha hecho, a lo mejor es porque ha hecho el replace.
Claro, esto también lo vamos a tener que arreglar.
Esto seguramente al hacer el replace no está cambiando este user.
O sea, este user solo se está ejecutando a lo mejor una vez.
Tendríamos que ver, pero seguramente si recargo vamos a ver que esto está funcionando bien.
¿Qué pasa?
Que esto lo estamos haciendo cuando se monta.
Es posible que no haya cambiado el, claro, que el usuario no esté autentificado
esté ocurriendo la autentificación, intenta ir a la homepage y entonces no hace el fetch.
Eso podría ser una, ¿ves?
Entonces lo que podemos hacer, uy, así no, así.
Es que cuando cambie el user, entonces, claro, si cambia el user,
vuelve a ejecutar ese efecto, entonces si tiene usuario, haga el fetch.
Y así pues ya lo tendríamos solucionado.
Porque el problema si no, es que si no está autentificado, hago login, me lleva a la página,
pero claro, la página ejecuta el efecto, ve que no estoy logado y entonces me hace este fetch.
Es entonces donde pasa esto, ¿no?
Y es justo porque ocurre justo cuando está montándose.
Con esto lo solucionaríamos.
Vale, creo que con esto tenemos lo del useUser.
Me he ido un poco de madre con el tema del useUser.
Vamos a volver al composeTweet, ¿vale?
Os leo un poquito, a ver, y entonces vamos a ver qué me comentáis.
Y seguimos con el compose, ¿vale?
Vamos a darle al streamDeck, maravilloso streamDeck.
Vale, a ver.
Me comentáis por aquí, ¿vale?
Sí, lo del hook.
Zik decía si podía usar TypeScript y PropTypes al mismo tiempo.
Lo puedes utilizar sin ningún tipo de problema, ¿vale?
Son las dos cosas.
Es verdad que si utilizas TypeScript, el uso de PropTypes es menos claro, ¿no?
No tiene tanta... no te da ninguna ventaja.
O sea, si utilizas TypeScript, yo ya no utilizaría PropTypes, en mi opinión, ¿vale?
Vale.
Cracksport dice que alguien tiene que anotar todas las cosas que dice que hará más adelante.
Pues está muy bien que me las recordarais, ¿vale?
O sea, que si las apuntáis, genial, porque hay un montón de cositas que me gustaría hacer.
No se me suelen olvidar, ¿eh?
Pero bueno, está bien.
Vale, vale.
¿Cuál es la diferencia entre el replace y el push del router?
Con el push, si navego hacia atrás, vuelvo a la página donde dice el push.
Dice Diego.
Efectivamente.
O sea, básicamente, el replace es que reemplaza la URL de la barra de direcciones.
La reemplaza.
Y el push lo que hace es, pues, empujar una nueva URL de la barra de direcciones y, por
lo tanto, en el historial tienes, pues, podrías ir hacia atrás, ¿no?
Porque es como una cola en todas las direcciones en las que has estado.
Cuando haces un push, pues, pones una más en la cola.
Pero cuando haces un replace, lo que estás haciendo es reemplazarla.
¿Qué pasa?
Normalmente, si lo que queremos es como que funcione como una SPA, ¿no?
Lo haríamos un push.
Porque es, no, no, voy a hacer un push porque he navegado de esta página a esta otra.
Pero cuando queremos hacer una redirección, es más de este tipo, ¿no?
En el que es una página en la que no tiene, digamos, acceso, no tiene sentido que se la
dejemos en el historial.
Porque si le da hacia atrás, volvería otra vez a la misma en la que estaba.
Y puede ser un poco chocante, ¿no?
Y es, realmente es como decirle, ¿no?
Es que esta URL en este historial no tiene sentido porque has intentado una URL que no
tenía sentido para ti.
Así que te la reemplazo totalmente por esta.
Como una redirección, en realidad.
Es como una redirección de decir, no, esta URL en tu historial ya no está.
Porque no tenías acceso a ella, ¿vale?
Es un poco esa la diferencia, ¿vale?
¿Qué más?
Ojo, ¿eh?
Que Junior dice, con replace cambias el location del navegador
y es decir, recarga la página.
Eso no es cierto, ¿vale?
O sea, una cosa es hacer el location.replace, que eso sería una.
Pero otra cosa es hacer un replace con el router.
O sea, con el objeto history.
Si tú haces un replace, no hace una navegación.
Otra cosa es que nosotros utilicemos el location.
O sea, con location, location.hrf y aquí pospongamos lo que sea y tal.
Pero un replace puede funcionar igual que un push, ¿vale?
O sea, lo que hace básicamente es que te lo reemplaza.
Otra cosa es que lo hagamos más como location.replace o location.hrf y lo machaquemos y cosas así.
¿Vale?
¿Vale?
¿Qué más?
¿Qué más?
Muy entretenido el vivo.
Felicitaciones y éxito.
Muchas gracias, Javier.
Te lo agradezco.
Pues seguimos, ¿vale?
Vamos a seguir porque ya nos vamos acercando a hacer el Compose.
Y sé que tenéis ganas de ver el tema este.
Lo hemos dejado así el Compose.
El qué está pasando aquí.
Vamos a volver a la página donde teníamos el Compose Tweet.
Aquí.
Voy a hacer esto más chiquitito y a ver qué.
Vale, teníamos el user del Compose.
Vamos a ver dónde me había quedado.
Tengo aquí una plantilla más o menos donde va mis...
¿Qué es lo que tengo que ir haciendo para tener un hilo conductor?
Y no vaya a ser.
Vale, entonces, tengo lo del useUser.
Efectivamente, seguro, vamos a tener que guardar el mensaje que queremos guardar en la base de datos.
Así que por ahora vamos a hacer esto.
Y este message, pues nada, lo típico, lo ponemos en el value porque vamos a controlar esto.
Este setMessage, useState, no, lo estamos importando.
Estaría bien que lo importase automáticamente también, ¿eh?
Vamos a ver, setMessage.
Este setMessage lo vamos a utilizar cuando hay...
Vamos a hacer el handleChange.
Y este handleChange se ejecuta cuando hay cambios en el textarea.
Cada vez que hacemos un cambio se ejecuta este onChange.
Esta prop es el evento, ¿no?
Es la respuesta al evento de cambiar el valor dentro del textarea.
Pues ejecutamos el handleChange.
A esto le llega el evento.
Esto sería el event.
Y en el event, pues tenemos event.target y extraemos el value,
que es el texto que se está escribiendo dentro del textarea.
¿Y qué hacemos con esto?
Pues hacemos un setMessage.
Y aquí lo que vamos a guardar es el value.
Con esto ya tendríamos guardado un poco lo que es el mensaje.
Luego también vamos a necesitar...
A ver, ¿qué es lo que me gusta esto?
Que no estoy...
Bueno, claro, es que todavía no he cambiado.
No he guardado los cambios.
Vamos a guardar.
A ver si a esto le gusta.
Vale, bien.
Mejor.
También vamos a necesitar un handleSubmit,
que este va a ser para el formulario, ¿no?
Cuando hacemos submit del formulario.
Así que onSubmit, cuando hacemos el submit, una prop especial,
que esto ya viene de React, le podemos pasar un callback
y le pasamos nuestra función handleSubmit,
que se va a ejecutar cuando haz submit el formulario.
Lo primero, y esto es importante, en los formularios hay que hacer el
preventDefault.
Event, preventDefault.
¿Vale?
Si no, el formulario funcionaría como funciona por defecto
y nos la podría liar bastante parda.
Con esto, en realidad, ya podríamos...
Bueno, podríamos darle, pero no pasaría nada.
Así que vamos a hacer algo más.
Hay un tema interesante, ¿no?
Y es que cuando no hay nada, no deberíamos ser capaces de darle
al botón de bitear.
Porque, claro, si no hay mensaje, que vamos a tuitear.
Entonces, lo que podemos hacer en el botón es añadirle un disable
que, si el mensaje, la longitud del mensaje es cero,
decimos que está desactivado el botón.
Pero, claro, ahora, aunque lo he hecho, esto sigue funcionando igual.
¿Por qué?
Porque el botón no recibe esta prop.
Esta prop no la entiende.
Así que vamos a añadirla rápidamente.
El disabled, esto se lo hacemos llegar al botón.
Y este disabled lo vamos a tener en cuenta aquí.
Vamos a hacer un button que...
Y ahora os explico esto.
Bueno, esto significa cuando el botón tiene el atributo disabled,
o sea, es un selector especial en CSS que lo que hace es seleccionar
elementos con un atributo en concreto.
Por ejemplo, podríamos hacer aquí disabled o incluso si el class name es tal.
Pero en este caso, como disabled se queda tal cual como un atributo así.
Y, de hecho, lo podemos mirar.
Si le damos aquí...
Bueno, voy a guardar los cambios.
Y si le damos, si lo inspeccionamos, deberíamos ver el atributo.
Hay una cosa interesante.
Claro, cuando ahora le doy encima, no me funciona el botón derecho.
¿Vale?
Esto es porque ya por defecto algunos navegadores,
cuando detecta que tu botón tiene el botón desactivado,
pues no recibe eventos.
¿Vale?
No le puedes dar porque no recibe el evento.
Entonces, aquí podéis ver que está el disabled.
Entonces, para destilarlo aquí, ya podríamos hacer...
Porque tengo una oposidad muy chiquitita,
para que quede claro que no se puede dar.
¿Vale?
Ya lo podéis ver, ¿no?
Pero si le doy un clic ahora...
Claro, esto tiene el touch.
Veis que tiene este efecto raro.
Es como que todavía el hover funciona.
Vamos a poner aquí un pointer events known,
como para decirle, mira, hagas lo que hagas.
Esto no tiene que reaccionar.
Ahora sí.
No tiene que reaccionar a nada, a ningún evento.
¿Vale?
Que sea de darle clic o de hacer touch y tal.
Así que, ahora sí, ya ha dejado de funcionar.
Bueno, se puede seleccionar esto.
Lo podríamos hacer, ¿eh?
También el user, al menos user select, creo que es así.
Y así ya ni siquiera se puede seleccionar.
Efectivamente, ya lo puede seleccionar.
Y de esta forma, pues queda bastante bien.
Entonces, cuando escribimos, pues tiene este efecto que se activa.
Además, está bien porque hacemos este pointer events known,
y aunque obviamente lo podríamos llegar a hackear de quitarle por CSS esto,
esto lo estamos haciendo con CSS.
O sea, no necesitamos código JavaScript para controlar este comportamiento,
lo cual creo que está bastante bien.
¿Vale?
Así que, vale, ya tenemos el disabled.
Ah, mira, tenemos por aquí un superchat de...
Ay, voy a quitar por aquí.
James Mendez, ¿cuál sería el criterio para usar o no usar una ruta en React
por una ruta del servidor?
Gracias y excelentes tutoriales.
Muchas gracias.
James, ¿cuál sería el criterio para usar o no usar una ruta en React
por una ruta del servidor?
La verdad es que no entiendo muy bien tu pregunta.
Me has dejado un poco loco.
A ver, ¿para usar o no usar una ruta en React por una ruta del servidor?
Es que, claro, o sea, puedes tener rutas en React
que en realidad las está sirviendo el servidor.
¿Qué quieres decir?
Cuéntame más en el chat.
James, a ver si puedo entender del todo tu pregunta.
Y así entiendo y te intento contestar bien, ¿vale?
¿Qué más?
Dice Diego que otra cosa que hago con los length similar a lo que te pregunté
de las variables es que uso mucho la negación, variable.length,
en vez de variable length, igual, igual, cero.
Esto sí es transparente, ¿no?
A ver, sí, podríais hacer esto si queréis.
Pero os voy a comentar una cosa que a veces no lo cumplo, ¿vale?
O sea, que no miréis mi código como, ahí no lo has cumplido.
Yo intento siempre que puedo ser, en este caso, en message.length,
tiene bastante sentido que puedas hacerlo así porque el .length ya das por sentado
que es un número en concreto, o sea, que es un número y difícil que se te pueda colar otra cosa.
Así que sí, aquí puede estar bien.
De hecho, lo he pensado antes y he dicho, lo voy a hacer, pero bueno, lo voy a hacer así.
Así que aquí se ve indiferente.
Pero es verdad que normalmente intento ser muy implícito, o sea, intento ser muy explícito
con las cosas que quiero hacer o las comparaciones a las que quiero en mi programa
estar seguro que se hacen.
¿Por qué?
Porque JavaScript es bastante peligroso muchas veces en las comparaciones.
Incluso para entender el código, a veces, esa verbosidad puede venir bien, ¿no?
El igual, igual, igual a esto, como lo que he hecho del usuario, ¿no?
Cuando, si le hubiéramos puesto la negación a lo del usuario, puede ser un poco
que alguien que viene después diga, ¿pero esto qué quiere decir?
La negación del usuario, que no tiene un usuario, que está cargando el usuario,
¿qué quiere decir, no?
Y aquí igual, ¿no?
Esto lo puede entender cualquiera, pero estoy seguro que esto lo entiende todavía mejor alguien, ¿no?
Cuando, incluso esto, extraerlo a un método que sea checkMessageIsEmpty, cosas así.
Pero, bueno, que esto es, ya os digo, esto soy yo, que a veces hago estas cosas.
Pero está bien también el que lo hagáis así y así funciona perfectamente.
Vale, vamos a asegurar que tenemos el textarea, tenemos el botón, hemos creado los métodos.
Bueno, pues básicamente lo que nos queda aquí, y lo voy a ir creando, sería tener un método que le llamemos
addDebit, por ejemplo, que aquí le pasemos todos los parámetros que queremos que tenga en la base de datos.
¿Qué parámetros teníamos aquí que nos gustaría que tuviésemos en la base de datos?
Y veremos que esto, a lo largo del curso, seguramente iremos haciendo cambios.
Pero por ahora hay que saber que Firestore es una base de datos que no es SQL.
Esto quiere decir que no es relacional.
O sea, que no tenemos diferentes colecciones, no, tablas.
No tenemos diferentes tablas.
Una tabla, tweet.
Una tabla, tal.
Una tabla, tal.
Y luego la relacionamos entre ellas para recuperar toda la información.
Al ser no SQL, lo que se busca muchas veces es tener la información repetida.
Y no hay ningún problema normalmente en esto.
Hay que no ser muy bestia, que ahora lo vamos a hacer, pero no pasa nada por tener información repetida.
Muchas veces esa información repetida, lo que se hace para actualizarla es utilizar una Cloud Function,
que veremos cómo lo hacemos para, pues, para, imaginemos que el usuario cambia el avatar.
Vale, pues, lo que vamos a hacer es, donde se esté repitiendo el avatar, a lo mejor, pues, lo actualizamos.
Cambiamos a la nueva referencia.
Cosas así, ¿vale?
Pero vamos a ver que este tipo de base de datos puede tener información repetida
o se hacen agregaciones diferentes, ¿no?
Las colecciones, vamos a tener colecciones en lugar de tablas,
y a lo mejor en una colección guardamos más información solo por el simple hecho
de que es más fácil extraerla de esa forma, ¿vale?
Así que en este caso vamos a aprovecharnos de esto y vamos a ir muy a saco.
Y lo que vamos a hacer es grabar, por ejemplo, pues, el avatar directamente.
Cada tweet va a tener el propio avatar del usuario.
Esto, más adelante veremos cuando metamos el usuario en la base de datos,
que no es necesario porque nos simplificará la vida tenerlo en dos colecciones diferentes.
Pero por ahora vamos a ir como muy a saco.
Luego tenemos el contenido, ¿no?
Que en este caso es el mensaje, que va a ser como el tweet.
Luego tendríamos el user ID, que sería el usuario, la ID del usuario.
Para esto, en el user tendríamos que ver si tenemos un user ID.
Si vamos al cliente de Firebase, cuando lo estábamos mapeando, aquí no lo estábamos extrayendo.
Pero el usuario aquí tiene una propiedad que se llama unique ID, unique identifier, ¿vale?
Que es la UID, que básicamente esto lo que tiene es un identificador único para ese usuario.
Así que lo podríamos extraer y ya lo podríamos recuperar para utilizarlo.
No lo estábamos haciendo antes porque no lo habíamos necesitado,
pero ahora sí que lo vamos a necesitar.
Así que vamos a hacer esto.
Vamos a guardar los cambios de cliente y vamos a volver aquí.
Así que el user ID lo recuperamos de user.uid, ¿no?
¿Lo he puesto de nuevo ID?
Sí, vale.
¿Qué más necesitamos?
Tenemos el username, también lo vamos a necesitar.
Y esto sí que lo estábamos mapeando.
Tenemos el username de display name.
Veremos cuando metamos el usuario en la base de datos
que nos gustaría también recuperar el username de GitHub, no su nombre real.
Pero por ahora, como tenemos ese, pues vamos a hacer eso.
Vamos a recuperar el username.
Ahora, este adddebit, este método, ¿de dónde lo vamos a sacar?
Pues lo vamos a tener en el cliente de Firebase.
Así que vamos a Firebase, client, guardamos los cambios.
Y ahora nos revienta porque nos dice, vale, esto está muy bien,
pero ¿dónde está sacando este nuevo método adddebit?
¿Vale?
Pues lo vamos a poner aquí.
Y aquí, pues vamos a empezar a añadir, pues eso.
Teníamos el avatar, teníamos, a ver, cuáles sean los cambios pasados.
Content, user ID, user name.
Content, user ID, user name.
Estoy pensando que hemos puesto username todo en minúscula.
No sé si tendría sentido cambiarlo.
Porque hemos puesto user ID con mayúscula.
No sé.
¿Qué pensáis?
¿Hacemos camel case en todo o no?
Bueno, podemos hacerlo.
En la base de datos lo hacemos así y ya está.
Todo con camel case que es mejor.
Vale.
Ahora viene un poquito el tema de Firebase, Firestore.
Vamos a ir a nuestra consola de Firebase que ya vimos en el,
no sé si el segundo o tercer capítulo.
Segundo.
Puede ser el segundo.
Tenemos nuestro proyecto de DevTerm.
Y aquí vamos a crear una base de datos.
La hacemos aquí.
Aquí tengo database, ¿vale?
Entramos en la base de datos.
Pa, pa, pa.
Y ya nos está diciendo que debemos crear,
no tengo todavía creada la base de datos,
así que la voy a crear con vosotros.
Pero ya nos dice, podéis ver que os está ofreciendo,
vamos a base de datos y ya os ofrece Cloud Firestore directamente.
Y nos dice que tiene actualizaciones en tiempo real,
consultas potentes, escalado automático y que tiene un montón de cosas.
Pero si bajáis un poquito, veis que hay otra, ¿no?
Que dice, o bien, elige real-time database.
Esta es la base de datos que comentaba antes que es como la antigua de Firebase.
Esta es la base de datos con la que empezó Firebase.
Y esta base de datos no es que esté mal, pero, bueno, tiene cosas diferentes.
De hecho, puede ser que sea mejor opción que la otra, dependiendo de muchas cosas.
Es que, de hecho, no sé si creo que tienen como una encuesta, unas preguntas para ver cuál deberías usar.
Por ejemplo, depende un poco de si quieres utilizar, real-time database es como un árbol.
No es tanto como colecciones, objetos JSON, sino que es como un solo objeto JSON de lo que todo tira ahí.
Entonces, es un poquito más complejo trabajar con ello.
En cambio, con la que vamos a utilizar son más colecciones, también se parece a JSON,
pero son JSON más manejables, más pequeñitos.
Entonces, depende también de eso.
El número de operaciones, el real-time database, las operaciones que puedes hacer al momento son menores,
son muchas, ya te lo digo, creo que son mil escrituras al mismo momento, que es un montón.
Pero Firestore, en ese aspecto, es bastante mejor.
O sea, no se bloquea en ningún momento.
Los dos tienen soporte sin conexión.
Lo que pasa con un real-time database es que las consultas son más directas.
O sea, las consultas que haces no te permiten filtrar tan bien.
Tienes que hacer el filtrado más, digamos, en la parte del cliente o en el servidor o tal.
Y recuperas demasiada información muchas veces.
No te deja filtrar fácilmente.
En cambio, Firestore tampoco es que sea la panacea de los filtros,
pero te permite hacer consultas más interesantes, ¿no?
Como puedes encadenar filtros, puedes decirle dónde este parámetro sea tal.
Puedes ordenar más fácilmente.
El otro es un poquito hacer consultas, sobre todo profundas, es bastante complejo y difícil.
Así que si tienes que hacer filtros que no sean limitados, vas a necesitar utilizar Firestore, ¿vale?
Entonces, te lo puedes mirar a ver cuál de las dos es más interesante.
Real-time database, digamos que es más básica las operaciones de escritura y de actualización
y transacciones que puedas hacer.
Y Firestore, pues, las tiene más complejas.
Cosas así.
Otro problema que tiene, que esto no nos va a afectar, ¿eh?
Pero real-time database solo puede estar en una región.
En cambio, Firestore como que escala infinito.
Así que eso es otra cosa que si tu aplicación es muy grande, tienes que tener en cuenta.
Y real-time database, tú te tienes que preocupar un poco de la fragmentación que tienen tus datos,
lo cual no suele ser muy bueno.
Y esto de Firestore, que como he dicho, pues, escala automáticamente, no te vas a tener que preocupar.
Eso sería un poquito las diferencias que tienen y por eso Firestore es el que vamos a utilizar en nuestro caso, ¿vale?
Así que vamos a crear la base de datos.
Por ahora, esto lo haremos también en una clase de el tener las reglas y tenerlas bien.
En este caso, vamos a empezar en modo prueba.
Y esto es el modo prueba no está preparado para llegar a producción, ¿vale?
Este modo prueba es mientras estás desarrollando, para ir probando y tal.
¿Por qué? Porque luego tendríamos que hacer reglas específicas de qué se puede o no se puede hacer en nuestra base de datos
dependiendo de qué usuario o dependiendo de qué operación quiera hacer.
Si quiere leer, si quiere escribir, si quiere escribir en esta colección, en esta otra, ¿vale?
Si es dependiendo del tiempo, tiene un montón de propiedades, ¿vale?
En este caso, vamos a poner modo prueba por ahora para empezar a lo grande, ¿vale?
Ahora nos pide la región, le vamos a decir Europa, porque en mi caso estoy en Europa, pero, bueno,
podríamos poner también el de Estados Unidos, el de Asia, donde veamos en Sudamérica.
En este caso, vamos a poner Europa.
Esto es lo que va a ser importante para la latencia de vuestros usuarios, ¿vale?
Pero si en el caso de que vuestros usuarios estén en Sudamérica, pues pondríamos Sudamérica.
Puede seguir utilizándose fuera de esa región, pero no significa que no vaya a funcionar,
solo significa que va a estar optimizado para los usuarios que estén cerca de esa región.
Así que, listo, creamos nuestra base de datos, modo prueba por ahora, ¿vale?
Veremos el tema de las reglas en otro vídeo.
Y ahora, pues, va a estar, están como un montón de trabajadores tocando un montón de teclas,
creando la base de datos y vamos a ver qué saca por aquí.
Dice aquí Nicolás, Nicolás Santis,
¿Algunas regiones creo que limitan el free tier?
Pues no tengo ni idea, pero creo que sí que hay como algunas ventajas si no estás en free tier, ¿no?
Como que puedes tener o multiregión o cosas así.
O sea, sí que hay limitaciones, pero no sabía si había limitaciones a nivel de, a ver, ¿región?
No, ¿región? Bueno, pues no, no lo sé, no lo sé, lo podemos mirar después y eso.
Pero sí que me suena a lo que comentas, ¿eh?
De que podías tener o replicada la base de datos en más de una, cosas así.
Vale, a ver qué más, dice Junior.
Consulta, en el caso que el usuario actualice, por ejemplo, su avatar, el ser no SQL y la base de datos,
si ese usuario tiene millones de debits, habría que actualizar todos esos debits.
Efectivamente, Junior.
Y veremos, ahora lo vamos a hacer así, ¿vale?
Porque no tenemos el usuario, pero veremos que tenemos que estudiar bien esto que comentas, ¿no?
¿Cuántos cambios tenemos que hacer de repente cuando haya una información no normalizada?
Como, por ejemplo, el avatar.
Entonces, el avatar veremos que es algo que tiene sentido, que esté a nivel de usuario.
Pero hay otra cierta información que a lo mejor no tiene sentido.
Por ejemplo, podríamos tener en cada debit, a lo mejor, los likes y los retuits.
De hecho, lo vamos a tener.
Y eso es una información que podríamos tener a nivel de, por ejemplo, los usuarios podrían tener una tabla y tal.
Pero aquí lo podemos hacer que se actualice cada vez que se actualiza en realidad la colección del usuario.
O sea, cuando la colección del usuario que tiene sus favoritos se actualiza,
podríamos actualizar automáticamente el número de favoritos que hay en un debit o al revés, ¿vale?
Lo que vamos a buscar es más eso, más que agregar los datos y hacerlos en el cliente.
A lo mejor lo que vamos a hacer es que la información que no esté normalizada
lo vamos a querer actualizar en Cloud Functions o cosas así, ¿vale?
Vale, pues ya tenemos nuestra colección aquí.
Como podéis ver, pues ahora mismo está vacía.
Nos ha puesto un número aquí bastante peligroso.
Este 6661A.
Vale, entonces, ahora que ya tenemos esto, vamos a tirar por el tema de utilizar este Firebase, ¿no?
Porque ahora mismo no lo estamos utilizando.
Así que, como hemos creado, ahora mismo no tenemos ninguna colección, podríamos crear una.
Hay como tres niveles, ¿no?
Que digamos que tendríamos en Firebase, tendríamos la colección, luego dentro tendríamos el documento
y dentro de cada documento tendríamos como data, como la información, ¿no?
Como cada una de las propiedades de ese documento, ¿vale?
O sea, que son colecciones de documentos.
Y veremos que los documentos son muy parecidos al JSON, a un objeto JSON de toda la vida.
Así que ahora, para utilizar este adddebit con Firebase, lo que tenemos que hacer primero sería inicializar la base de datos.
Para inicializar la base de datos, ahora, la verdad, no me acuerdo.
Así que lo vamos a ver.
¿Cómo era Firebase?
Init.
Firebase.
Firestore.
Mira, primeros pasos.
Agregar, etc.
Vamos a verlo en un momento.
Es que no me acuerdo ahora, modo prueba, esto ya lo tenemos, esto, es que es súper fácil.
Es que ahora tenía dudas de si había que, vale, la colección la he tomado después, vale.
Es tan sencillo como esto, vale.
Bien.
Lo que tenemos que hacer aquí entonces es que era primero la, es que a veces las cosas más sencillas son las que uno se olvida.
Vale, para inicializar el servicio de Firestore, lo que tenemos que hacer es Firebase.firestore y no necesitamos pasarle ningún tipo de configuración.
Esto ya tenemos aquí como la base de datos.
No tenemos la base de datos, ¿vale?
Aquí lo que tenemos es como el servicio.
Porque todavía tendríamos que decirle qué colección es la que queremos utilizar.
O sea, que aquí tendríamos como el servicio de base de datos.
Ahora sí, lo que podemos hacer aquí es que hay un momento que me he emparanollado de que no sabía, ¿sabía que pasarle ya la colección?
No.
Tenemos la base de datos y aquí le decimos la colección en la que queremos trabajar.
En este caso le vamos a llamar debits.
Aquí le vamos a decir que queremos añadir un nuevo documento.
Para eso, cuando hacemos punto, aquí tenemos un montón de cosas, es punto add.
Y le tenemos que pasar el documento que queremos añadir.
Así que el documento que queremos añadir, ya tenemos el avatar, el contenido, el user ID y el username, ¿vale?
Estas son cuatro cosas que tenemos segura, que seguro que queremos añadir en nuestro documento para la colección debits.
Ahora bien, por ahora vamos a añadir tres cosas más.
Vamos a añadir, por un lado, cuándo se ha creado.
Para añadir cuándo se ha creado, creo, podríamos probarlo, pero tampoco quiero liarla,
que podríamos hacer esto, pero como no estoy seguro, sé que hay otra forma, que es utilizar Firebase,
donde le dices, podemos utilizar Firebase punto, Firestore punto.
Y aquí tiene una clase que es timestamp.
Y dentro de timestamp tiene un método estático que se llama fromDate.
Y aquí le podemos pasar una fecha.
De esta forma, lo que vamos a hacer aquí es crear un timestamp que es compatible con Firestore
a partir de la fecha actual, del momento ahora, ¿vale?
Entonces, no tengo duda si con el new date directamente funcionaría,
pero como la última vez que lo hice, lo hice así, vamos a continuar así.
No sé si es alguna cosa que ha podido cambiar.
Lo estudiaré y lo miraré a ver.
Pero si alguien me dice que no, pues me lo comentáis.
Vale, ¿qué más?
Luego vamos a poner el likes count, que lo vamos a poner a cero por ahora,
y vamos a poner el shared count, que serían los retuits, que lo vamos a poner a cero.
Hacemos un retool de este add porque el objeto que añadimos, o sea, este documento,
cuando lo añadimos, esto devuelve una promesa.
Y de esta forma seríamos capaces de encadenar cualquier cosa una vez que hemos hecho el add debit.
Por ejemplo, actualizar el estado para, no sé, pues si ha ido bien, pues para mandar al usuario a otra página,
que tiene sentido, ¿no?
Que esto es algo que es lo que hace Twitter, ¿no?
Que cuando tú haces un tweet, pues te manda a la home, no te deja ahí y ya está.
O si hay un problema, pues de esta forma lo sabríamos y podríamos enseñarle una información en el formulario.
Vale, pues ya tenemos esto.
Voy a guardar los cambios.
Ahora me dice, ¿qué está pasando?
Vamos a ver si esto funciona bien porque he sido aquí.
Hola, este es mi primer debit.
Top.
Y vamos a probar si mete emojis, ya que estamos.
Le voy a dar a debitear.
Vale, no ha pasado nada.
O sea, no sabemos si está petado o no ha hecho nada.
Vamos a ir a la consola y, bueno, vamos a darle otra vez.
A ver qué.
Debitear.
Bueno, no aparece absolutamente nada.
Vamos a ver a Firebase, a ver qué pasa.
A ver si sí que lo hemos hecho o no lo hemos hecho.
Vale, pues no lo hemos hecho.
O no aparece por ahora.
Vamos a ver.
Vale, sí, sí, sí que aparece.
Se han creado los dos, ¿vale?
Perfecto.
Aquí podemos ver los dos debits que hemos añadido.
Aquí tenemos toda la información.
Avatar, content, created ad, likes count, share count, user id, username, que es justo lo que hemos enviado.
Puedo ver que el created ad, además, lo ha creado correctamente.
Lo que es interesante de esto es que, como puedes ver, no hemos tenido que crear un esquema para decirles cómo son los documentos, sino que nosotros hemos enviado el documento y automáticamente ha dicho, vale, esto es una cadena, esto es una cadena, aquí esto es una marca de tiempo, un timestamp, esto es un número, esto es un número.
Pero directamente ya como que ha detectado el tipo de los datos y ya ha creado su propio esquema.
Esto está muy bien, pero esto de no tener un esquema está muy bien, ¿no?
Que te lo cree.
Pero también tienes que tener en cuenta que puede haber peligro.
¿Por qué?
Porque al no tener un esquema, nosotros ahora mismo podríamos enviar un documento que no encajase con este esquema a la misma colección y se lo tragaría con patatas fritas, ¿vale?
Podríamos enviar debits que no tuviesen el avatar y se lo comería.
No te daría ningún error, no te diría que algo está funcionando mal, o sea que ten cuidado con esto, ¿vale?
Porque esto te puede fallar muy estrepitosamente.
No nos está haciendo ningún tipo de chequeo.
Es algo que se controla más a la hora de enviar la información, pero está bien que lo sepas.
Luego, aquí ya podemos ver que ha sido súper rápido de tener aquí la información, así que lo bueno es que ya funciona.
Vamos a hacer algún mínimo detalle para arreglar un poquito más esto.
Por ejemplo, he visto que cuando le he dado, le podría seguir dando ahí infinito, ¿no?
O sea que vamos a hacer dos arreglos.
Uno, lo que vamos a hacer aquí, vamos a quitar esto.
Bueno, tapo un poquito, pero ya está bien.
Y esto lo vamos a hacer.
Una cosa que podríamos hacer, más que nada para evitar que pueda darle muchas veces el usuario,
podríamos poner form states y aquí tener, por ejemplo, mientras esté cargando,
bueno, es como un enum, o sea, no es importante el string, ¿vale?
Esto puede ser un número, por ejemplo, cero, ¿vale?
Loading, ¿qué más?
Podría ser un success, ¿qué más?
Podríamos tener un error, podríamos tener también,
más que form states, puede ser compose states,
porque podríamos también tener user not known,
podrá ser también, esto podría ser cero, este podría ser uno, el dos.
Como os digo, tampoco los números son importantes.
De hecho, podríamos utilizar símbolos directamente.
Lo importante es que nos sirvan de referencia.
Bueno, no sé si lo podamos utilizar todos ahora,
pero lo importante de esto es que ya podemos tener una forma
de saber cuándo está ocurriendo cualquier cosa.
Por ejemplo, aquí podríamos tener ya este...
Compose status.
Vamos a poner status, me gusta, status.
Y aquí podría ser compose states.user not known,
porque al principio no sabemos si el usuario está,
podríamos hacer un playholder,
que lo haremos más adelante en enseñar el avatar del usuario.
Entonces, este set status, aquí, antes de hacer el submit,
lo podríamos pasar a compose states, compose states,
lo podríamos pasar a loading.
¿Y qué pasa?
Que cuando esto es loading, y lo hacemos justo antes,
lo que podemos hacer es que el botón no solo se esté desactivado
cuando el mensaje está vacío, sino que también isButtonDisable
cuando el mensaje...
Vale, vamos a ponerlo igual.
Cuando sea falsi...
Uy, tres.
O cuando el status este, el status que tenemos en el estado,
el status sea que está haciendo loading.
De esta forma, y esto lo ponemos aquí,
de esta forma, mientras se está cargando,
pues tendremos el status diferente al loading, ¿no?
Que esto nos permitirá evitar que se vuelvan locos un usuario
y envíe tres tweets, ¿no?
Que solo se puede enviar uno.
Luego también, pues cuando hacemos el den de esto,
lo que podemos hacer es enviarlo a la página, ¿no?
A la página de la home.
Para que vea que se ha publicado su tweet, por ejemplo.
Entonces, podemos ir aquí a la home.
Es que no tengo claro si te lleva a la home o te lleva a tu perfil.
Lo podríamos mirar.
Por ahora, lo vamos a hacer a la home, ¿vale?
Para simplificar.
Así que, vamos a hacer otra vez lo mismo.
Utilizamos el router.
El router lo importamos.
Lo ha importado automáticamente de nextRouter.
Aquí es lo que quería enseñar.
NextRouter.
Y ya está.
Ahora, de esta forma, pues hacemos un push y lo llevamos a la home.
¿Vale?
Una vez que ha hecho el commit, pues lo llevamos a la home.
Y luego podríamos hacer el catch,
por si hay algún tipo de error.
Esto.
O podríamos cambiar el status y el composeStates,
pues ya tendría que ser algo diferente que sería que hay un error.
Y aquí incluso podríamos poner que error sería y todo esto, ¿no?
¿Vale?
A ver qué es lo que me gusta.
Vale.
No le gusta que no estamos haciendo nada con el error.
Bueno.
Por ahora, vamos a ponerlo así.
Para saber que si ha habido algún problema.
Pues seguimos aquí con debit.
Rocket, Rocket y debitear.
Y ahora, fíjate bien que el debitear, cuando le haga clic,
debería desactivarse.
Y me debería evitar volver a darle, ¿no?
Entonces, lo que voy a hacer es darle muchas veces para ver si
realmente funciona correctamente, ¿no?
Le voy a dar unas cuantas veces a ver cuántos documentos nos crea.
No sé si esto sea lo suficientemente rápido.
Me imagino que sí.
Que debería, si no, lo que podríamos hacer es algún tipo de
Thrustling o lo que sea, ¿no?
Para, oye, que solo puedas enviar uno.
Pero, bueno, por ahora lo vamos a dejar así.
Tampoco vamos a llevar más allá de esto.
Porque me interesa más que leamos los documentos de Firestore y
así cerremos más el ciclo.
Pero al menos tenemos esto, ¿no?
Le damos a debitear.
Le he dado a debitear.
Le he dado dos veces, ¿vale?
Así que vamos a ver.
Aquí, vale, parece que sí que más.
Este es mi primer.
No, solo me lo he enviado una vez.
El que, ah, no, me lo he enviado dos.
Me lo he enviado dos, ¿eh?
Sí, sí, sí.
Nada.
Pues haremos lo de Throttle, ¿vale?
Para evitar esto.
Por ahora, ya que estamos en la home,
lo que queremos aquí es justamente leer.
Ya sabemos que somos capaces de enviarlo.
Ahora lo que tenemos que ser capaces es
demostrar aquí la información y leerla.
Así que vamos a ver cómo lo podemos hacer.
Realmente, para leer es bastante fácil.
O sea, no tiene tanto.
Hemos visto que añadir es súper fácil, ¿no?
Pero leer, pues, es básicamente lo mismo.
Vamos a crear aquí también otra constante.
Le vamos a llamar fetch latest debits.
Y veremos que nos iremos dando cuenta que esto lo debemos ir
adaptando mejor a las oportunidades que nos da Firestore.
¿Por qué?
Porque, claro, ahora vamos a hacer un fetch de los últimos debits.
Pero a lo mejor queremos que el usuario pueda seguir gente.
Entonces, su home no será tanto los últimos debits y ya está.
Sino que realmente tendremos que filtrar lo que está siguiendo ese usuario.
Así que eso lo puede complicar un poquito.
Así que veremos cómo le damos un cambio y ya está, ¿vale?
Me dice, se ha enviado dos veces porque el botón ha perdido el disable con el and.
Ay, tienes razón.
Muy bien, Adolfo.
Sí, sí.
Creo que es verdad.
Mira, aquí creo que me he equivocado, ¿verdad?
Este isDisable, esto está mal.
No es un and.
Es un or.
De hecho, ay, bueno, todo el mundo me lo está diciendo aquí.
Creo que si tiene más sentido un or, no sería un or.
El operador es el or.
Tenéis toda la razón.
Es un or.
Era un or.
O sea, si el mensaje está vacío o está cargando, hacemos el disable.
Tenéis razón.
Tenéis toda la razón.
Vamos a probarlo otra vez.
Teníais razón.
Por eso la estrellita...
Uy, le he dado sin querer.
Teníais razón.
Por eso la estrellita de GitHub Stars debería ser vuestra.
Teníais razón, ¿vale?
Vamos a darle.
Ahora sí, ahora sí.
Ahora sí que se ha puesto...
Es que como estaba encima no me he dado cuenta, pero es verdad.
O sea, es verdad.
Vamos a ver cuántas veces se ha grabado el Teníais razón.
¿Vale?
A ver si...
Seguimos aquí.
Teníais razón.
Solo se ha grabado una.
¡Bravo!
¡Muy bien!
¡Bravo!
Lo habéis arreglado.
Muy bien, muy bien.
Me encanta cuando estáis atentos, ¿eh?
Me encanta.
Y estáis ahí viendo...
Oye, ¿qué has hecho de esto?
¿Qué lo otro?
Me encanta.
No dejéis nunca de hacerlo.
Que me chifla.
Vale.
De la misma forma que hemos hecho antes el punto add, aquí también vamos a utilizar la colección
de debits, pero ahora lo que tenemos que hacer es otra cosa.
Es hacer un get.
Y al hacer el get, vamos a hacer un get ahora mismo de toda la colección.
¿Vale?
Hacemos el get de toda la colección y esto lo que nos devuelve es una promesa.
Voy a hacer...
A ver si puedo hacer esto un poquito más pequeño.
Vale.
Y voy a formatear esto para que lo podamos ver.
Vamos a ver qué nos devuelve esta promesa.
Esta promesa nos devuelve una cosa un poquito especial que se llama un snapshot, ¿vale?
Que es como una fotografía o un punto de cómo queda ese acuerio.
Hay gente que le puede llamar como cursor, pero básicamente no es el resultado.
Hay que tratarlo, ¿vale?
Es como un objeto complejo que tiene Firebase que nos va a permitir obtener los resultados,
pero todavía no los tenemos ahí tal y como nos gustaría, ¿vale?
Entonces, este snapshot que nos llega aquí...
Snapshot.
Si miramos la documentación oficial, seguramente nos diría de hacer algo así, ¿no?
Porque el snapshot tiene aquí el for each y podríamos, a partir del for each,
podríamos hacer una iteración y guardar la información y luego hacer un return y tal.
Y está bastante bien, pero...
Bueno, está bastante bien.
Está bien, pero se podría hacer de otra forma.
Que no sé por qué esto no sale en la documentación o no sale tanto o no lo he visto tanto.
Pero hay una forma de acceder directamente a los documentos que tenemos en este snapshot, ¿vale?
En este resultado de esta query en el formato de Firebase.
Entonces, si utilizamos los docs, ahí tenemos el array de resultados, ¿vale?
Tenemos un montón de cosas.
Por ejemplo, for each.
Podemos ver el size para ver el tamaño que tiene.
O sea, tenemos un montón de cositas que podemos hacer.
Pero una de ellas sería recuperar directamente los documentos, que es justamente lo que queremos.
Y como los documentos que recuperamos aquí ya es un array, ya lo que podemos hacer es un map.
Y con el map podemos mapear estos resultados a lo que queremos.
Porque todavía tenemos que tratarlos.
Pero al mapearlos, esto nos simplifica bastante porque podemos hacer directamente un return de esto.
Al hacer un for each, el for each no puedes hacer un return directamente.
Y tiene un poquito más de peligro.
Así que hacemos esto.
Hacemos el mapeo.
Y con el mapeo lo que vamos a hacer es tener un doc, que es un documento, ¿no?
Aquí tenemos el documento.
Pensad que si estamos haciendo snapshot.docs, el .docs sería todas estas documentos de la colección de bits.
Cada uno de estos documentos.
Y ahora cada documento es lo que vamos a iterar con el mapa, ¿vale?
Así que ya lo tendríamos ahí.
Y ahora el doc tiene un método especial, no sé si va a aparecer.
Bueno, veo que no.
Que es .data.
Este método lo que nos va a hacer es como extraer todos los campos que tenemos en ese documento.
Y los campos los vamos a tener como un objeto.
Es un poco raro, ¿vale?
Porque aquí alguien podría esperar que en .doc ya tuviésemos, por ejemplo, el avatar.
Pero no es así, ¿vale?
Tenemos que transformarlo.
Tenemos que transformar ese objeto complejo de Firebase, ese documento, lo tenemos que transformar a un objeto plano.
Y para hacerlo haríamos esto.
Así que aquí tendríamos ya el data.
Ya tendríamos el objeto.
Lo vamos a guardar aquí en data, por ejemplo.
Y aquí podríamos devolver data.
Podríamos hacer un return directamente.
Pero vamos a ver que vamos a necesitar hacer algún tipo de cambio.
¿Por qué?
Porque si miramos nuestro documento, aquí podemos ver que no tenemos ninguna ID.
No hay una ID del debit.
No sabemos qué ID tiene, qué identificador.
¿Cómo identificamos esto?
Vale.
El tema es que Firebase, cada vez que tú creas un documento, nos genera una ID totalmente automática.
Y que además nos sirve.
Que sería esta que podemos ver aquí.
Ahora, para recuperar esta ID, lo que tenemos que hacer es utilizar la propiedad ID.
Así que igual que tenemos el data con el .data y ahí tendríamos la parte de la derecha, todos estos campos que tenemos aquí, para recuperar la ID tendríamos que hacer un .doc.id.
Así que la ID la tendríamos en .doc.id.
Así que ahora vamos a devolver un objeto que por un lado tenga la ID y por otro lado tenga todas las propiedades, ¿vale?
Las propiedades que hemos recuperado en data.
Por ahora esto es todo lo que necesitamos.
Tener la ID del debit y todas las propiedades del documento.
Así que con esto guardamos los cambios y vamos a ir a la página home para dejar de utilizar esto que teníamos por aquí.
Y lo que vamos a hacer es utilizar este fetch latest debits, ¿vale?
Así que vamos a hacer esto fuera y hacemos un fetch latest debits.
Esto nos devuelve una promesa.
Y cuando tenemos la promesa podemos utilizar el set timeline para guardar esa información.
Ahora este fetch tenemos que importarlo, claro, si no esto no funciona.
Y lo hacemos de Firebase client, ¿vale?
Guardamos los cambios.
Ahora funciona y, bueno, está bastante bien porque se ve mi careto en muchos sitios.
No se ve el mensaje, no se ven cosas, pero eso lo vamos a arreglar ahora.
Esto no funciona porque seguramente el contrato ha cambiado.
Pero por ahora vamos a quedarnos con esto.
He hecho el fetch, esto nos devuelve una promesa.
Y para que lo veáis muy claro y esto no nos liéis,
esto sería una promesa que recibe el timeline.
Este timeline es un array donde cada array es un objeto que tiene una ID
y todas las propiedades del documento como un objeto con sus strings y tal.
Y luego aquí lo que estamos haciendo, una vez que tenemos el timeline,
hacemos un set timeline de lo que nos viene como parámetro.
Ahora, como esto, en realidad este set timeline recibe como parámetro el timeline
y aquí tenemos una función que a su vez recibe, o sea, el timeline como parámetro,
podemos hacer esto y dejarlo mucho más limpio, ¿no?
Que .den, pues ese parámetro se lo pasa directamente al set timeline.
Y esto ya nos lo guardaría ahí.
Y ya nos está mostrando, o sea, ya está funcionando hasta cierto punto.
¿Por qué?
Porque el avatar seguramente tiene el mismo nombre.
Pero si miramos aquí los campos que está recuperando el timeline
cuando hacemos el map aquí, pues vemos que tenemos ID, Username, Avatar, Message.
Y creo que Message no lo hemos llamado.
Esto lo hemos llamado content.
Podríamos hacer diferentes cosas.
Por ejemplo, podríamos recuperar aquí el content y hacer el mapeo aquí de Message.
Y al menos ya deberíamos ver nuestro mensaje.
Aquí hay diferentes alternativas.
Ahora mismo podríamos hacerlo así para simplificarlo.
Pero creo que lo mejor es siempre referirnos a la información de la misma manera en todos los sitios.
Y evitar que en un sitio tengas content y otro message y tal porque puede ser que te líes un poco.
Entonces, vamos, esto como es un momento, vamos a hacer aquí el content.
Vamos a hacer que esto sea content.
La idea, eso sí que está bien.
El Username, aquí hemos hecho al final que sea camel case.
Así que vamos a poner que el Username que recibe aquí sea Username, todo en mayúscula.
Luego, el User ID es justamente, no lo necesitamos como tal.
Luego sí que podríamos hacer, bueno, se lo vamos a pasar porque lo necesitaremos, el User ID.
Para cuando alguien haga clic en el avatar que pueda ver su perfil, User ID.
Y tenemos el avatar, el Content Created Add.
El Created Add también, Created Add.
Created Add.
Vale, Created Add.
Esto se lo vamos a poner así.
Es verdad que si esto se lo hubiésemos pasado todo directamente así, ¿no?
A Cholón, ¿no?
Recuperamos, por ejemplo, el Timeline, bueno, Debit.
Pues esto nos hubiera simplificado la vida.
¿Por qué?
Porque ahora mismo no teníamos que estar cambiando constantemente.
Pero en la anterior clase ya os comenté un poco los problemas que también comporta esto.
Y creo que está bien controlar exactamente qué props les está llegando a tu componente.
Sé que no queda tan limpio, sé que es un poco más engorroso, pero una vez que lo haces, tienes la seguridad de la información que le está llegando.
¿Vale?
Así que por ahora vamos a hacer esto.
Tenemos la ID, tenemos la Key, la ID, Username, el avatar, el Content, Created Add.
Vale, pues lo que necesitamos ahora mismo.
He guardado los cambios.
Vale.
A ver ahora.
¡Pum!
Vale.
Vamos a ir a Debit y lo que vamos a hacer en este componente es cambiar un poquito el contrato que teníamos.
Este Message ya no tiene sentido.
Vamos a poner Content.
Porque la verdad es que Message también era un nombre un poco raro.
Ahora tenemos aquí el Created Add.
Así que podríamos utilizarlo aquí.
Tenemos, ah, el Username también, ¿vale?
Username como camel case.
Así que Username.
Esto que se ponga ahí.
Para la estrellita.
Ahora mirando Twitter.
Vamos a ver un momento Twitter.
Vale.
Esto es un poco lo que os comentaba antes.
Tenemos el nombre del usuario, pero como tal no tenemos el Username.
Esto lo vamos a solucionar en la siguiente clase porque vamos a crear la colección User y vamos a ser capaces de guardar cierta información que nos va a venir bien.
Además, seríamos capaces de darle la oportunidad al usuario que cambie cierta información si quiere.
O sea, recuperaremos información de GitHub, la guardaremos y una vez hecho eso podremos mostrar, por ejemplo, el Username que tiene en GitHub.
Y más adelante podríamos permitirle al usuario que cambie su nombre de usuario.
Tendría uno por defecto que sería el que recupera de GitHub, pero por ejemplo, si yo no quiero aparecer como Miguel Ángel, podría cambiarlo.
Este sería el que tendríamos por defecto, pero luego lo podríamos cambiar sin ningún tipo de problema.
Entonces, para dejarlo un pelín más parecido, vamos a pasar esto aquí y aquí vamos a poner el Date.
Que esto sea, por ahora tampoco lo vamos a formatear, vamos a dejarlo Created At.
No sé por qué esto.
Ahora, Created At, vale.
Vale, el problema del Created At es que creo que me lo está, vamos a ver cuál es el Created At.
Claro, esto seguramente el cómo lo está formateando, vamos a ver esto, porque lo que estamos intentando es renderizar un objeto complejo como si fuese algo de React.
Pero veis, he puesto el Created At y es esto, es un T, ¿sabes?
Y esto no tiene mucho sentido.
Pero vemos que nos está devolviendo segundos.
¿Qué pasa?
Que esto lo deberíamos nosotros transformar a una nueva fecha.
Así que lo que podemos hacer es, vamos a ir al Client de Firebase y aquí, esto lo voy a simplificar un poco, ¿vale?
Vamos a poner aquí el Docs, esto lo recuperamos de aquí, el Doc ID, bueno, esto aquí.
Luego, en el Data, aquí podemos recuperarlo directamente, pero vamos a Created At de Data.
Y vamos a poner que el Created At sea Normalize Created At.
Y este Normalize Created At, pues vamos a ponerlo del New Date, Created At.seconds.
Creo que era así.
No sé, vale.
Aquí se me ha olvidado una coma.
Y esto lo tenemos que poner arriba del todo para machacar, porque si no, claro, no estamos machacándolo bien.
Y esto además lo vamos a poner como un ToString, porque si no también sigue siendo un objeto complejo.
Ahora nos lo va a formatear muy extraño, pero no funcionaría.
Esto podríamos normalizarlo, de hecho, InterFormatDateTimeFormat.
Sí, esto puede funcionar.
Vamos a formatearlo en nuestro idioma, además.
Vale, así que vamos a hacer esto.
Vamos a hacer esto.
Esto básicamente es un constructor que tiene JavaScript, que no es muy, muy viejo.
Bueno, a ver, ya tiene su tiempo.
Pero que está integrado en el navegador, o sea, que podremos traducir y un poco formatear nuestra fecha de una mejor forma de como lo hacíamos hasta ahora.
Porque además va a tener en cuenta nuestra información.
O sea, le podemos decir el formateador este internacional, le podemos decir de qué país somos y qué lenguaje utilizamos y tal.
Así que podemos hacer el Intel este.
Aquí vamos a decirle que estamos en España porque de esta forma podemos formatear esta, esto, esto lo hacemos, a ver, eeeintel.format y formateamos esta nueva, a ver, es que se lee súper chiquitito.
A ver, vale, he creado el Intel.
Le he dicho un nuevo daytime format en español y le estoy diciendo que me formatee esta nueva, esta, esta, esta fecha que viene de este timestamp y vamos a ver.
Vale, vale, me pone 1970.
1970. A ver, cuando no formateado me ha salido bien porque es posible que la esté liando y a lo mejor, a ver, me salía bien la, a ver, a ver, toString.
No, no, no, me sale mal. Vamos a ver. Igual cuando lo he puesto también, Firebase, el avatar no debería venir, mira, voy a leeros por si me decís la solución, ¿eh?
Format date.
Timestamp. Igual tengo que utilizar otra vez el de timestamp. La verdad es que ahí sí que no me acuerdo para nada.
Get seconds, esto lo hemos hecho ya, toDate. Vale, pues esto pinta bien. Vale, vamos a utilizar este.
Básicamente, como teníamos esto de antes, este Firebase, no sé qué, no sé cuánto, toDate, y aquí le pasamos el new date.
Claro, no, pero es que el problema, como tal, es como lo estamos creando, bueno, ¿sabéis qué?
Lo vamos a dejar para la siguiente y me lo miraré con calma, a no ser que me queráis hacer una PR.
Os voy a echar trabajo. Ya sabéis que esto es de código abierto, por lo tanto, vamos a dejarlo por ahora sí,
vamos a dejar que esté mal la fecha porque ahora mismo veo que está mal.
No me queda claro si la estamos guardando mal, que yo diría que no, ¿no?
Porque estamos haciendo un new date, esto tiene buena pinta de la fecha, tal, esto tiene buena pinta,
pero si por lo que sea lo estamos haciendo mal o tenemos que hacer algo más, pues os dejo estos deberes.
Se aceptan pull requests, ¿vale? Para que hagamos esto, por ahora lo vamos a dejar como estaba,
con el create at, y lo voy a dejar así más o menos porque aquí faltaría formatear bien la fecha, ¿vale?
Y bueno, por ahora la dejamos así, bueno, esto, el create at, voy a dejar, vamos a dejar el create at,
porque si no, create at, normalize, create at, vamos a hacer esto, normalize, no está bien del todo,
pero al menos vamos a hacer que sea un string, ¿vale?
Y luego más adelante veremos, porque yo estoy bastante convencido,
Joder, new date, ah, porque hay que extraer los segundos, seconds, seconds, ¿era?
Puede ser, ahí, a ver, create at, era, o sex, ahora no me acuerdo qué es lo que hemos añadido aquí, a ver,
Pi, pi, o añadir, validate seconds, punto seconds, ah, es que no era una función, era una propiedad,
vale, vale, pues ya está, vale, pues esto, punto seconds, esto lo cerramos aquí, ponemos el toString,
y ya le enviamos la normalizada, ¿vale?
Tu, tu, vale, ahora no le ha gustado otra cosa, porque tu, tu, el new date, tenemos ahí el seconds, vale,
está mal la información, pero al menos la vamos a dejar así, porque al menos está mostrando algo, ¿vale?
¿Estás usando Firebase directo desde React? ¿Qué pros y contras existen en eso en vez de usarlo desde Node como una API?
Pues la verdad es que tiene sus pros y sus contras, efectivamente.
Una cosa que estaría bien es que podríamos, podríamos hacer que los tweets que ocurren en tiempo real, pues aparezcan ahí, ¿no?
Podríamos detectar cuando se está cambiando algo, ¿no? Que alguien está haciendo un tweet, pues que aparezca automáticamente.
Y este real time, hombre, está bastante bien, porque esto viene fuera de la caja.
Desde el servidor podríamos tener ventajas en cuanto a rendimiento, porque claro, podríamos mostrar en el servidor,
renderizar ya los tweets que queremos mostrar, pero como verás incluso en Twitter, esto, todo esto lo hace en el cliente.
¿Por qué? Porque en el cliente vas a ser capaz de enseñarle cierta información antes de tener los tweets preparados
y además tienes como esa sensación de más de inmediatez con los tweets, ¿no?
Porque, por ejemplo, ves que a veces hay un tweet que es de hace un segundo.
Claro, eso si lo hicieses desde el servidor podrías lograrlo, pero no sería tan, tan inmediato, ¿no?
Tendrías algún tipo de, no verías eso tan increíble de un segundo, ¿no? Porque haría un poquito más de tiempo.
A ver, eso sería un poco en el tema de Twitter, ¿no?
Desde el servidor también podríamos controlar mejor el hacer el renderizado del servidor y a lo mejor tener mejor SEO,
pero en casos de Twitter y en este caso que es una aplicación que vamos a querer, que eso puede entrar cuando el usuario está registrado,
pues tampoco es tan interesante, ¿no?
Así que, no sé, en este caso la inmediatez y la facilidad que tenemos en el cliente creo que es lo suficiente,
pero creo que podríamos llegar a hacer un sistema mixto, que es lo que vamos a hacer, ¿no?
Y veremos con el GetStaticProps y cosas así, ¿no?
Vamos a intentar tener cosas estáticas preparadas lo antes posible,
pero luego lo que vamos a hacer es hidratar o mostrar más información cuando estamos en el cliente, ¿vale?
Pues aquí tenemos a Julio Barajas.
Un superchat. ¿Qué recomiendas para pasar el JavaScript Web Token en GetStaticProp?
Bueno, pues aquí tendrías el tema de utilizar cookies, porque necesitas utilizar algo que pueda leer el servidor.
Otro tema es que, aparte de tener la cookie, el JavaScript Web Token, en lugar de enviarle eso,
lo que le envíes es tener un token más corto, que eso lo que te hace es recuperar el JavaScript Web Token.
Eso serían técnicas, pero vas a necesitar que sea sí o sí, que sea por cookies,
porque es que no tienes otra cosa.
Ya sea que le pases el JavaScript Web Token o que tengas un Auth Token,
un token que te permita recuperar el JavaScript Web Token en el servidor,
pero vas a tener que utilizar algo así para utilizar algo que sea universal,
que te funcione tanto en el cliente como en el servidor.
Si no, va a ser más complicado.
Vale, vale. Pues, ¿qué más me comentáis?
¿Qué es mejor en cuanto a performance?
¿Usar context para el user disponible en todo momento?
¿Crear el hook y usarlo en cada componente?
No solo creo que es mejor, creo que sería más correcto utilizar el contexto
y seguramente tiraremos a esa solución para que ese cambio solo lo haga una vez,
porque si no, lo que vamos a hacer es que más de una vez tendremos que tener el hook ejecutándose,
como hemos visto, y la sensación es que debería hacerlo una vez,
debería hacerlo de forma más global.
Entonces, en este caso, yo creo que lo ideal sería que fuese un contexto
y que el custom hook que hemos hecho lea de ese contexto el estado
y ver si está el usuario logado o no.
Así que seguramente lo pasaremos porque no creo que sea correcto
que cada componente, cada vez que lo necesitemos, hagamos esto.
Así que, Sebastián, esta es tu pregunta.
Yo creo que lo más correcto, no solo por temas de performance,
porque lo haríamos solo una vez,
sino porque sería más beneficioso, más fácil de utilizar,
es que lo hagamos tantas veces como queramos,
sin necesidad de ejecutar constantemente los efectos de dentro.
Importante lo que dice Nicolás, porque la cookie que te comento
tiene que ser HTTP only, eso es lo ideal,
que solo se pueda leer directamente de forma segura,
que en el cliente en JavaScript no se pueda leer.
Así lo podrías hacer y funcionaría correctamente, ¿vale?
Y eso sería, no se puede formatear los segundos con JavaScript,
directamente digo, no sería más simple.
Lo que vamos a hacer, voy a esperar un poco vuestras PRs,
a ver qué hacéis, si metéis una librería, si no la metéis.
Yo tengo una idea clara de cómo lo voy a hacer
y qué es lo que voy a hacer una vez que detecte
dónde está el problema de por qué me sale 1970,
que debe ser una chorrada como un piano,
pero ahora mismo no quiero liaros.
Estoy pensando, estoy pensando una cosa,
estoy pensando una cosa, puede ser, claro, es que,
madre mía, madre mía, claro, a ver,
la solución de esto es que estas cosas pasan en directo
y en todos los lados.
Cuando he hecho el create.at este,
y he hecho el console.log y he visto el t este,
claro, he visto nanoseconds y seconds.
Y yo me he liado, y yo me he ido a saco a por el seconds
pensando, ah, no, hago un new date y tal.
Y estoy sorprendido que ninguno de vosotros
no hayáis dicho nada, ¿vale?
Pero el caso, claro, es que cuando haces un new date
no se le pasan segundos, se le pasan milisegundos.
O sea, estos segundos habría que multiplicarlo por mil.
Y entiendo que con esto, ahora sí, ahora sí tenemos bien
la fecha, la estamos guardando bien.
Es que no sé por qué, claro, el problema ha sido
que he visto segundos y nanosegundos, ¿no?
Y he visto, ah, pues me quedo con los segundos.
Pero no, claro, cuando haces un new date,
lo que tienes que pasarle son los milisegundos.
Entonces, para transformar los segundos en milisegundos,
lo multiplicamos por mil y ya está.
Era un error como un piano, era una chorrada, ¿vale?
Aún así, tengo una idea de cómo podemos hacer esto,
ya que he visto lo del time format y tal,
lo que hemos visto del daytime format,
que también lo podemos hacer, por supuesto,
que está bastante bien.
Esto debe ser un momento.
Que hagamos el new daytime format
y le decimos que esto es SS.
Y formateamos format.
Vamos a poner que lo que formateamos sea esta.
Y como yo tengo una regla,
que es el single line responsibility,
que es hacer una cosa en una sola línea,
voy a evitar hacer cosas raras.
Así que vamos a crear primero la fecha
y luego la formateamos aquí.
Date.
Esto debería funcionar.
El output este,
esto ya sea normalize, create, esto.
Esto ya lo podemos eliminar,
que no lo necesitamos.
Y vamos a ver esto cómo queda.
Vamos a ver.
Vale, esto ya queda un poquito mejor, ¿vale?
Entonces, bueno, nos sale la hora.
Queda mejor,
pero no es exactamente lo que tengo en mente,
porque obviamente lo que nos gustaría es poner,
hace dos segundos, hace no sé qué.
Eso lo haremos en la siguiente clase.
Empezaremos por ahí,
de forma que mejoraremos esto.
Luego, esto debería tener aquí una separación
con un puntito, por ejemplo,
un poco para que se parezca más a Twitter,
y hacer un poco más pequeño,
y hacer un poco más gris el date, ¿vale?
Pero bueno, el caso,
el caso es que al final lo hemos sacado,
que más o menos ha quedado más bonito,
ya tenemos la fecha.
Lo que vamos a hacer con esto,
haremos el time ago,
pero lo vamos a hacer sin librerías, ¿vale?
Y veréis que es bastante sencillo,
no es muy complicado hacerlo sin librerías.
Lo vamos a hacer utilizando la plataforma,
ya sabéis que me encanta la plataforma,
pero bueno, me alegro que al final lo hemos solucionado.
Creo que ahora me estáis comentando por aquí.
Moment.js, para la fecha, ¿qué opinas?
¿Podríamos usar Moment.js?
Os voy a decir lo que opino de Moment.js.
No me gusta Moment.js, ¿vale?
No me gusta.
No me gusta porque, de hecho,
los propios creadores de Moment.js
tienen otra librería que creo que es Luxor,
Luxor, Luxor, Luxor, Luxor, Dates,
ah, no me acuerdo,
Format, Dates, Creators, Moment.js,
o Luthor, ¿cómo es esto?
Luthor, Luthor, bueno,
los creadores de Moment.js tienen otra librería
que creo que es más interesante.
¿Qué pasa?
Que en su día los creadores de Moment.js
pues se utilizaron lo que podían utilizar, ¿no?
Y no había muchas APIs dentro del navegador
para formatear fechas.
Ahora Moment.js ha quedado muy, muy,
muy detrás como solución correcta
a la hora de utilizar esto, ¿vale?
Luxor.
Es que no sé.
Format, Dates, a ver, es que estoy convencido
que era Luxor, Luxor, a ver si alguien se la sabe.
Luxon, madre mía.
Gracias, Nicolás.
Luxon, efectivamente, Luxon.
Como veis, es de Moment, o sea, es de los mismos.
Pero la forma de funcionar es bastante mejor
porque al final envuelve los métodos nativos
que ya tiene el navegador.
Entonces, yo si tuviese que hacer algo,
utilizaría Luxon, utilizaría DateFNS,
o no utilizaría ninguno,
que es lo que vamos a hacer en la siguiente clase, ¿vale?
Porque actualmente la plataforma ya nos ofrece
la posibilidad de hacer un time ago súper fácil,
súper rápido, muy bien implementado,
muy, yo diría que bastante soportado en los navegadores,
al menos en los navegadores serios.
Así que, bueno, está diciendo Luxor,
Luxor, y Juan Felipe dice,
a Superman no le gusta eso.
Tiene razón, me gusta Luxon.
Os recomiendo Luxon, ¿vale?
También César nos recuerda que hay una página
que se llama You Don't Need Moment.js,
que está muy bien, ¿no?
Que, bueno, no es una página,
o sí, sí que habrá una página por ahí,
que te comenta un poquito,
mira, aquí está un poco la comparación de Luxon,
ya veis que, o sea, ocupa como cuatro veces menos.
Y aún así, ya os digo,
aunque es mejor alternativa también que DateFNS y DJS,
que es otra alternativa,
aún así, ya os digo que creo que,
dependiendo de lo que necesites,
no se necesita ningún tipo de librería,
que es un poco lo que viene a decir
este repositorio, que está bastante bien.
De hecho, este es el que quiero que utilicemos
el próximo día,
y es el que vamos a utilizar,
RelativeTimeFormat, que es nativo,
y funciona muy bien.
Así que, eso es lo que haremos.
Niñas y niños,
chicas y chicos,
frontenders y frontenderas,
espero que estéis muy bien,
que hayáis disfrutado un montón de la clase,
espero que el próximo día esté mejor de la voz,
que como veis la tengo un poquito pillada.
Muchas gracias a todos por haberme ayudado
cuando he tenido el error ese del OR,
y la verdad es que os agradezco un montón
que estéis aquí súper atentos.
Solo os pido que antes de iros,
dejéis vuestro like,
si os gustan las clases.
La semana que viene haremos otra el viernes.
Vamos a,
como ya sabemos un poco cómo funciona Firestore,
y hacemos más rápido,
y lo que vamos a hacer es dejar el debit bien maquetado,
vamos a mostrar ya todos los likes y todo,
vamos a formatear bien la fecha,
vamos a meter al usuario en el Firestore,
vamos a tener el username y el nombre real del usuario,
eso lo vamos a tener,
vamos a empezar a tener también navegaciones
de cuando haces el compose del tweet,
poder volver atrás,
crearemos todo lo de volver atrás,
adelante y todo esto,
y también veremos la ruta con el segmento dinámico
para poder entrar a un tweet en concreto,
y para que también podamos compartir
con gente esa URL
y puedan entrar directamente a ese tweet,
y de esta forma veremos las URLs dinámicas,
con paz dinámicos.
Esa será la siguiente clase,
si os gusta todo lo que hago,
pues ya sabéis,
le podéis dar like,
podéis suscribir al canal,
estoy también en Instagram,
estoy también en Twitter,
estoy también en Facebook,
aunque en Facebook a lo mejor no tanto,
pero muchísimas gracias por acompañarme,
os agradezco un montón,
que sé que es agosto
y estamos en medio de vacaciones,
y aún así pues somos 114,
y me parece espectacular,
os lo agradezco de corazón,
de nuevo,
me gustaría agradeceros de corazón,
de verdad,
o sea,
no sé cómo deciros,
que os quiero,
por vuestras nominaciones en el GitHub Stars,
esta estrellita,
todas las puntas,
son vuestras,
¿vale?
son gracias a vuestro apoyo,
al apoyo que me dais,
a todo el acompañamiento,
y a la comunidad que creáis,
y muy pronto,
que se me lo habéis preguntado muchos,
vamos a tener las suscripciones,
las membresías,
en el canal de YouTube,
os hago un pequeño spoiler,
van a ser solo dos niveles,
lo quiero hacer bastante sencillo,
no es obligatorio apuntarse,
todo mi contenido siempre va a ser gratuito,
siempre,
pero si queréis contribuir de alguna forma,
y a veces,
pues por lo que sea,
no puede ser por el superchat,
y mucha gente me preguntáis,
creo que la membresía puede estar bien,
es verdad que me pegan una tajada así,
de los superchats y tal,
de un 30%,
la gente de Google,
pero bueno,
vamos a hacer la membresía,
vamos a probar,
a ver qué tal,
he creado una comunidad en Discord,
también,
pues para que ahí podáis proponer vídeos,
y la comunidad,
pues os puede ayudar con las dudas,
yo de vez en cuando,
no os voy a engañar,
no tengo muchísimo tiempo,
pero de vez en cuando,
pues participaré obviamente en la comunidad,
haré lo que pueda,
y creo que puede estar bien,
que estemos en una comunidad ahí más al día a día,
y también me deis muchas más ideas,
de qué vídeos queréis ver,
qué puedo hacer,
por dónde puedo tirar los cursos,
y todo esto,
así que espero tenerlo muy pronto,
para que os podáis apuntar,
y también en septiembre,
el libro de aprendiendo React,
¿vale?
De aprender React,
el libro que a mí me hubiera gustado tener,
con ejercicios prácticos,
va a tener un repositorio,
donde vais a tener ejercicios,
y con un comando,
podréis ir viendo,
si el código,
el ejercicio que habéis hecho,
está bien o no está bien,
va a tener testing,
para que podáis ver,
si has hecho bien el ejercicio,
o no está bien,
así que bueno,
y además es un libro,
que espero ir mejorando,
conforme con el tiempo,
o sea que una vez que lo adquieras,
a lo mejor estará terminado,
como yo entiendo estará terminado,
pero seguro que se me van ocurriendo cosas,
para añadirle,
¿vale?
Entonces el libro,
creo que aparecerá por unos 15 dólares,
lo tengo que mirar más o menos,
para ver lo que sale y tal,
pero irá por ahí,
voy a intentar que sea lo mínimo posible,
pero con el trabajo que tiene detrás,
creo que lo compensa,
¿vale?
De nuevo,
todo el contenido,
todo lo que vamos a hacer,
siempre no está desobligado a nada,
es totalmente gratuito,
y siempre lo vais a tener gratuito,
no vamos a hacer ningún tipo de,
creo que no vamos a hacer ningún curso,
creo que todo lo vamos a hacer en YouTube,
y lo vamos a hacer abierto,
y lo único que espero es poder hacer más contenido,
porque para compensaros vuestra ayuda,
vuestro apoyo,
vuestros likes,
vuestros comentarios,
es increíble todo lo que me habéis dicho estos días,
cuando dije lo de GitHub Star,
mucha gente en privado,
de verdad,
me habéis dicho cosas que me han emocionado un montón,
y espero saber compensaros,
así que muchas gracias a todos y a todas por estar aquí,
gracias Juno García por estar aquí,
muchas gracias Claret también,
ya quiero el libro,
yo también quiero el libro,
porque no veas lo que cuesta escribir un libro,
gracias Carlos,
cuenta conmigo para todo lo que dices,
eres un fuera de serie,
muchísimas gracias.