This graph shows how many times the word ______ has been mentioned throughout the history of the program.
¿De qué vamos a hablar hoy en esta clase del viernes, la midu clase de NextGS?
Pues hoy vamos a hacer diferentes cosas.
Lo primero, las rutas dinámicas de nuestra aplicación.
Al menos una ruta dinámica.
Al ser un clon de Twitter, vamos a necesitar una ruta para acceder directamente a un tweet.
En nuestro caso, un debit, ¿vale?
Porque es un Twitter para desarrolladores.
Entonces, necesitamos tener una URL donde podamos tener la ID de ese debit.
Y eso sería una ruta dinámica, ¿no?
Porque hay un segmento que es la ID que puede ir cambiando.
Así que vamos a ver cómo lo hacemos.
Además, vamos a ver el concepto de Firebase Admin.
Que nos va a permitir desde el lado del servidor acceder a los servicios de Firebase.
En nuestro caso, el que vamos a utilizar es de Firestore.
Que ya lo hicimos y veremos que lo vamos a copiar.
Lo vamos a hacer muy fácil, muy rápido.
Pero esto nos proporciona la posibilidad de acceder a Firestore desde el servidor.
Y esto lo vamos a necesitar cuando hagamos el data fetching en Next.es.
Porque en Next.es puedes hacer el data fetching de diferentes formas.
Pues vamos a ver las diferentes formas que hay.
La que está más deprecada, que es el getInShieldProps.
Y vamos a ir pasando las diferentes formas.
Que luego es getServerSideProps y el getStaticProps.
Vamos a ver un poco las diferencias que tienen, qué comporta.
Las ventajas, las desventajas.
Para qué es ideal cada una.
Vamos a ver hasta dónde llegamos ahí.
Y eso sería un poco la clase de hoy.
Así que, para empezar la clase, como siempre, hay que ir a este repositorio.
Y tenemos todas las ramas aquí ya perfectas.
0.1, 0.2, 0.3, 0.4.
Cada una de las clases.
Para ir al código de esa clase.
En nuestro caso, tenemos que ir a la última clase.
Que sería la de 0.5.
Upload Images for Airbus Storage.
Time to Go, bla, bla, bla.
Que es esta.
Y antes de pasar a la PR esta.
A la PR.
A la rama.
Quería mirar las PRs.
Porque, y esto me encanta, ¿no?
Que siempre estáis ahí aportando.
Y os gusta ir mirando.
Y a ver cómo estamos haciendo las cosas.
Cómo lo podemos mejorar.
Y aquí tenemos un par de aportes.
Uno de ellos, que nos lo trae Mian Game.
Creo que era Miguel Ángel.
Exacto.
Que creo que también está en el chat.
Que he visto por ahí.
Pues ha hecho uno que me ha gustado mucho.
Que es el hecho de añadir el Created Add.
Pero formateado en el título de la fecha.
Porque, ¿qué pasa?
Que aquí en las fechas, cuando tú te pones encima.
A ver si sale.
Ahí.
Aparece la fecha bien formateada, ¿no?
En lugar de tener el formato este del tiempo relativo.
Que es el que hicimos en la última clase.
No se aparece con el tiempo como bien formateado.
Perfecto.
Pues eso lo vamos a incluir.
Gracias al código que ha hecho Miguel Ángel.
Y él ha creado un hook aquí.
Que es bastante similar al UseTimeGo.
Pero para utilizar otra API.
Que es del Internationalization.
¿Vale?
Que es el DateTimeFormat.
Que también le puedes pasar tu lenguaje.
Y el tipo del formateo que quieres hacer de la fecha.
Es parecido al RelativeTimeFormat que vimos en la clase anterior.
No es exactamente igual.
Pero esto es lo que nos va a permitir.
Además ha cambiado aquí.
Ha puesto el title.
Pero hay un error.
No es suyo.
Es mío.
Hay un pequeño error aquí.
Y es que el Date no está bien.
Tenemos que utilizar Time, me parece.
De hecho, esto lo he visto ahora.
He visto Date rápidamente y me he dado cuenta.
Yo diría.
Vamos a ver.
Exacto.
El correcto debería ser Time.
O sea, la etiqueta Date que puse en su día está mal.
Ahora lo arreglaremos.
Y lo que tendríamos que poner es un DateTime.
En lugar de poner el title.
Que el title puede estar bien porque seguramente funcionará.
Pero esto debería ser Time.
Esto lo vamos a arreglar.
Lo vamos a mergear, si os parece.
Así quedará ya en la rama que vamos a descargar.
Que es la de subir.
Bueno, es la de la semana pasada.
Pero bueno, le vamos a dar un dedito.
Lo vamos a probar.
Un poco para ver un poco el workflow de cómo haríamos esto.
Y vamos a hacer un merge de esta pull request.
Así que así nos quedamos los cambios.
Y cuando descarguemos la rama, pues ya lo tendremos.
Luego, tiene otro que es el del refactor layout.
El del refactor layout lo vamos a hacer, pero no lo voy a mergear ahora.
Lo vamos a hacer desde cero.
No lo voy a hacer porque ahora, tal y como está, me gustaría que viésemos exactamente por qué.
En lugar de hacerlo fuera de cámara, ¿vale?
Y creo que, bueno, está pendiente un tema de loading y todo esto.
Pero por ahora, creo que ya está bien.
Así que, este, si no lo tenéis, el repositorio, os lo voy a dejar ahora mismo en el chat, ¿vale?
Os lo dejo en el chat, por si estáis en directo.
Y si no, os lo dejaré en la descripción.
Siempre lo dejo en la descripción del vídeo, si lo ves en diferido, ¿vale?
Perfecto.
Pues, ¿qué tenemos que hacer nosotros?
Pues, vamos a empezar por aquí y lo que tenemos que hacer es ir, como he dicho, a la última rama.
Creo que voy a hacer un getfetch de todo.
No sé, a ver si ya hace mucho tiempo que no tengo esto.
Y vamos a ver cuál es la rama.
Es 05, upload images, vale.
Yo creo que esto, checkout 05, a ver si esto hace un autocompid.
Perfecto.
Pues, hago el checkout y ya me he traído los cambios.
Aquí puedes ver ya que tengo todos los archivos y todo esto, ¿vale?
Pues, vamos a levantarle el entorno de desarrollo, como siempre.
Y así, pues, arrancamos y empezamos ya.
Ah, me dice que el puerto este ya está usado.
Claro, es que a lo mejor tengo por aquí, un momentito, tengo que tener por aquí algo levantado de otro proyecto que estaría haciendo.
A ver ahora.
Ahora parece que sí.
Vale, ahora sí.
Ahora está iniciando el entorno de desarrollo.
Voy a mover mi camarita para abajo a la izquierda, para que no moleste.
Voy a hacer esto un poquito aquí para saber dónde está mi cámara.
Vale, pues, ya compilado.
Pues, vamos a ir a localhost 3000.
Y aquí tendremos nuestro proyecto.
Vale.
Muy bien.
Ahora está haciendo el loading.
Ahora sí, estamos bien logados.
Aquí dejamos lo de las imágenes de la semana pasada.
Quedo pendiente hacer un par de mejoras en las imágenes.
Y he pensado en hacerlo en un live entre semanas, para no hacerlo en un viernes y tomar mucho tiempo.
Entonces, estate atento, atenta, suscríbete y te pones la campanita para que te avise.
Porque a lo mejor lo hago un martes o un miércoles, pero creo que es interesante hacerlo.
Pero no quería que tomase más tiempo de un viernes, ¿vale?
Entonces, lo que me gustaría primero en esta clase es que al hacer clic en un tuit, pues, podamos entrar.
En el caso de Twitter, y esto es curioso, ¿no?
Pero en el caso de Twitter tiene un sistema un poco raro, ¿no?
Que tú haces un hover de todo.
Aquí lo puedes ver, ¿no?
Que si haces un hover, cambia el color de fondo.
Y al darle clic, pues, entras.
Pero donde está realmente el enlace, porque, claro, tiene un montón de elementos que son clicables.
Y no puedes tener un elemento clicable dentro de otro clicable.
Puedes tenerlo, pero está mal, ¿vale?
No podrías tener dentro de un anchor un botón.
No está bien, ¿vale?
Entonces, aquí, ¿qué pasa?
Que tenéis botones.
Entonces, el cómo funciona esto es raro, ¿no?
O sea, no tiene sentido que en este caso podamos tener el anchor y dentro de los botones y clicar.
No.
Lo que hace es que el anchor lo tiene aquí.
Solo lo tiene aquí.
Lo tiene en el tiempo, ¿vale?
De hecho, si miramos aquí y lo inspeccionamos, pues, seguramente aparecerá ahí en el tiempo.
Y me parece que, mira, aquí está.
El anchor con el href, ¿vale?
Entonces, lo que vamos a hacer, vamos a empezar por aquí.
Vamos a hacer que nuestro anchor también esté en el tiempo y luego lo arreglaremos para que todo sea clicable, como hacen ellos.
Pero, bueno, vamos a dejar, le damos aquí y aquí tendríamos un poco la url.
Ya vemos que aquí está el nombre del usuario, status y la id.
Pues, este un poco es la ruta que vamos a seguir, pero vamos a obviar el nombre de usuario.
Para crear una nueva ruta, si has estado siguiendo las clases, ya sabrás que dentro de páginas, en las páginas estas que tenemos aquí, tenemos ya directamente las rutas que podemos crear.
La de API es un poquito especial porque nos crea como unos endpoints que vamos a poder ir creando, ¿vale?
La API es especial, pero luego el compose sí que machea con la ruta que estaríamos haciendo, ¿no?
Los archivos y los directorios físicos, de alguna forma, se traducen a los paths a los que va la página.
Por ejemplo, el barra home y tenemos el index.
Aquí, este barra home que tenemos aquí, ¿no?
Pues, es esta página.
Este index que vemos aquí, pues, sería el que tengamos acá, ¿vale?
Entonces, ¿cómo creamos esta nueva página de status y cómo hacemos que sea dinámico?
Porque, claro, hasta ahora hemos dicho que la estructura de archivos, pues, se tiene que traducir.
Pero, ¿cómo hacemos realmente que una parte de esa estructura sea dinámica?
Pues, lo que tenemos que hacer primero es crear status, barra, y aquí podemos crear una carpeta que es especial, que va entre corchetes,
para indicarle que ese segmento de la ruta es dinámica.
Así que hacemos así, corchetes y cerramos corchetes.
ID va a ser el nombre del parámetro cuando lo capturemos dentro de la página.
Y ahora hacemos barra index.js.
De esta forma, lo que nos ha creado es una carpeta status, dentro de status, otra carpeta que es corchetes ID,
y dentro el fichero index.js.
Ahora, esto, vamos a ver cómo esto funciona.
Esto sería la página del debit page.
Como props, por ahora, vamos a hacer que no tenga ninguna.
Y vamos a poner aquí que esto es un work in progress.
Guardamos los cambios.
Y lo que vamos a hacer es ir aquí a status, 1, 2, 3.
¿Vale?
Y aquí tenemos el whip.
Así que, esta página ya hemos hecho que exista.
Aquí esto lo podemos cambiar y vamos a ver que esto funciona correctamente, ¿no?
Y ya está.
Ahora, lo que estamos viendo es que el layout ha dejado de funcionar.
O sea, no se está viendo la página bien integrada.
Este problema no es un problema, es una feature, no es un bug, es una feature.
Lo podríamos arreglar fácilmente si utilizásemos el applyout, ¿no?
Lo típico de esto de que aquí podemos hacer applyout.
Importamos ahí el applyout.
Ay, no me la he importado automáticamente.
Ya, pa, chao.
A ver, a ver.
Aquí.
Autoimport.
Ahora sí.
¿Vale?
Y entonces, todo esto que tenemos aquí lo meteríamos aquí dentro y ya debería funcionar
y verse con todo el layout y todo esto.
Perfecto.
Pero, como dijimos, esto lo íbamos a tener que crear en todas las páginas
porque tenemos clarísimo que este applyout va a estar en todas las páginas igual, ¿vale?
Entonces, lo vamos a arreglar ahora mismo, pero antes de eso, me gustaría explicarte
otra forma en la que puedes crear esta ruta dinámica y a lo mejor la prefieres
y, de hecho, la vamos a hacer así.
Aparte de tener esta estructura de status, luego la carpeta id que decimos que es dinámica
y dentro el index.js, también podrías crear directamente, vamos a, me voy a copiar el contenido
para no liarla, pero lo que podríamos hacer, vamos a eliminarlo, pum, y esto también.
Bueno, esta carpeta de status ya nos sirve.
Dentro de status podríamos crear directamente el fichero id.js.
De la misma forma que hemos creado en la carpeta corchetes id, también podríamos hacerlo
creando directamente el archivo.
Así que puede ser el que tú prefieras.
Depende un poco, yo creo, en el caso de que en esa ruta tengas que tener más archivos dentro
que no quieres que sean rutas, porque si no quieres que sean rutas, pues entonces mejor
utilizar la carpeta.
Pero si no te importa y tienes clarísimo que aquí vas a crear más ficheros, o sea, porque
esto, claro, ¿qué pasa?
Que aquí puedes crear otro fichero.
Podríamos poner, por ejemplo, papa.js y aquí pues vamos a poner que este es papa, ¿vale?
Claro, esto es un poco raro y te voy a explicar por qué.
Porque ahora lo que tenemos aquí es que dentro de status tenemos dos rutas, una que
es dinámica, que hemos dicho que es slide, y otra que es estática, que sería papa.
O sea, vamos a intentar que aquí en papa entre.
Pero aquí podemos tener el papa, porque es justamente el que machea con la parte estática
y luego tendríamos el 1, 2, 3, porque es el otro que hemos hecho que sea dinámico.
Y como no machea con el estático, pues sí que funciona.
Esta podría ser una de las formas.
Así es como lo vamos a dejar, porque creo que en este caso creo que lo teníamos de otra
forma en otro sitio.
Bueno, no sé.
Creo que este está bien.
Este me gusta, así que vamos a utilizar este, ¿vale?
Hay otras formas de machear rutas.
Por ejemplo, se pueden hacer, pues, ¿cómo era esto?
Se puede hacer que mache no solo el segmento, porque claro, en este caso tenemos un segmento
en concreto, ¿no?
1, 2, 3, sino que podemos hacer también el 1, 2, 3, barra lo que sea, barra 1, 2, 3, ¿no?
Entonces, ahora podemos ver que esto no está macheando.
Entonces, ¿qué podríamos hacer aquí?
Pues crear dentro de status una carpeta que sea id, luego lo que sea.
Bueno, esto sería static, por ejemplo, ¿vale?
Y luego machear también con el 1, 2, 3.
Pero también hay otra forma que es utilizando corchetes con aquí lo que pondríamos es el
punto, punto, punto.
Y lo que le estaremos diciendo es captura cualquier parte dinámica a partir de aquí.
Eso podría ser otra forma, pero en nuestro caso no lo vamos a ver.
Solo te lo explico para que sepas que en el caso de que lo necesites también tienes
esta posibilidad.
Nosotros no lo vamos a ver porque no lo necesitamos, pero en tu caso de que lo necesites porque
estés haciendo un blog y quieras tener la categoría y la idea y tal, normalmente yo te recomendaría
que no tuvieses la necesidad de hacer esto porque machea demasiado amplio, ¿vale?
¿Qué pasa?
A partir de aquí empieza a machear todos los elementos dinámicos.
Entonces es un poquito más molesto.
Es mejor que tengas bien la estructura y lo tengas claro, pero a veces puede ser que lo
necesites porque sepas que esto existe.
Por ahora lo dejamos así, tenemos el static status, 1, 2, 3, lo podemos cambiar, hemos
dicho, lo tenemos así, he creado esto.
Lo que si os parece, creamos rápidamente el app layout y por si no habías visto en la
primera clase cómo crear como un envoltorio de nuestra aplicación en NextDS, pues así
lo vas a ver.
¿Cómo lo hacemos?
Hemos dicho que en Pages hay algunas cositas que son un poquito especiales.
Una de ellas es la carpeta API, pero hay más.
Hay otra que es un archivo especial que empieza con underscore, que es app.js.
El app.js, este archivo, cuando lo creamos, lo que sirve es de envoltorio de toda nuestra
app.
Este no es el único especial que hay, de hecho hay otro que es el de document, que
este es un poquito más agresivo incluso, ¿no?
Porque es el envoltorio de toda, no la aplicación que se renderiza, sino del documento incluso
que envuelve toda nuestra aplicación.
O sea, tendríamos todo el HTML de fuera de la aplicación.
Entonces, el document hay que evitarlo siempre que se pueda.
Hay veces que si estás utilizando themes y cosas así, pues te obliga de alguna forma,
lo cual a mí no me gusta.
Pero el mejor que podemos utilizar ahora para asegurarnos que vamos a utilizar el app layout
en todas nuestras páginas va a ser este de app, ¿vale?
Así que vamos a crear simplemente un componente.
El tema de este componente, que vamos a llamarle app, es que recibe, esto es siempre así,
este archivo, como digo, es especial.
Así que lo que pasa que siempre es que recibe dos props.
Uno que es el component y otro son los page props, que son las páginas que va a recibir las props
que va a recibir la página.
Y ahora, con este component, lo que podemos hacer aquí, pues es renderizarlo.
Vamos a quitar esto y vamos a poner component y aquí ya tendríamos los page props.
Esto sería así.
Esto sería muy similar a lo que ya hace la propia aplicación.
O sea, ahora mismo no estaríamos haciendo nada.
Sería como crear un envoltorio que no hace nada.
Pero vamos a aprovechar que tenemos esta posibilidad.
Esto sería el comportamiento por defecto, ¿no?
Voy a renderizar el componente, que es como la página, y le voy a pasar hacia abajo
los props que tiene la página.
Esto sería lo normal.
Pero vamos a aprovechar que tenemos la posibilidad de modificar esto
para añadir el app layout.
Así que vamos a hacer el app layout aquí.
Y lo que vamos a envolver con el app layout va a ser el componente.
Guardamos los cambios y no vamos a ver nada.
No vamos a ver nada porque tenemos que reiniciar el servidor para ver los cambios.
Esto, como digo, es una página especial y, por lo tanto, a la hora de ver estos cambios
hay que reiniciar el servidor de desarrollo, ¿vale?
Así que vamos a hacer un envio en run dev.
Y ahora sí debe utilizar este nuevo archivo app que hemos creado.
Ahora vemos que esto no funciona del todo bien.
Hay un poquito raro, ¿no?
¿Qué pasa?
Que ahora tenemos el app layout dos veces.
Así que vamos a empezar a quitarlo.
Aquí, por ejemplo, ya lo vamos a quitar, fuera.
Y ahora deberíamos ir página por página para quitarlo.
Aquí ya podemos ver que queda bien, pero bueno, si vamos a la home, pues veremos que tampoco está bien.
Esto lo vamos a hacer rápidamente.
Vamos a buscar app layout.
Bueno, ahí se puede ver, ¿no?
Que la home tampoco funciona.
Así que funciona, pero no se ve bien.
Entonces, este componente timeline, a mí es que me parece que esto no lo estamos usando.
Así que fuera.
Este timeline yo creo que lo hicimos en la primera clase para ver algo.
Así que esto lo eliminamos.
Vale, ¿qué más?
¿Qué más?
Vamos a buscar el app layout.
Este sí que lo queremos.
Esta sería la home, por ejemplo.
Así que esto también nos lo podemos cargar.
Fuera.
Quitamos este app layout.
Tampoco lo tenemos en muchos sitios.
El de hacer el compose del tweet, a la hora de crear el tweet, que también lo habíamos hecho en una clase anterior, pues esto también nos lo cargamos.
Fuera.
Podemos quitar este de la línea.
Y en la home, esta page home, pues nada, ya tendríamos el de la home.
Pues no sé cuál es el que he quitado antes.
Si no he quitado el de la home.
Ah, el del loading, claro.
El de el inicio, la página de inicio.
Vale.
Ahora sí.
Pues ya tenemos el app layout en todas nuestras páginas.
Así ya nos podemos olvidar de esto.
Cada vez que creemos una página, como por ejemplo esta del status 1.2.3 que hemos creado, pues ya tendrá este layout que ya le están volviendo a nivel de aplicación.
¿Vale?
Así que será mucho más fácil desarrollar y no estar pendiente de esto constantemente.
Hemos reiniciado el servidor.
Importante.
¿Vale?
Que no haya locuras en el caso de que no veáis los cambios.
Es importante reiniciar el servidor porque este archivo especial no utiliza ningún hot module replacement ni nada.
¿Vale?
Así que ya tenemos esto preparado.
Ya tenemos nuestra página nueva, que por ahora está vacía, para tener los tweets.
Y lo que vamos a querer, como aquí lo que tenemos que mostrar sería el debit o tweet con la ID de la URL.
Esto ya lo tenemos claro.
No sé si lo veis muy chiquitito.
A ver.
Mira, dice Oscar.
¿Por qué los estilos de app layout no los utilizas en app si ese layout lo va a usar toda la app?
Pues, buena pregunta.
Realmente es porque ha sido más sencillo.
O sea, ya lo teníamos así, era más sencillo y ya está.
Podéis, si desde el principio lo hubiéramos hecho así, seguramente hubiéramos puesto los estilos y todo esto,
lo hubiéramos puesto directamente en la app en lugar de utilizar un componente.
Pero en este caso, pues, como ya lo teníamos separado en un componente, pues, bueno, creo que ya estaba bien.
Igualmente, tampoco hace daño tenerlo separado.
Así que, ¿qué más?
Y si queremos que sean varios layouts, habría que entender qué queremos por varios layouts.
O sea, varios layouts, ¿qué quiere decir?
Que por props aparezca un layout u otro.
Si es así, seguramente puede ser que valga la pena dejarlo en la página.
Si los layouts pueden cambiar mucho.
Pero, o lo que te recomendaría es que sí que pongas a nivel de app el layout que tengas claro que siempre es el mismo, ¿no?
Aunque sea el fondo o lo mínimo de tu aplicación, ¿no?
Otra cosa que podrías hacer, al final esos page props, una cosa que tiene buena este app,
es que puedes también reescribir el GetInitial props.
Podrías ver de estos page props lo que le llega.
Y dependiendo de esas props, pues, utilizar un layout u otro.
Esa podría ser una cosa.
Ahí tienes opciones.
Yo intentaría no liarla mucho porque el problema que tienes aquí es que estás tocando algo que ya no está tan dentro de tu aplicación.
Así que podrías tener un layout que fuese lo más simple o más reusable o lo...
Siempre todas las páginas tienen que tener un layout que es muy básico, que es lo que envuelve la aplicación.
Eso suele pasar y suele ser así.
Pero si es que a veces, por ejemplo, pues sale un top bar o no sale un top bar, pues eso es que a lo mejor ya lo puedes tener a nivel de página.
O, en este caso, mirar las props y dependiendo de las props, utilizar uno u otro.
Y con esa pequeña lógica, pues, ya podrías cambiar lo que quieras.
De hecho, aquí lo pone Miguel.
Dice, dentro de la puedes hacer una lógica para elegir el layout.
Lo podrías hacer.
Lo que, bueno, yo te diría, ten cuidado.
Tampoco te...
Quiero decir, si tienes dos layouts igual tiene sentido.
Pero si tienes 15, igual es que tienes 15, es mejor bajarlo a las páginas, ¿vale?
O sea, por eso siempre estas cosas dependen.
Depende.
Vale.
¿Qué más?
¿Qué más?
Me he acordado del midu truco, hombre.
Por supuesto.
Saludos, al parecer llegué tarde.
No llegaste tarde.
Llegaste justo a tiempo.
Luego, no he cambiado lo del date, ¿cierto?
No he cambiado lo del date.
Decía por aquí Miguel, sí, es time, ¿cierto?
Que os lo he comentado.
Pues esto es el...
Ay.
De hecho, ahora que lo veo, aquí no tengo los cambios.
No sé por qué.
Ay, ay, ay.
De hecho, a ver.
Habíamos hecho un...
Ahora.
Ahora sí que me los he traído.
No, habíamos hecho el merch del APR de Miguel Ángel y no estaban aquí los cambios.
Vale.
Pues el date este, vamos a...
Que habíamos puesto esto ahora...
Uy.
Ponemos aquí time.
No sé si se ve pequeña, se ve bien la letra.
Me comentáis, ¿vale?
Por el chat me decís algo.
Vale.
Pues a ver si este time ahora funciona.
Ay, ¿qué he hecho aquí?
Como he bajado...
Ya.
Levanto el entorno de desarrollo otra vez.
Vale.
Tenemos el time.
Le ponemos el...
Por ahora le ponemos el title.
Porque el date time tiene que tener un formato especial.
Y creo que no estamos teniendo el formato especial.
Pero bueno, no pasa nada.
A ver.
Pues eso.
Vale.
Ahí se puede ver, ¿no?
Que sí que sale como el día que fue y todo esto.
No se ve muy grande.
Pero bueno, lo importante es que ya está.
Creo que abajo también teníamos los estilos.
Pues aquí también tenemos que poner time para que se queden los estilos.
Voy a leeros.
Así que comentadme lo que queráis por el chat.
¿Vale?
Y que ahora empezaremos con el Firebase.
Además he visto ahí que me habéis dejado un par de superchats.
Oman Ferrer.
Supersticker.
¿Cien soles argentinos?
Creo que eran los ARS.
Creo que era eso.
Muchísimas gracias, Oman.
Te lo agradezco un montón.
Esperemos con ansias sorteos del libro, dice Julio.
Bueno, primero lo tengo que escribir, ¿eh?
Y muchas gracias por interesarte.
¿Qué ganas del libro?
Dice Luis.
Pues también lo que tengo que escribir.
Sí, lo tengo que terminar.
Es muchísimo trabajo.
¿Se hará algún filtro usando Firestore?
Buscar por texto que contiene es un poco raro, ¿no?
Sí, es un poco raro.
Y sí, vamos a intentar crear.
Lo estoy mirando, ¿vale?
Lo estoy mirando.
A ver cómo podemos utilizar algunas cositas más de Firestore.
Lo tengo en cuenta.
Alan Matkorsky.
También 100 ARS.
Muy bueno el curso.
¿Vamos a ver seguridad sobre Firebase?
Sí, lo vamos a ver en una clase.
Lo que vamos a verlo de golpe.
Porque si no, lo íbamos a ver poco a poco.
Como, por ejemplo, validar que usuarios no creen tweets en nombre de otro, que esté autentificado.
Sí.
Lo comentamos en todas las clases.
Hemos ido comentando esto, pero por ahora no lo hemos hecho.
En una clase en concreto vamos a ver solo temas de seguridad de Firebase.
¿Vale?
Vamos a ver las reglas.
Las vamos a revisar.
Y vamos a ver en cada una de ellas qué es lo que tiene sentido.
Por ejemplo, el Firebase Storage al menos sí que hicimos que estuviese autentificado.
Pero como dices, ahora los tweets los podría crear en nombre de otro un usuario.
Así que vamos a intentar hacerlo también.
Lo veremos en una clase y lo vamos a poner en un solo sitio.
Porque si no, se iba a quedar un poquito...
Sergiedo.
¿Cómo harías para hibridar y migrar progresivamente...
Y muchas gracias por el superchat de 5 euros.
Muchísimas gracias, Sergiedo.
¿Cómo harías para hibridar y migrar progresivamente una app con Express.js?
Todo server site hacia Next.js.
¿Se puede integrar con Express.js?
Buah, Sergiedo.
Esto me daría para una clase...
No, una clase.
Bueno, o sea, primero yo tendría que aprender muchísimo.
Tendría que aprender muchísimo porque es complejo.
De hecho, es uno de los objetivos que mi empresa a veces se ha mirado y se ha pensado.
Y me da la sensación...
Depende mucho, ¿no?
Pero no pueden...
Digamos que no pueden coexistir a la vez.
Entonces, una de las posibilidades que se me ocurre
fácilmente sería que tener un proxy que dependiendo de la ruta fuese a la versión de Express
o a la versión de Next.js, ¿vale?
Porque no puedes tener...
O sea, son dos servidores distintos.
No pueden coexistir.
Eso por un lado.
Lo que...
Yo creo que eso sería lo más fácil progresivamente.
Es decir, esta ruta está en Next.js, esta ruta está en Express.
Si vas de esta ruta a esta ruta, cambias de servidor.
Pero ya está.
Entonces, no sería SPA en ese momento, pero lo podrías hacer progresivamente.
Entonces, dice, ¿se puede integrar con Express.js?
No se puede...
Claro, podrías hacer que una de las rutas de Express.js o todas las rutas que tú quieras
de Express.js, al final la sirva el servidor de Next.js.
Eso sí que lo podrías hacer.
Eso te podría funcionar.
Pero la verdad es que es complejo.
Aunque sean tecnologías que es Node.js y tal, claro, al final Next.js tiene un servidor
propio, funciona de su forma, con sus maneras y, claro, yo creo que lo mejor sería para
hacerlo progresivo eso.
Dividir como la aplicación en rutas y ir migrando poco a poco.
Lo bueno de esto es que el usuario, pese a perder la funcionalidad de SPA, a veces no
debería notar mucho cambio.
Debería ser bastante simples para el usuario, ¿vale?
Entonces, mira, por aquí Nicolás dice, ¿se puede crear Custom Server pero estarías
perdiendo cosas geniales en Next?
Claro, podéis crear el Custom Server, pero es que es muy complicado.
Entonces, ya no dejarías de utilizar toda la parte de Express.
Tendrías que lo que tienes en Express, migrarlo dentro de Next.js, utilizar el Custom Server,
ver cómo metes ahí, como sea que estés haciendo ahora la hidratación, lo podrías hacer, pero
habría que ver cómo de complicado has hecho tu Express.js y su Server Site, qué es lo que estás
utilizando, si estás utilizando Redax, si estás utilizando... Es interesante, la verdad es que es un
problema interesante, pero tendríamos, o sea, se tendría que ver realmente lo que hay ahí, lo complicado
que es. Yo tiraría así sin saber exactamente la dificultad. Claro, es que como dices que tiene
Server Site, es que seguro que tiene ahí métodos de hidratación y tal. Si no, claro, se podría hacer
lo de Custom Server, pero depende un poco, depende un poco de... Vale. ¿Qué más, qué más? Pues creo que sí,
que hay ejemplos, es mejor construir una aplicación de formularios con unos 30 campos con Next o con una
aplicación en el servidor. Buah, Luis, pues depende. Una aplicación de formularios con unos
30 campos, con Next o con una aplicación en el servidor. Depende de la interacción que tenga
el formulario en sí. Seguramente, si necesitas validación, si necesitas que cuando escriba el
usuario pasen cosas, eso no lo vas a poder hacer en una aplicación en el servidor y vas a necesitar
React, ya no tanto Next.js, sino React o cualquier otro framework que te permita fácilmente hacer
de esa interacción. Pues hacerlo con JavaScript Vanilla, pero la verdad es que formularios
y cosas así, justamente para formularios se creó React en Facebook, que lo utilizaron
en la sección de Facebook Ads. Así que creo que es un buen caso de uso. En la parte del
servidor, todavía tienes que tener validaciones y tienes que tener código. O sea, vas a necesitar
las dos cosas. Una cosa no te va a quitar la otra. ¿Vale? React Native o SPA con React.
A ver, React Native para aplicaciones nativas con iOS y Android y SPA con React cuando es
la web, claramente. ¿Que puedas utilizar una SPA con React y crear una aplicación? Sí,
pero hombre, React Native de verdad es que te acerca a la sensación nativa. Estás haciendo
una aplicación nativa. Yo intentaría utilizar React Native, siempre que pueda, desde luego.
¿Pero si en Express está corriendo una API REST, ¿no se podría consumir directamente
en Next.js? Sí, eso no hay ningún problema. Pero por lo que entiendo de la pregunta, no es
tanto consumir endpoints que tienes en un Express, sino lo que pasa es que Sergiedo ya tiene una
aplicación de React dentro de ese Express donde está creando el server-side rendering. Y ahora lo
que quiere es migrarlo a Next.js. Entonces habría que ver exactamente cómo está construido. Al final
necesita algo muy parecido a Next.js. Entonces tiene que tener ahí, no parecido, pero necesita
alguna forma en getting shell props y cosas así. Así que si son endpoints de APIs, las puede
consumir sin ningún problema. Eso está clarísimo. Pero me da que no van por ahí
los tiros. Hilo Mim dice, ¿cómo te das tiempo para aprender sobre tantas
tecnologías y herramientas? Pues vivo de esto. O sea, es mi trabajo día a día, trabajo
de esto, así que tengo que hacer esto porque tengo que estar al día, si no, me quedo atrás.
Y bueno, me gusta mucho el frontend, voy practicando y tal. Vale, Sergiedo dice, no, no tengo
React en el server. Es una regular web app. Ah, bueno, vale. Pensaba que era que tenías
un Express.js con, vale. Tienes Express.js con todo server-side. Pues nada, pues es lo
que yo haría la solución que comentaba antes. Tienes el Express.js con tus rutas, que tienes
server-side. Tienes Next.js y vas migrando rutas. Por ejemplo, la home. Tienes un proxy
y dices, ahora cuando es la home, en lugar de ir al express, vas al de Next.js. ¿Y qué
pasa? Que cuando el Next.js tenga una ruta que, por lo que sea, todavía no la tenga, por
ejemplo, la búsqueda, pues cuando esa ruta vaya al proxy, dirá, ah, tú tienes que ir
a Express. Yo eso es lo que haría. Iría ruta a ruta e iría haciendo eso. Tendría los
dos servidores levantados y dependiendo de la ruta, pues iría un servidor u otro. Pero
al final tienes que tener los dos. Entonces, por lo que comentas, sí que se podría. Iría
cambiando módulos que son regular web a SPA SSR. Sí. Yo lo haría más por rutas que
por módulos. Es que depende tanto la aplicación. Porque si me dices, no tengo nada de React,
pues igual haría widgets de una ruta, por ejemplo, la home. Pues un trozo, cosas así,
¿sabes? Entonces, las cosas no son blanco y negro, ¿no? Si tienes una página muy complicada,
la home, por ejemplo, y no tienes nada de React, en lugar de empezar con Next.js, pues a lo mejor
lo que puedes hacer es crear un widget dentro de la página que tienes ahora que cargue React
y que una parte de la página sean componentes de React. Poco a poco lo vas haciendo grande
hasta que llegue un momento que es tan grande que lo que tiene sentido es que toda la página
sea ya de React. Entonces, puedas utilizar Next.js para eso. Y eso sí que sería progresivo
y creo que sería, a lo mejor, el mejor tema. ¿Qué más? Siempre que se toca el tema
de rehidratación se pone la cosa tensa. Lo veremos en el futuro. La verdad es que lo vamos
a ver hoy. La rehidratación la vamos a ver hoy y la vamos a ver hoy. Si la rehidratación
como tal... A ver, otra cosa es hacer tú desde cero la rehidratación, que también lo podemos
hacer en un ejemplo algún día para que lo veamos. Pero hoy lo vamos a ver. Vamos a ver
cómo funciona la rehidratación porque la hace Next.js cuando haces el server site. Así
que lo veremos. Vale, terminamos con Brian, que dice React Native o Progressive App con React.
A ver, de nuevo, si es web, Progressive App con React. Es que React Native se puede llegar
a utilizar en web. Se puede. Hay algunos inventos como React Native Web y tal, pero no.
Si hablamos para la web, React. ¿Vale? React con Progressive Web App. Si hablamos para
aplicaciones nativas, React Native. Ya está. React Native se puede utilizar en la web y se puede
utilizar incluso para hacer aplicaciones, pero no está pensado tanto para la web. Y para
la web está mejor pensado React. Así que, si es para la web, React. Si es una aplicación
nativa, si es una aplicación para Windows y Mac, que es de Microsoft, que tiene el
binding y que es súper interesante, pues ahí lo tendrías, ¿vale? Con React Native.
Vale, pues este ha sido un poco el repaso. Vamos a darle cañitas, que luego se me echa
el tiempo, que ya llevamos 45 minutos. Madre mía. Vale. Entonces, lo que vamos a hacer
es, primero vamos a ir a Firebase. A ver si entra, a ver dónde entra esto. Firebase. Esto
tendríamos que entrar en la consola porque vamos a necesitar lo que son todos los temas
de la configuración. Este, Depter. Este es nuestro proyecto. La configuración para hacer
el Firebase Admin. Aquí, en la configuración, configuración del proyecto, tenemos cuentas de
servicio. Me gusta cuentas de servicio, más que el otro nombre de Firebase Admin. Cuentas
de servicio. Básicamente, lo que te permite es utilizar Firebase desde el servidor, no tanto
desde el cliente, sino que puedes utilizarlo de forma, como si fuese en modo administración,
claro, es que te he sentido el nombre, desde un servidor, no desde el cliente directamente.
Y aquí tendríamos un poquito nuestro snippet de código que tendríamos que utilizar.
Aquí ya se ve que pone aquí este required. Aquí tiene un JSON que hay que generarlo,
que lo tenemos en este botón y entonces nos lo genera, lo descargamos y tenemos que
hacer un required de esto. Pero esto lo que tiene es que tiene tus claves privadas.
Este sí, este sí, que no tiene que ser público.
¿Vale? Ya vimos que en Firebase tienes, pues, no sé si lo puedo enseñar sin liarnos mucho,
pero tienes como el SDK aquí, un montón de cosas que son para el cliente y mucha gente
dice, wow, pero esto sale y está muy expuesto. Pero eso es normal porque eso está en el
cliente y es imposible que puedas hacer nada para ocultarlo, que es todo esto.
Todas estas API keys y todo esto. Lo que tenemos que hacer son las reglas que comentábamos
antes de si es este dominio, si el usuario está autentificado, si es esto. Unas reglas
de permisos para evitar que una persona que tenga estos acceso a estas API keys, a esta configuración
pueda hacer ciertas cosas. Pero en este caso del Firebase admin, este, este JSON que se
genera, este sí, que es importante que no sea público. No lo subáis al repositorio.
¿Vale? Así que vamos a generar la clave y luego ahora haré fuera de cámaras y eso,
esto también, para que no, para que no la veáis. Pero bueno, ahora hacemos esto.
Entonces, este código que tenemos por aquí, me lo voy a copiar y vamos a ir aquí a nuestro
proyecto otra vez y aquí en Firebase, vamos a crear el admin.js. Y aquí, pues nada, copiamos
el código que acabamos de tomar de la página de Firebase y este require.py, pues este es el archivo
que nos faltaría como tal. Así que, por ahora vamos a poner aquí, service, vamos a poner
Firebase keys, ¿vale? Y este es el nombre que le voy a poner al otro archivo, que es
Firebase keys, ¿vale? Ahora voy a ver si soy capaz de mover el archivo, porque si lo copio
en Visual Studio Code va a aparecer ahí. Y yo me fío de vosotros, pero no me fío de alguno.
No me fío de que venga alguien de la competencia y nos fastidie el proyecto.
Entonces, nada, lo hago un momentito. Buscamos aquí el curso, a ver. Ah, Depter, Depter, Firebase.
Lo vamos a poner por ahora aquí. A ver. Que al final, seguro, seguro que se me escapa en algún
momento y lo veo, ¿eh? Pero bueno, por ahora vamos a intentar evitarlo. A ver si soy capaz.
Entonces, ya tenemos esto, ¿no? Este require lo que hace es importar este archivo que tiene
como todas las claves de Firebase. Todas las claves y tenemos que tener cuidado de que no
se nos cuelde, ¿vale? Entonces, ahora que tenemos, estamos, aquí lo que hacemos es un
import de la dependencia Firebase admin y esta dependencia la tenemos que instalar. Así
que voy a crear aquí una nueva terminal y ya en mi caso, acuérdate, yo tengo yarn, pero
quizás tú tienes otra cosa que es npm. Pues haces un yarn add o si estás utilizando
npm, haces un npm install y aquí hacemos Firebase admin, ¿vale? Lo añadimos. Esto, nada,
tarda unos segundos y mientras, pues vamos a seguir revisando. Este service account,
esto son todas las keys. Esto es un objeto que tiene un montón de keys. Además, tiene
keys que están encriptadas y cosas así. Este es el archivo que hay que descargarse aquí
en el generar una nueva clave privada, ¿vale? Y que si por lo que sea se te
escapa o lo que sea, tienes que generar otra. Entonces, si le das otra vez a
generar, la anterior ya no te sirve. Se genera una nueva clave y la anterior deja
de funcionar. Que ya está bien pensado, claro, por si se te cuela. ¿Vale? Entonces, aquí lo que
hacemos con admin es inicializar la aplicación. Esto es muy parecido a lo que
hacíamos aquí en el cliente, ¿no? Que era inicializar la aplicación con la
configuración de Firebase. Pues aquí es muy parecido. Le pasamos los
credenciales y la URL de nuestra base de datos, la que vamos a funcionar de
Firestore. Y este certificado es el que va a utilizar. Ahora, ¿qué servicio es el
que vamos a inicializar con todo esto? Porque, vale, ahora hemos inicializado
como toda la cuenta de servicio. Pero queremos una cosa en concreto, que es lo
de Firestore. Así que lo que tenemos que hacer ahora, que tenemos esto, es hacer
admin.firestore. Y esto nos va a devolver, nos va a exportar hacia afuera
justamente solo el servicio de Firestore. Así que con esto ya lo tendríamos.
Vamos a, yo creo que con esto ya está. Veremos si no nos da problemas. Como ya nos
dio un día, ¿no? Con el live, el hot module replacement. Yo creo que no debería.
Vale, esto ha terminado. Ya cierro aquí la terminal. Y entonces, ahora que tengo esto,
ya podemos crear un endpoint que utilice este Firebase Admin. Así que aquí en Pages
API, vamos a crear una nueva API. Vale, teníamos aquí una Statuses, Home, Timeline. Yo creo
que esto también lo hicimos en la primera clase para tener como contenido vacío que
realmente no servía para nada. Así que esto como tal lo podríamos eliminar, pero bueno,
vamos a dejarlo ahí por ahora. Vamos a crear una nueva ruta dentro de API que sea
debits, a ver si sale, sí, debits, barra, y aquí también necesitamos tener rutas
dinámicas. Y esto es súper importante porque en la API también podemos tener
rutas dinámicas, ¿vale? De la misma forma que podemos tener las páginas, como la API
está dentro de páginas, también podemos hacer rutas dinámicas. Así que hacemos esto.
De esta forma tendremos algo así, api, barra debits, y aquí pues la URL del debit o del
tuit que queramos recuperar, ¿vale? Entonces, aquí esto tiene que devolver, esto tiene que
devolver una función que, bueno, es asíncrona, pero puedes hacer que sea asíncrona, que recibe
dos parámetros. La request de cuando se le llama, ¿no? La petición que se le está haciendo
y la response. La response que es para devolver lo que queramos, ¿no? Para responder que este
endpoint devuelva algo. Entonces, lo que queremos hacer aquí es conectarnos primero, vamos a
importar Firestore, Firestore, ¿vale? Vamos a importar Firestore y esto lo hacemos de
Firebase, barra admin. Este Firestore que tenemos aquí es justamente el que estamos exportando
aquí, ¿vale? Así que ya tengo la conexión al servicio porque lo hemos hecho en Firebase
admin, ¿vale? Cuando lo hemos inicializado y todo esto. Y aquí ya, pues lo que podemos
hacer es, uno, recuperar la idea, porque si tenemos esta URL, api, barra debits, barra la
ID que queremos recuperar. ¿De dónde recuperamos esta información? Pues la tenemos en Query,
dentro de la request. Si queréis, puedo poner aquí request y response para que no haya
líos, ¿vale? Y dentro de la query ya tenemos todos los segmentos que ha hecho match en la
URL. En este caso, como es la ID, que es el último segmento después de la barra debits,
pues aquí la ID la sacamos de Query. Ahora, ¿cómo podemos utilizar esta ID? Pues tenemos que
buscar este documento en Firestore. Para ello, utilizamos Firestore, luego vamos a la colección
donde queremos utilizar, donde queremos buscar el documento en concreto. Creo que era debits,
si no, lo podemos mirar rápidamente. Pero bueno, yo voy a dar por hecho que es debits. Luego
le decimos el documento en concreto que queremos recuperar, así que le pasamos la ID, que es la
ID que teníamos en el... Ay, cuando está chiquitito. Que no sé por qué he cerrado la página
antes, yo también. Me ha podido el ansia, si ya ves tú. Será por el tabs, si luego tenemos
un millón de tabs. Bueno, yo confío bastante que queda debits, es que es lo único que me
suena. Así que, Firestore, Cloud Firestore. Ahí vamos a ver la colección y todos los
documentos que tenemos. Vale, aquí está el nombre, vale, debits, ¿vale? Perfecto. Vamos
a volver esto por aquí. Vale, una vez que tenemos el documento, lo que necesitamos es decirle,
vale, pues quiero que lo recuperes, que hagas un get y ya nos devuelve aquí una promesa
con el documento que tiene la información que nosotros necesitamos. Ahora, este documento,
esto es exactamente lo mismo que en el cliente. Si mirásemos este doc, este documento que
nos está devolviendo la Firebase, o Firestore en este caso, este documento es un objeto complejo
de Firestore donde tiene un montón de información. Es como un cursor en realidad. No es como,
no es la información, esto no es un objeto que nosotros podamos consumir. Para ello, lo
que tenemos que hacer en realidad es llamar a un método en concreto para extraer la
información. Así que podemos hacer aquí data, doc.data, y este es el método que nos
va a recuperar la información de este documento. Y con esto ya podríamos hacer un
response.json y devolvemos la data, ¿vale? Con esto ya tendríamos nuestro endpoint.
Bien, vamos a probarlo a ver cómo funciona, si ha funcionado bien esto o no ha funcionado
bien. Vamos a ver. Tenemos esto por aquí. Voy a darle que... Bueno, no. Es que, claro,
espera, espera. ¿Cómo miramos este aquí? Vamos a recuperar un documento de estos. Por ejemplo,
este, ¿no? Esto tiene... Esto de esta idea... Vale. Estoy recuperando una idea que sepa que
existe porque si no, no va a funcionar por ahora. Luego ya haremos que funcione también
con eso, ¿eh? Entonces, le ponemos esa idea y ya tenemos la información que hemos extraído
directamente de la base de datos. Pero esto es un endpoint que hemos creado nosotros.
No estamos en el cliente y hemos sido capaces de extraer esta información. Y esto está bien
porque así no necesitamos de ninguna forma el tener que pasar por el cliente y esta
información pues ya la tenemos en el servidor. Pues esto es por un lado. Ahora, ¿qué pasa?
Si yo aquí pongo, por ejemplo, otra cosa, una idea que no existe, esto ya empieza a dar
problemas, ¿no? Y aquí en la terminal pues puede ver que no le gusta esto, ¿no? Dice,
oye, ¿qué pasa aquí? Que no sé qué, no sé cuánto. Vale. Entonces, el tema aquí es que
no estamos haciendo un catch del error del not found, ¿vale? Porque no lo ha encontrado
y pues tenemos que hacer el catch, ¿no? De qué pasa cuando no existe este documento.
Podríamos hacer un montón de cosas. Yo creo que lo más sensato seguramente es
devolverle que el endpoint se comporte un poco igual que Firebase, ¿no? Es decir, oye,
no funciona, no existe este documento. Así que el estatus de la respuesta es 404 y luego
terminamos la respuesta directamente y ya está. Creo que esto puede tener sentido.
Vamos a ver si esto funciona. A ver si, por ejemplo, aquí le damos otra vez antes.
Vale. Pone internal server error. Vamos a ver si esto es un error porque no le gusta
lo nuestro. Vale. Es que sabía. Vale. Este error que ha salido ahora no tiene nada que ver
con lo que estamos haciendo. Esto es un error que suele ocurrir cuando se inicializa
Firebase más una vez. Aquí podéis ver que la aplicación de Firebase ya existe. Esto es
porque como tiene el hot module replacement este, pues se vuelve un poco loco, ¿vale?
Aquí lo que tenemos que hacer es evitar que se vuelva a reiniciar, que vuelva a crear
este inicializar la aplicación cuando ya la ha inicializado. Por ahora, a ver, podemos
hacer un try que intente esto y el catch no hacer nada. Podríamos llegar a mirar si el
error incluye este mensaje y, bueno, pues dependiendo, ¿no? Porque si es un error que no es
este y es otro, seguramente nos gustaría saber cuál es el error. Pero bueno, por ahora
vamos a dejar así, ¿vale? Vamos a ver si ahora funciona. Vale. Esto ahora
funciona. Ahora aquí funciona. Si quito algunos, vale. Parece que hay un error, pero
esto tiene sentido, ¿eh? Este error es que nos está diciendo localhost no puede, no se
puede encontrar y nos está dando un 404. Pero es el status code que nosotros le hemos
dicho. O sea, tiene sentido. Si aquí en lugar de un 404 ponemos un 400 y aquí
refrescamos, pues vemos que nos dan 400. O sea, lo estamos controlando. Estamos
controlando el error, ¿vale? Esto es lo importante. Vale. Entonces, ya tenemos
esto. Vamos a ver cómo podemos... Ahora ya tenemos el endpoint. Hemos visto más o
menos cómo funciona. Aquí podemos ver que si le pasa una ID que está bien, sí que
funciona, que es importante. Bueno, a ver si soy capaz de copiarlo. Vale. Pero lo que
vamos a hacer, ahora que ya tenemos el endpoint más o menos listo, es poder ir a esa página,
¿no? Porque para utilizar esta API, pues tendremos que utilizarla para algo. Así que
vamos a hacer que sea clicable este tweet. Así vamos a la página y en la página llamaremos
a este endpoint para que ya cerremos el círculo. Así que vamos a añadir esto. ¿Y dónde
vamos a añadir? Hemos dicho que lo vamos a hacer en el time, ¿vale? En este time que tenemos
aquí con el title, vamos a hacer que eso sea lo que tenga el anchor. Lo vamos a hacer
así, pues para que se parezca a Twitter, pero vamos a hacer también que luego podamos
hacer clic en toda la tarjeta y le vamos a poner el hover y todo esto. Entonces, vamos
a hacer esto que tenga un link. Y aquí vamos a ver una cosa muy interesante. Ahora me he
acordado. ¿Por qué? Vale. Tenemos que utilizar link porque es el router que utilizamos
en Next.js. Y este link lo tenemos que importar del link desde next barra router. ¿Vale?
¿Era desde el router? Creo que sí. O era de... A ver, vamos a ver. Esto, lo bueno
que tiene el auto import es que te lo chiva. Import link. Sí, yo creo que era del router.
Vale. Entonces, le tenemos que decir hacia dónde tiene que ir esta ruta, ¿no? Hemos
dicho que tiene que ser status barra lo que sea, ¿no? Vale, pues vamos a poner aquí
status barra y aquí debería ir la id. Y eso es todo lo que tendría que hacer. O sea,
no es muy complicado, ¿no? O sea, realmente tenemos claro que esa es la id de nuestro
tweet y queremos que vaya aquí. Y ya está. Por ahora vamos a hacer esto. Vale, hay algo
ya que no le ha gustado. Check the render method. Está claro que el error, el problema lo tiene
aquí. Pero bueno, puede ser que no le guste esto. Vamos a ver si es que no le gusta esto.
No. No. Otras. Igual es el este, ¿eh? Es que no es... A ver. No, es que es
barra link. ¿Ves? ¿Cómo sabía yo que era barra link? Es que no sé por qué he pensado en
router. Bueno, también tiene sentido que sea router, ¿eh? El import es import link
from next link. Vale. Ya está. Entonces, esto todavía no lo necesitamos, pero bueno,
se lo puedo dejar. Ahora sí. No, pensaba que era el router y no sé por qué. Ahora ya se ve
aquí que tengo el anchor, ¿vale? Entonces, si le doy, pues funcionar funciona. Sí que
me ha llevado a la URL, pero no sé si te has dado cuenta, pero aquí hay un problema,
¿vale? Hay un problema que a mí la verdad es que me puso muy nervioso cuando lo vi. El
caso es que cuando le doy, se recarga toda la página. Fíjate. Pero esto no tiene sentido,
¿verdad? Porque dijimos que cuando utilizamos el link, claro, si yo aquí hubiese puesto un
anchor normal, lo entendería, ¿no? Que diría, vale, puesto un anchor, pues tiene sentido
porque un anchor no sabe cuándo está en una SPA. Pero estoy utilizando el link. ¿Por
qué me está haciendo esto, no? Me está refrescando toda la página. Y esto yo, sinceramente,
con el corazón en la mano, creo que, a ver, lo van a arreglar porque sí que he estado
siguiendo pull requests en GitHub, han hablado de esto y sé que lo van a arreglar porque
no tiene sentido. Y es un poco raro. Y ahora cuando lo explicas a alguien, pues
seguramente dice, man, ¿por qué tienes que hacer eso? Es muy raro. En RealRouter no
tienes que hacer nada de esto. Y es verdad. Pero ¿qué pasa? Para que esto funcione
como una SPA, le tenemos que decir la ruta dinámica a la que tiene que ir y luego le
tenemos que pasar la ruta que realmente tiene que machear con esa ruta dinámica.
Te lo intento explicar otra vez. El href, este que estamos utilizando aquí, no le tenemos
que pasar exactamente la dirección a la que queremos ir. Le tenemos que decir la ruta
a la que queremos ir. ¿Y por ruta qué queremos decir? Pues es la ruta que hemos creado antes.
Le tenemos que decir que el href, en realidad, es status barra corchetes id. Que es la misma
ruta que hemos creado antes. Pero claro, entonces alguien diría, bueno, ¿y cómo sabe,
cómo sabe que esa id es la idea a la que tiene que ir? No tiene mucho sentido.
Porque acepta otra prop que se llama as, no de culo, sino de cómo, que es la que le va
a decir exactamente cómo tiene que viajar a esa ruta dinámica. La dirección a la que
quiero ir es status barra un id dinámico. Y tienes que ir como status barra y la id.
Aquí podríamos ver, aquí yo podría poner 1, 2, 3 y si guardase los cambios y hiciese
un clic, pues aquí puedes ver que ha intentado viajar status 1, 2, 3. Así que yo lo que quiero
aquí, en lugar de 1, 2, 3, es que sea la id a la que quiero ir. ¿Vale? Así que guardo
los cambios, le voy a dar, pam, y ahora sí está viajando a la id que yo quiero. Pero
es, ahora además te puedes fijar que no está recargando la página. Ahora sí que
está funcionando como una SPA. Es como que ahora sí que está detectando que la ruta
a la que quiere ir es una ruta suya, que tiene un segmento dinámico y que tiene que
funcionar así. Cuando no tiene segmentos dinámicos, tu ruta no tienes que hacer esto,
no tendría sentido. Pero cuando tiene segmentos dinámicos, tienes que hacer esto. Tienes
que pasarle el href, que es la ruta a la que tú has creado, a la que se tiene que
dirigir y luego como has, le tienes que pasar realmente cómo se traducen esos
segmentos dinámicos. Y tiene que ser toda la ruta completa. Ya te digo que este
vídeo a lo mejor lo ves dentro de una semana, un mes y esto que te estoy contando
ya no tiene sentido. ¿Vale? Pero ahora mismo esto es así. Un poco para que lo
supáis. Mira, aquí dice Nicolás, dice
creo que leí al
TimnodeCamps que pronto podría dejar de usarse el A solo o el href no más.
Sí, estoy seguro. Es algo que se ha quejado muchísima gente
y yo también leí ese comentario. Estoy seguro que
si no este mes, bueno, este mes le quedan unos días. Estoy seguro que el que
viene en una de las versiones, vamos a ver que esto, ya este href
dejará tener sentido y será así. ¿Vale? Pero hoy en día ten esto en
cuenta que esto es súper importante porque si no te va a refrescar toda la
página. ¿Ok? Entonces, claro, dice y si se le quiere enviar un parámetro
adicional, me dice Esteban. Vale, pues no pasa nada. Al final este href
imaginemos que es otra categoría, por ejemplo. Categoría. Pues aquí pondrías
category. Esto sería así. Ya está. Pero claro, esta ruta tiene que de
alguna forma hacer match con las rutas que tú tengas entre las páginas.
Eso sí. Esto no se está creando al vuelo, sino es la ruta que hemos creado
antes. ¿Vale? No sé si esto ha quedado claro, pero es bastante importante
porque puede dar bastantes problemas. ¿Ok? Aquí voy a poner un class name
porque ya que estamos vamos a estilar un poquito eso. Y como un anchor...
A ver, podríamos hacer el anchor directamente. Lo que pasa es que quizás
después pongamos un anchor. Venga, va. Vamos a utilizar el anchor.
Pero no arrepentirme más tarde. Pero bueno, podemos hacer esto.
Le quitamos el text decoration. Le ponemos un non. Y cuando hacemos hover de esto,
sí que hacemos el text decoration underline. Y vamos a ver esto cómo queda.
Vale, pues ya está. Y ya funciona bien. Eso sería un poco la ruta que tenemos.
Ya tenemos el link y lo tenemos en la fecha. Entonces, antes de pasar a hacer
que todo el artículo sea clicable y cómo lo vamos a hacer, voy a leer los comentarios
del chat. A ver qué me estáis contando. A ver qué me contáis.
¿Qué más? O sea, ¿qué idea sería un folder?
Vale, puede ser un folder o puede ser un archivo. Es lo que he explicado antes.
Aquí puede ser status barra y aquí tenemos el segmento dinámico o puede ser status barra otra carpeta
llamada con barra corchetes id barra index.js. Tiene las dos formas. ¿Ok? O sea que importante.
El id no es un folder. Es una forma de indicar que hay una variable dinámica ahí, dice Cristian.
Bueno, a ver. Claro, ¿eh? Pero lo que estamos comentando es que esto puede funcionar así también.
A ver si se ve, ¿no? Justo encima mío.
Tenéis estas dos formas. Podéis crear la carpeta con el corchetes id, que es indicando
aquí hay un segmento dinámico que tiene el parámetro id y luego lo capturas como id.
O podéis crear directamente el archivo. El que queráis.
Aquí dentro luego vendría el index.js.
Estos son como los dos sabores que podéis hacer esto que hemos visto.
A mí me gusta más el del fichero, pero bueno, depende de cada uno.
Así que, ¿qué más?
Bueno, en sí, ¿qué sería el data fetching? No te preocupes, lean Pérez, que luego lo vemos, ¿vale?
Jason, ¿Firebase es usado en muchas empresas o no?
Pregunto porque he visto ofertas laborales pero no piden saber Firebase.
La verdad es que no. A ver, sí. ¿Qué pasa?
Firebase, hay un nicho de Firebase que son las startups.
Son startups que están empezando y que quieren validar una idea.
Quieren validar una idea, quieren hacer las cosas muy rápido y no quieren tener servidores
o quieren tener el mínimo número de desarrolladores en plantilla.
Por ejemplo, no van a fichar a backends para hacer todo el tema de base de datos.
Quieren empezar rápido. Y como quieren empezar rápido, yo he visto ofertas en las que dice
startup, busca desarrolladores que sepan de Firebase. Pero sobre todo startups, ¿vale?
Porque buscan eso, validar ideas, hacer cosas muy rápido. Y entonces, en lugar de contratar
a desarrolladores que te hagan el backend, que te hagan estas cosas, primero validan la idea
y luego, si funciona bien, pues normalmente se van de Firebase. Se van porque Firebase suele ser
bastante caro. No sé si ha cambiado el precio, pero hace un año o así, digamos que cuando creces
mucho, pica. Que también pica contratar muchos desarrolladores, ¿eh? Pero, bueno, ¿qué es eso?
Que al final, cuando creces, claro, no te se da cuenta. Al principio es gratis. Y también tienes,
cuando estás creciendo un poquito, sí que está bien el precio. Pero llega un momento
que sí que se dispara. Entonces, ahí es donde está el tema, ¿vale?
¿Qué más? Y si la ruta dinámica quisiéramos mandarle search params por qué motivo,
pues le puedes pasar al query string y puedes recuperar el query string y no habría ningún problema.
Lo que no hace falta que, si son query strings, que lo hagas en la ruta. O sea, la ruta son solo
los segmentos del path. Eso sería, ¿vale? Para saber si existe el documento en Firestore,
se puede usar doc.exist. Pues también. En este caso, creo que, o sea, está petando directamente.
Entonces, si ya está haciendo el pete, yo creo que ya está bien. Que si no lo encuentra, en lugar de
primero mirar si existe o no existe, yo creo que está bien. O podríamos incluso, no sé si devuelve el error
y lo podemos mirar. Pero para lo que queremos, con que no pete y le dé un objeto extraño,
yo ya estaría bien. ¿Vale?
¿Cuando uso el link, el comportamiento de Next es una SPA o cuando Next tiene el comportamiento de SPA?
Guau, Luis, ahí me has dejado loco. No entiendo la pregunta. Cuando uso el link, el comportamiento...
A ver, cuando usas link, el comportamiento de Next debe ser una SPA. Pero tiene que ser una URL que esté
dentro del proyecto de Next. Entonces, tiene ese comportamiento de SPA. De hecho, lo estamos viendo
en nuestra aplicación. Ahora, cuando entramos, ahora no se está recargando nada. Cuando le doy aquí,
puedes ver que rápidamente entra y no se recarga la página. Entonces, está funcionando como una SPA.
Solo está el tema este que hemos visto que no funciona exactamente bien cuando tiene rutas dinámicas
y todo esto. ¿Vale? A ver, ¿qué más?
Hola, Midu. Gracias por todo este video. Me ha ayudado mucho. Quería consultarte si nos enseñarás
en tu video a hacer una configuración de archivo en next.config.js.
Pues, vale, lo miraré. Normalmente no soy muy fan porque, a ver, soy fan si son cosas muy concretas.
Pero no suelo ser muy fan de hacer cosas muy grandes, de tocar muchas, muchas, muchas cosas.
Porque normalmente, si tocas mucho el next.config.js, de alguna forma te estás hipotecando hacia el futuro
de cosas que te puede traer el Next.js. Entonces, tienes que tener un poco de cuidado.
En el caso de... Yo es que he visto el next.config.js muy grandes, lleno de configuraciones y cosas muy raras.
¿Vale? Forzando un poco el Next.js haga ciertas cosas.
Por ejemplo, es que no soporta SaaS de una forma en concreto que no sé qué, no sé cuánto.
¡Pum! Pedazo de configuración. Y luego, aquí tienes el soporte a SaaS.
Pero tal y como lo has hecho todo, ya no te funciona.
Entonces, la migración a la nueva versión de Next es un poco complicado.
O sea, hay que tener cuidado. Un gran poder. Conlleva una gran responsabilidad.
Y sobre la pregunta si he probado Fauna. No he probado Fauna.
La conozco, pero no la he probado. Sé que es una base de datos que está en la nube y que hablan que está súper bien.
Así que me gustaría probarlo. Así que no descarto que veamos algo sobre esto.
Vale. Pues vamos a seguir con el tema porque tenemos todavía un montón de cositas de las que queremos hablar.
Así que, article. Queremos hacer que el article también pueda ser clicable.
Así que vamos a hacer aquí, le vamos a poner un clic y vamos a poner aquí... ¡Ay! Que me he puesto aquí. Perdón.
Tenemos el article, ¿no? Y le he puesto aquí un clic y, bueno, vamos a poner handle, article, clic.
No vamos a complicarnos mucho la vida con esto. Al final lo que queremos es básicamente que al clicar el artículo vaya a la ruta.
Ahora tenemos dos opciones que podríamos hacer. Pero bueno, por ahora vamos a ir a lo fácil.
Si luego añadimos botones, seguramente tendremos que revisar un poco esto. ¿Vale? ¿Por qué?
Tenemos que revisar esto porque tengo que hacer que se pare la propagación de eventos para evitar que sea el artículo el que se lleve el evento y todo esto.
Y puede ser que sea interesante. ¿Vale? Voy a añadir el urrouter, the next router, porque necesitamos utilizar el router para hacer la navegación.
Y os quería enseñar esto porque esto... Bueno, esto lo hemos visto ya unas cuantas veces.
Para hacer la navegación programática, ¿no? Imperativa.
Y esto es interesante porque pasa algo similar a lo que hemos visto antes.
Por ejemplo, si aquí ponemos barra status, barra... Y ponemos aquí la id, ¿no? Y hacemos esto. ¿Vale?
Y antes de probarlo, antes de probarlo, voy a añadir aquí unos estilos un poco... ¿Vale? Background... Y ponemos 5... F8... F8...
Y hacemos que el cursor tenga el pointer este. ¿Vale? Y a ver... ¿Vale? Pues ya se nota, ¿no? Que es un poco clicable, tiene el cursor y todo esto.
Entonces, ahora cuando le dé clic, debería entrar en este método y debería navegar a la página del tweet.
Le voy a dar. Pero ¿qué ha pasado otra vez? A ver si te has fijado. ¿Qué ocurre?
Que se está recargando toda la página otra vez. ¡No me lo puedo creer!
Sí, efectivamente. Se está recargando toda la página.
Y es porque este router.push le pasa exactamente lo mismo que en link.
También lo tienes que tener en cuenta.
De la misma forma que aquí en link le hemos puesto el href y el as,
en el router.push también tenemos que indicarle la ruta a la que tiene que ir
y luego el path al que tiene que machear esa ruta.
Así que es un poco raro.
Entonces, lo primero, como lo mismo de antes, lo primero sería la ruta, así,
y luego sería el path.
El path a la que queremos ir con esa ruta.
Y ahora sí, ahora sí, puedes ver que no se está recargando.
Así que, importante, hemos visto ya las rutas dinámicas,
hemos visto cómo podemos hacer el link
y cómo podemos hacer con el router, la navegación programática
y ahora sí, no deberías tener ningún tipo de problema
para utilizar las rutas dinámicas en tu aplicación.
Entonces, por ahora vamos a dejar esto así,
vamos a entrar ya en nuestro tweet
y vamos a hacer que aparezca aquí el tweet de alguna forma.
Data fetching.
Básicamente, el concepto de data fetching es tal y como se traduciría en castellano,
que es recuperar datos.
¿Pero qué quiere decir recuperar datos?
En nuestra aplicación, hasta ahora, a ver si hemos hecho,
claro, no hemos hecho ningún fetch,
pero sí que hemos recuperado los datos que necesitamos
para nuestra aplicación en el cliente.
Hemos hecho el data fetching, lo hemos hecho en el cliente,
en la parte del cliente.
¿Qué pasa con eso?
Aquí, cuando hacíamos este, por ejemplo,
pa, pa, pa, add debit, no.
Fetch latest debits, aquí.
Este, esto es un, al final, esto es un data fetching, ¿no?
Es recuperar datos.
Pero estos datos los estamos recuperando desde el cliente.
El tema de hacerlo desde el cliente
es que le vamos a tener que enseñar al usuario
algún tipo de placeholder o cargando, lo que sea,
mientras podemos recuperar los datos.
Por eso lo hacemos en el efecto,
no lo podemos hacer antes en el cliente.
¿Qué pasa?
Que hay cierta información o ciertas páginas
que nos gustaría que la pudiéramos hacer en el servidor,
poder renderizar esa información en el servidor
por diferentes motivos.
Uno puede ser el SEO, ¿no?
Porque queremos que Google encuentre esa página
mucho más rápido o porque ya tenemos el contenido
y podemos hacer que esa página, pues, sea estática
y no necesitamos que un artículo,
no necesitamos hacer el fetching en el cliente.
Si ya tenemos el artículo y lo podemos crear, ¿no?
Y dárselo estáticamente al usuario, pues, mejor que mejor
porque será más rápido para el usuario.
Así que vamos a hacer el data fetching
y vamos a ver cómo Next.js nos ofrece diferentes métodos
para hacerlo y cada uno de ellos, pues,
tiene sus cosas buenas o sus cosas malas.
Bueno, ya os digo que hay una que no es que tenga sus cosas malas,
sino que se va a dejar de utilizar.
Y es el primero que vamos a ver porque,
aunque es el que se va a dejar de utilizar,
no deja de ser el más famoso de todos.
Así que yo creo que en todos los ejemplos lo vas a ver todavía.
Así que creo que es interesante conocerlo.
El método del que estoy hablando se llama getInitialProps.
¿Vale?
Y este método tiene que ser una propiedad estática de la función.
También funciona con clases.
Si esto fuese una clase en lugar de una función,
también deberíamos hacer exactamente lo que estamos haciendo aquí.
Tenemos que poner el nombre del componente, punto,
getInitialProps y aquí ya tendríamos que hacer la magia
que tenemos que hacer para hacer el data fetching desde el servidor.
El getInitialProps se va a ejecutar siempre en el servidor
y también en el cliente cuando pasas de una página a otra.
De hecho, lo podemos ver ahora en un momento.
Si yo aquí, no recuerdo si,
yo creo que podemos devolver un objeto o así.
Si pongo aquí getInitialProps y guardo los cambios,
vamos a ver que si yo entro a esta página,
aquí le voy a dar ahora a refrescar aquí, ¿vale?
Y yo entro a esta página.
Entonces, aquí en la consola,
aquí puedes ver que me ha puesto el getInitialProps.
Si sale en la consola de la terminal,
es que se está ejecutando en el servidor,
no se está ejecutando en el cliente.
¿Qué pasa?
Si yo ahora voy a inicio,
voy a esta página donde tenemos diferentes tweets,
voy a quitar todo esto
y voy a entrar a uno de los debits, un tweet nuestro.
Pues vamos a ver, voy a limpiar esto también.
Y al entrar, puedes ver cómo,
bueno, esto es un console.log que tenemos por ahí.
Vamos a ver, este console.log lo voy a quitar
para que no añada ruido, ¿vale?
Perdón.
Y vamos a volver a hacerlo, ¿vale?
Para que no haya ese getDateDif.
Vale, entramos al tweet.
Vale, y ahora ves que se está ejecutando aquí.
Esto es porque cuando hacemos una navegación SPA,
se está ejecutando en el cliente.
Claro, no va a volver a renderizar la página del servidor.
Cuando se ejecuta el getInitialProps en el servidor,
es que está renderizando la página del servidor.
¿Y cuál es la diferencia?
Pues que si yo le doy aquí al viewPageSource
y miro el código fuente,
ahora porque no tenemos información,
pero lo que sí que podemos ver es que aquí
ha vuelto a ejecutar este método.
Y lo ejecuta justamente para que pueda crear el HTML
que va a expulsar como un string para dárselo al usuario.
Vale, hasta aquí todo bien.
Ya sabemos que el método este se ejecuta donde se ejecuta.
Recibe un parámetro context.
Que el parámetro context tiene un montón de cosas
que ahora no recuerdo, no sé si me voy a acordar de todas.
Tiene la query,
que es donde vamos a sacar el segmento dinámico de la URL.
Tenemos también la request y la response
en el caso de que estemos en el servidor.
¿Y qué más tenemos?
Y no me acuerdo qué más tenemos.
Creo que tenemos más cosas
que tampoco a lo mejor no son tan útiles.
Pero esas estoy seguro que son las que vamos a tener.
A ver, el data fetching.
Si me acordase ya de todo sería...
Ah, el path name.
Claro, el path name,
que es la ruta actual que tenemos.
El path name.
Query es el que os he comentado.
¿Qué más?
El aspath.
Aspath es un string con...
Ah, bueno, que es el path
que va a aparecer directamente en la URL.
Y el request, el response y el error.
Un objeto error en el caso que haya encontrado algún error
mientras se ha renderizado.
Bueno, he hecho un 50%.
He hecho un 5 de 10, más o menos.
Aprobado o raspado.
Bueno, tenemos este context.
Por ahora lo que vamos a hacer de este context
es recuperar la query.
Y en la query, os he comentado ya
que teníamos los segmentos.
Los segmentos de la ruta, ¿no?
Entonces, ¿qué segmentos nosotros hemos creado en esta ruta?
Pues hemos creado la de ID.
¿Y por qué ID?
Pues esta ID que puedes ver aquí
es la ID que hemos creado en nuestro archivo.
Es el nombre del archivo o directorio
que hemos hecho antes, ¿vale?
O sea, esto no es que sea ID siempre.
Esto es importante.
Tiene relación con la ruta que hemos creado aquí, ¿vale?
Así que por eso se llama aquí ID.
Así que este getInitialProps,
ahora podemos poner aquí la ID
y podemos devolver un objeto con ID.
Ahora vamos a ver el tema del objeto, ¿vale?
Si refrescamos, puedo ver que aquí tengo el getInitialProps
y que tengo la ID.
Pues perfecto.
Ahora, ¿qué tengo que hacer aquí?
¿Este return hacia dónde va?
Pues como dice el método, es el getInitialProps.
Así que la información que devolvamos en este método
va a llegar como props al componente,
al componente página.
Porque el getInitialProps, súper importante,
solo puedes tener en componentes de tipo página, ¿vale?
Todo lo que son páginas.
No puedes poner un componente así.
Tienen que ser páginas.
Así que aquí, si hacemos un console.log de props.id
y guardo los cambios,
puedo ver cómo aquí, tanto aquí,
como aquí, bueno, aquí no, porque no se está viendo,
pero aquí tenemos la ID, ¿no?
Ya ha recuperado la ID
y además aquí está ocurriendo este paso de rehidratación.
¿Por qué rehidratación?
¿Qué está pasando aquí?
El tema es que en el servidor
se está renderizando toda la aplicación.
Se está renderizando todo.
Pero cuando se renderiza,
lo que está expulsando es un string.
Es HTML.
O sea, es un string.
No tiene el concepto de props, state y todo esto.
Eso es de masa complejo.
Es un string.
O sea, lo puedes ver aquí.
Esto es un string.
Todo esto es un string.
¿Qué pasa?
Que cuando llega el cliente,
toda esta información,
el cliente tiene que inicializar la aplicación de React.
Pero, ¿cómo lo hace?
Porque se rehidrata.
Que esto significa que esto,
que está todo estático,
toda esta información que es estática,
que es un string,
lo que está haciendo es recuperar la información
que le llega aquí.
¿Ves?
Aquí que pone props, page props,
id, y aquí la id.
Pues esta información,
que la hemos recuperado desde el servidor,
la utiliza el cliente para hidratar la aplicación.
O sea, es como que está haciendo dos veces el renderizado,
uno en el servidor y luego en el cliente.
¿Vale?
Así que por eso se llama rehidratación,
porque es algo que ocurre como dos veces.
Piensa que esto es como dotar de vida.
Es como,
no sé exactamente por qué se llama rehidratar.
Es porque, bueno,
hidratar es porque se están dando los datos para que cobre vida.
Pero básicamente es eso, ¿no?
Tenemos que hacer que la aplicación funcione en el cliente
y entienda que tiene ciertas props,
ver si realmente machea todo,
que se inicien los eventos y todo esto.
Y eso ocurre en ese punto.
¿Vale?
Ok.
¿Qué más?
Usando router replace en lugar de router push,
creo que soluciona lo de tener que pasarle el as.
Dice Miguel,
sí, puede ser,
pero es que el problema es que el replace
no es exactamente lo mismo que el push.
O sea, el replace lo que tú haces es reemplazar la URL.
Cuando queremos hacer,
o sea,
reemplazarla significa que en el histórico
no debería,
o sea,
la estás reemplazando.
El push es como que estás añadiendo en la cola
otra navegación
y debería ser lo correcto.
Igualmente,
yo creo que esto lo van a arreglar en AI-.
Así que,
vale.
Pues ya que sabemos esto,
ahora lo que nos gustaría hacer,
tenemos la idea,
pues lo que tenemos que hacer aquí,
aquí esto puede,
esto es totalmente síncrono ahora,
pero esto puede ser asíncrono,
o sea,
podemos utilizar una promesa,
en este caso,
vamos a hacer un return
de un fetch.
Este fetch
lo vamos a tener en HTTP,
localhost,
y ahora os explico
por qué tengo que poner
toda la ruta.
Claro,
porque alguien diría,
bueno,
pero por qué tienes que poner toda la ruta,
esto no tiene mucho sentido,
¿no?
O sea,
vale,
Apple Response
y esto,
si el API Response
es ok,
¿vale?
Porque ya hemos visto
que puede no ser ok,
pues entonces lo que hacemos
es hacer un return
de API Response
punto JSON,
que eso,
ese JSON
es el que hemos visto antes
aquí,
aquí en API
barra
debits,
creo que era,
vale,
pues este JSON
es el que estamos creando
con este API Response
punto JSON,
¿vale?
Ok,
si no es ok,
bueno,
pues ya veremos lo que hacemos
si no es ok,
por ahora lo vamos a dejar así
y yo creo que está bastante bien,
vamos a dejar esto así
y ahora no sé si,
vamos a ver que nos llega
como props en general,
¿vale?
Vamos a refrescar,
vale,
ya vemos que tenemos
toda la información,
¿por qué hay que hacer un fetch
aquí?
¿Por qué hay que hacer un fetch
poniendo el dominio,
¿no?
Porque alguien diría,
oye,
pues por qué no quitas esto
si ya sabes que la ruta
es esta.
Esto,
bueno,
igual funciona
y alucinado,
no,
claro,
y bueno,
y es que ya te lo chiva,
dice que solo las URLs
absolutas están soportadas,
claro,
tiene sentido,
¿no?
Porque nos tenemos que poner
en el lugar del servidor,
el servidor en realidad
no tiene esa información,
no sabe en qué ruta
va a poner el dominio,
no tiene por qué saber
esa información
en ese punto,
¿vale?
Entonces,
¿podrían llegar
a solucionarlo?
Creo que es algo
que podrían llegar a hacer
el soportar rutas relativas,
pero conceptualmente
puede tener sentido
que no funcionen
las rutas relativas.
Así que,
bueno,
cuando hacéis el get initial props
tenéis que hacer rutas absolutas,
pero cuando estáis en el cliente
ya pueden ser relativas,
no hay ningún tipo de problema.
Vale,
ahora que ya tenemos
toda la respuesta
en las props,
veo que aquí tengo
toda la información,
veo que vamos a tener
a lo mejor un problema
con el credited ad,
pero bueno,
nosotros lo vamos a probar igual.
Vamos a hacer aquí,
vamos a recuperar el debit,
que es el componente
que renderiza un tweet nuestro,
vamos a hacerlo a saco,
¿vale?
Vamos a hacer el punto punto props,
básicamente para hacer
un spread ahí
de todas las props
que nos están llegando
y pasarse directamente
a esa debit.
Creo que esto va a petar,
¿eh?
Pero lo vamos a probar.
Guardo los cambios
y efectivamente ha petado.
Vale,
ha petado
porque ya me he fijado
en el console log y tal
que la,
aquí,
aquí podemos ver
este credited ad
que tenemos segundos
y nanosegundos.
Esto habíamos quedado
que esto no nos gustaba,
que esto no iba a funcionar
así como tal.
Esto lo que teníamos que hacer
en la,
voy a ir a la página esta,
que esta es la API,
¿no?
Claro,
en el client,
si lo miramos,
aquí estábamos haciendo
otra cosa.
Aquí estábamos recuperando
el data,
recuperamos el ID,
que esto lo vamos a necesitar,
que no lo estábamos haciendo,
así que esto lo vamos a recuperar
también,
el ID,
y lo que hacíamos
con el created ad este
era este created,
o sea,
es que esto se puede copiar
tal cual,
que también esto nos,
nos está indicando
que algo podríamos hacer
mejor aquí,
vale,
solo que en lugar
de un return,
aquí lo que deberíamos hacer
pues sería
o el response.json
directamente de esto
y ya está,
vale,
ahora sí tendría
el timestamp
que habíamos creado
anteriormente,
porque no queremos
un objeto,
sino queremos el timestamp
del created ad,
así que guardamos
los cambios,
vamos a ver ahora,
vale,
esto también peta
por otro lado,
pero esto ya tiene pinta
de ser otra cosa,
porque pone navigator,
hmm,
navigator,
esto es un bug
que me ha traído
mi amigo Miguel Ángel
en la PR,
¿qué pasa?
y esto es súper importante,
¿vale?
cuando utilizamos
getinshalprops
o otros métodos
como el get
getServerSideProps,
claro,
tenemos que pensar
que eso se ejecuta
en el servidor
y por lo tanto
nuestros componentes
cuando se rendericen
no pueden tener llamadas
que vayan
a utilizar
una API
que sea del navegador
y ya os puedo asegurar
que este
navigator language
ya suena a navegador.
Entonces,
a ver,
vamos a poner por ahora
el default language,
¿vale?
y nos vamos a olvidar
de esto,
el default language
creo que era el español
así que ya estaría,
¿vale?
ahora funciona
y bueno,
ya tenemos ahí
nuestro tweet
que hemos recuperado
del servidor
y ya se está mostrando.
Ahora,
lo interesante de esto
es que si miramos
los,
si miramos el HTML
deberíamos ser capaces
de ver
que ahí está ya
toda la información
y esta es la diferencia,
aquí podemos ver
que tenemos el HTML
¿no?
y se ha renderizado.
Estamos haciendo
el renderizado
en el servidor.
¿Qué pasa?
si miramos
por ejemplo
la home
que no tenemos
esta estrategia
y es totalmente distinta
¿no?
si vamos a la home
y yo miro
el HTML
aquí podremos ver
que sí que tengo
algunas cosas
pero no tengo
el contenido
porque este contenido
este no te pierdas
en live
si yo busco aquí
el no te pierdas
en live
pues me dice
cero de cero
esta información
la estamos recuperando
en el cliente
entonces
en Twitter
tiene sentido
son
esa información
muy muy
o sea en Twitter
o en la home
es información
que es muy muy muy fresca
y no tiene sentido
porque cada usuario
ve una home distinta
imagínate
como de computación
puede haber ahí
si tiene que ser
nuestro servidor
el que lo hace
mejor
si esto se lo delegamos
al cliente
y los millones
de usuarios
que tenemos
en sus dispositivos
son los que hacen esto
que además
tiene diferentes ventajas
no solo monetarias
y tal
sino también de velocidad
porque le devuelves
al usuario
rápidamente
algo que pueda haber
por ejemplo aquí
nosotros
mientras está cargando
pues podemos poner aquí
un playholder
vamos viendo cosas
hasta que se carga
y eso
es algo bueno
para el usuario
en lugar de tener que esperar
en el servidor
que se renderice todo
y entonces enviárselo
porque eso lo que va a hacer
es que el usuario
se va a quedar
mirando una página en blanco
todo el rato
pero
entonces
¿por qué puede ser interesante
por ejemplo
hacerlo aquí
en el tweet?
en el tweet
puede ser interesante
por diferentes cosas
lo primero
es que es información
que no cambia
por lo tanto
la podemos cachear
súper rápido
la podemos tener
en el servidor
muy rápido
y esto
si es muy rápido
como la capturamos
pues si la renderizamos
en el servidor
y se la damos
inmediatamente
pues es genial
luego también
porque vamos a querer
que los crawlers
puedan tener acceso
rápidamente
a esta información
¿no?
que
esto porque es un tweet
muy muy corto
pero por ejemplo
bueno
este también es muy corto
no son los tweets
más largos del mundo
pero bueno
es interesante
que el crawler
pueda ver
todas las urls
como por ejemplo
esta url
y pueda ver
el contenido
que hay
la url
todas las conversaciones
que hay
y eso es interesante
¿no?
el tema es que
este fetch
que estamos haciendo aquí
o sea
esta petición
está ocurriendo
cada vez
que el usuario
entra a esta url
o sea que
si el crawler
entra mil veces
mil veces
se va a hacer ese fetch
lo cual
es un poquito problemático
pero bueno
por ahora
nos quedamos con esto
que estamos haciendo
getinshalprops
esto se está renderizando
en el servidor
y ya se está haciendo
la rehidratación
y ya funciona
correctamente
luego en el cliente
así que
hasta ahí bien
esto lo podríamos mejorar
un poco
porque me imagino
que yo si pongo aquí
por ejemplo
lo que sea
esto peta
por todos los lados
peta
porque nos dice
que el getinshalprops
tiene que resolver
un objeto
y tal
tenemos diferentes estrategias
una podría ser
devolver un objeto
que tenga el error
conteniendo un error
y entonces en el cliente
hacer algo
y decir
oye pues esto
no funciona bien
o lo que sea
pero
no dejaríamos
de enviarle
un status code
200
que de alguna forma
eso es como decir
no todo ha ido bien
una cosa
que podríamos hacer
otra opción
es ir a
mirar si tenemos
la respuesta
si estamos en el servidor
o sea
que si entra directamente
a esa url
al menos tener la información
que no existe
o que ha habido algún error
y podríamos decir
que esta
la respuesta
esta respuesta
que estamos recopriendo
del contexto
hago este if
porque este response
este objeto response
solo lo tenemos
en el servidor
y esto es importante
así que hacemos un response
podemos cambiar
un poco
la cabecera
para hacer
podríamos hacer
una redirección
esa podría ser una
podríamos hacer una redirección
o podríamos directamente
hacer un
no sé esto
cómo funcionará
vale
pero funciona bien
o sea
esto lo que está haciendo
es que está devolviendo
un 404
lo que estamos diciendo
oye
esto es el servidor
has intentado
tras esta url
esto es un 404
otra cosa
es que podríamos hacer
una redirección
y decirle
que tienes que irte
bueno
podríamos poner aquí
algo más en condiciones
voy a poner la home
por ejemplo
pero
quizás
podemos hacer
un error 404
más interesante
con lo que sea
hacemos un 301
a un sitio
que no sé
que tenga
oye
aquí ha habido un error
esto no funciona
o lo que sea
cualquiera de las cosas
al menos
es un poquito mejor
que dejar que eso
pete libremente
y no controlarlo
vale
así que
al menos lo tendrías
por esa parte
más controlado
entonces
getinshalprops
vale
voy a leeros en el chat
y ahora seguimos
con el get
server site props
porque esto es importante
getinshalprops
que es el que hemos visto
y es el más famoso
es el más conocido
no voy a decir
que está deprecado
porque tampoco
utilizan esa palabra
todavía
y supongo que no lo hacen
porque saben que
no que es peligroso
porque es que
hay demasiados ejemplos
de getinshalprops
llevan demasiados años
con esto
pero sí que están
haciendo una transición
al get server site props
y al get static props
entonces en esa transición
ya te están diciendo
no
deja de utilizar
getinshalprops
y empieza a utilizar
get server site props
y get static props
porque digamos
que son los nuevos métodos
que te van a permitir
generar
o ejecutar
en el servidor
el fetching de datos
o generar páginas estáticas
entonces vas a tener
esas dos opciones
vale
así que
vamos con el
con el chat
a ver que me comentáis
pero en clientes
sí que se ejecuta
el pintado de react
porque en el código fuente devuelto
están solo los datos
quiero decir
que lo que evitas
es tener que obtener los datos
no el render
sí que te evitas el render
y esto es interesante
por eso se llama hidratación
es complejo
vale
pero mira
lo podemos mirar rápidamente
aquí
así que
no solo están los datos
está el html
entonces
se le llama hidratación
si miramos aquí
aquí puedes ver que
aquí
esto es html
y este html
tiene
o sea
los datos
digamos que es este json
aquí estarían los datos
pero es que también tenemos html
entonces
el render
cuando hablamos de render
es construir
el html
y además
inicializar los eventos
ejecutar
el use mount
el use effect
todos los hooks
que haga falta
y todo esto
pero el render
también implica
renderizar
crear
los elementos html
lo que está ocurriendo aquí
es que ya existen
esos elementos html
no hay que renderizarlos
entonces lo que hay que hacer
es hidratarlos
es
vale
ya está este html
lo que tengo que hacer
es dotarlo de vida
es
tengo la información aquí
y tengo el html aquí
así que lo que tengo que hacer es
echarle agüita
que es como lo de hidratar
que es como dotarlo de vida
vale
sé que es un poco raro
pero en react
en la documentación
tenéis los dos métodos
porque además son dos métodos distintos
no es lo mismo
cuando tú tienes el html
que cuando no lo tienes
así que
tenemos por un lado
el react.dome.render
que esto es para renderizar
para crear los elementos html
en un elemento
que tengamos en el DOM
y luego tenemos hidratar
que es lo mismo que el render
pero en lugar de renderizar
los elementos
de crear esos elementos html
estos ya existen
porque vienen del servidor
y lo único que hacemos
es hidratarlos
es diferente
porque el coste
que comporta
es diferente también
o sea no es lo mismo
tener que crear
todo el html
que el html
ya venga
y solo tendrás que asegurar
que
que inicias los eventos
y todo esto
vale
así que
ahí está
el tema
espero haberte contestado
Sergio
con eso
¿qué pasa con el link
que quedó dentro del article?
¿dos click handlers
ahí?
¿no?
bueno
lo que podemos hacer
por sí
es verdad que hay un link
pero es diferente
¿qué pasa?
hemos dejado el link
semántico
digamos
¿no?
el link semántico
del html
lo hemos dejado
en el tema
de la fecha
luego hemos puesto
dentro del article
hemos puesto uno
que no es semántico
sino que es un evento
ahí más con javascript
¿qué es lo bueno de esto?
lo bueno de esto
es que semánticamente
ya no solo un crawler
sino
alguien que quiera
leerlo con
un screen reader
o lo que sea
podría ver que hay un enlace
que va hacia algún sitio
entonces
no es un event handler
el del link
aunque sí
a lo mejor sí que es interno
es un poco raro
porque tampoco lo controlamos nosotros
pero
yo me quedo más
con que hemos hecho
un link semántico
que es algo
es exactamente lo mismo
que hace Twitter
y supongo que van por ahí
los tiros
porque
lo está intentando
está haciendo el conviva
para no perder el anchor
del todo
¿vale?
entonces
vale
veo que estáis hablando
por aquí
de Ant Design
que no está nada mal
a mí me gusta bastante
mejor Guter
totalmente
me alegro que conozcáis Guter
que ha salido una nueva versión
que está muy muy muy chulo
así que
os lo recomiendo un montón
vale
pues
vamos a
seguir
vamos a
seguir con el
GetServer
Site Props
vais a ver que es súper fácil
porque
el GetServerSite Props
que es otra forma de hacer
el data fetching
viene a sustituir
el GetInShare Props
exactamente
viene a sustituirlo
o sea
es como
no voy a decir exactamente
lo mismo
pero
viene a sustituirlo
cuando tienes que utilizar
el GetInShare Props
o
sobre todo
si vas a empezar
una aplicación ahora
no utilices
el GetInShare Props
yo lo he explicado
porque en cualquier ejemplo
que vayas a ver
te lo vas a encontrar
si vas a utilizar
el GetInShare Props
para eso
mejor utilizar
el GetServerSite Props
que es el que vamos a ver ahora
¿cuándo deberías utilizar este?
esto
tienes que tener en cuenta
que se renderiza en el servidor
en cada request
entonces es bastante costoso
y puede ser que al usuario
pues vea una página en blanco
antes de ver algo
no es lo más óptimo
pero es verdad
que a veces puede ser
lo más deseable
¿por qué?
porque puedes tener
por ejemplo
información que cambia
muy
muchas veces
pero que aunque cambie
muchas veces
quieres que lo vean
los crawlers
o que puedas tener
el HTML ya directamente
puede ser el caso
de resultados de búsqueda
¿qué pasa?
resultados de búsqueda
si tú quieres
que haga crawling
Google
es verdad que Google
ahora puede hacer
el renderizado
en el cliente
pero no es tan óptimo
tarda más
puede tardar más
en crawlear tu página
¿y cuál es el problema
de esto?
el problema es que
si tienes normalmente
las búsquedas con filtros
tienen miles y miles
de páginas
y de combinaciones
entonces
si te fías
del renderizado
en el cliente
no va a funcionar
tan bien
y vas a ver
que no te croalea
tantas páginas
como esperabas
no te las va a poner
en el índice
entonces vas a necesitar
hacer server-side rendering
entonces vas a querer
utilizar el get-inshared props
por ejemplo
un resultado de búsqueda
¿vale?
get-inshared props
o mejor
get-server-side props
get-server-side props
es súper fácil
una vez que tienes
el get-inshared props
lo que tienes que hacer
ha cambiado
la forma de utilizar
estos métodos
de hacer data-fetching
en lugar de hacer
una propiedad
del componente
ahora lo que hay que hacer
es exportar
directamente
un método
que va a ser
el que se llame
get-server-side props
¿vale?
se tiene que llamar
exactamente así
no me puedes poner
cualquier nombre
en lugar de un const
voy a poner que sea async
así utilizamos async
que muchas veces me decís
¿por qué no utilizas async?
¿vale?
y aquí igual
también recibí
un objeto context
aunque tiene alguna diferencia
a mi parecer
bastante adecuada
creo que han mejorado
ya que estaba en la API
¿vale?
así que para crear
este server-side props
tenemos que crear
esta función
un export
de la función
esto puede ser async
o puedes utilizar
promesas dentro
y lo que vamos a hacer
por ahora
vamos a hacer un corta
ahí pega
directamente
¿vale?
vamos a eliminar
la que teníamos antes
y vamos a poner esto aquí
esto es un poquito
diferente
porque en lugar de query
aquí lo que recibe
son params
así que en lugar de query
vamos a tener params
y en los params
vamos a tener la posibilidad
de acceder
a la ID
ahora aquí
las que tenemos
son params
tenemos request
tenemos response
también
y tenemos query
que es donde tenemos
la query string
¿vale?
esto sería lo que teníamos
en el contexto
por lo demás
lo vamos a dejar
igual
a ver
vamos a cambiar esto un poco
vamos a utilizar
aquí una wait
y ya está
o sea básicamente
esto ya lo podríamos poner así
aquí ya
ah
hay otro cambio
importante
lo que devuelve
no es exactamente lo mismo
lo que devolvíamos
en el getting shell props
era un objeto
que directamente
iba como props
al componente
aquí no es exactamente igual
de hecho esto lo vamos a cambiar
y vamos a ver por qué
aquí lo que hay que devolver
es un objeto
vamos a poner props
y hacemos una wait
de este json
lo que hay que devolver
es un objeto
que tiene la key props
y dentro
las props
que le va a llegar
al componente
¿vale?
así que tiene otra diferencia
esto es muy buena idea
porque si el día de mañana
va creciendo la API
le dan más posibilidades
claro si tú pasas un objeto
y ese objeto
ya le llega al componente
imaginemos que aquí
puedas tener más configuración
pues estaría bien ¿no?
así que lo que tenemos
que hacer es esto
por lo demás
esto funciona
o debería funcionar
exactamente igual
¿no?
si tenemos la respuesta
pues con algo así
tan rápido como esto
vamos a ver si
refresco
esto ya funciona
¿vale?
si miro aquí un poco
exactamente funciona igual
tenemos el HTML
tenemos el contenido
esto ya lo tendríamos funcionando
perfectamente
¿vale?
así que esto sería
esto sería ya la única diferencia
ya tenemos el GetServerSideProps
esto se ejecuta en el servidor
como hemos visto
con el GetInitialProps
y ya estaría
ahora
esto
en Twitter
puede tener sentido
pero existe otra forma
de hacer el DataFetching
o el DataFetching
o cómo crear
las páginas
de nuestra aplicación
de Next.js
ya os digo
que creo
que
en esta aplicación
seguramente
no tendría mucho sentido
pero como lo tenemos que ver
pues lo voy a enseñar
¿vale?
hemos visto que está la forma
de crear
o sea
de hacer el DataFetching
en el servidor
pero también podemos hacer
el DataFetching
en tiempo
de construcción
de nuestra aplicación
en tiempo de build
build time
¿vale?
o sea
cuando hagamos la build
de nuestra aplicación
podríamos hacer el DataFetching
y generar páginas
estáticas
de nuestra aplicación
para eso
tendríamos que utilizar
otro método
que se llama
GetStaticProps
así que voy a ponerlo por aquí
y voy a comentar esto
porque este
no es exactamente igual
y vamos a ver que tiene
unas cuantas cosas
más especiales
¿vale?
para utilizar el
GetStaticProps
lo primero que vamos
a ver
vamos a hacer
vamos a ir a saco
¿vale?
o sea
vamos a ir a saco
en el sentido de
si os digo que hay otro método
pues hay otro método
GetStaticProps
¿no?
y vamos a guardar los cambios
y vamos a ver si esto
directamente funciona
de una
o de que se queja
¿no?
para ver un poco
por dónde van los errores
ya vemos
que nos da un error
¿vale?
no es tan fácil
como cambiar
el método y ya está
¿por qué?
porque esto se ejecuta
en otro momento
¿qué pasa?
que en modo desarrollo
sí que vamos a hacer
que se ejecute
mientras estamos desarrollando
pero no es exactamente
lo mismo
esto se ejecuta
en BuildTime
ya nos dice
que tenemos un método
que se llama
GetStaticPath
y está requerido
para hacer
la generación
de la página estática
¿vale?
así que
tenemos que crear
otro método
esto si pensamos
que funciona
que ya os digo
que hay una cosita
por aquí
que no creo que funcione
pero pensando
que esto funciona
ya nos está avisando
que necesitamos
como acompañar
este método
con otro método
que es el GetStaticPath
vamos a crearlo
así que hacemos un
no sé
creo que no tiene
que ser asíncrono
bueno
podría ser asíncrono
porque al final
el GetStaticPath
lo que le vamos a decir
es
que path
tiene que hacer
que funcione
el recuperar
la información estática
¿por qué?
porque cuando la ruta
es dinámica
claro
si queremos
que nos genere
la página
cuando hacemos
el BuildTime
en BuildTime
o sea
cuando estamos construyendo
la aplicación
y la ruta
es dinámica
¿cómo sabe
cuántas rutas
tiene que generar?
porque como vamos a ver
nos está generando
el HTML
o sea
lo que está haciendo
es generar
el HTML
de cada una
de esas páginas
pero claro
si nosotros tenemos
millones de tweets
¿cómo lo va a hacer?
y si tenemos 10
pongamos que no son tweets
pongamos que es una tienda
tenemos 40
40
productos
¿cómo sabe
que son esos 40 productos?
para eso es este método
para eso es el GetStaticPath
para nosotros decirle
cuáles son los paths
que
cuáles son los paths
que tiene que crear
que tiene que generar
y esa información
la podríamos recuperar
de una base de datos
podríamos recuperar
todas las ideas
y entonces decir
pues estos son todos los paths
podría ser manual
podríamos decirle
no
estos son los paths
en concreto
que son
porque son o son 3
y ya está
lo importante
es que tenemos
que devolver el objeto
diciéndole
el array de path
y luego
tenemos otro
que es el fallback
que luego veremos
por ahora vamos a poner
que es false
y luego lo comento
ahora nos vamos a enfocar
en los paths
que tenemos el array
aquí es donde tendríamos
la lista
de todas las urls
que tendríamos que hacer
con el GetStaticProps
como para decirlo
no es que esta es la url
que tienes que hacer
vale
ya he cambiado esto
he añadido este método
pero al guardarlo
me da un 404
¿por qué?
porque esta ruta
que he añadido aquí
ahora mismo
en el path
no está
o sea
no le he indicado
que esta ruta
deba existir
que sea
esta ID exactamente
una ID
que yo estoy soportando
para que sea estática
claro
entonces ¿cómo hacemos esto?
pues le tenemos que decir
vale
entre el array
vamos a tener
un objeto
y en los parámetros
de ese objeto
tenemos la ID
y la ID
es justamente esta
ahora
si pongo esto aquí
y guardo los cambios
ahora sí
vamos a ver
que esto funciona
hasta aquí esto funciona
pero esto es un poco
más complejo que esto
aquí
todo esto funciona
porque estamos
en modo desarrollo
y lo que está haciendo
en modo desarrollo
es de alguna forma
hacer el fetch
cada vez que lo necesita
claro
porque si no
si realmente creas
un estático
y yo sigo programando
y cambio algo
se volvería loco
diría
pues ahora ¿qué hago?
nada
tú ya has creado el estático
ya no puedes ver lo que hay
no
en este caso
lo que está haciendo
es cada vez
que lo necesitamos
lo está generando
porque estamos
en modo desarrollo
y así cada vez
que hacemos cambios
pues los estamos viendo
en vivo
o sea es como que
se está saltando
el paso de estático
pero de alguna forma
intenta funcionar estático
porque si miramos
el HTML
veríamos
todo este HTML
pero el HTML este
comparado con el del servidor
es el mismo
la diferencia
es que el del servidor
se estaría generando
cada vez que hacemos
una request
y este
solo se generaría
una vez
una vez
una vez
¿cuál es el problema
de esto?
el problema de esto
es que no puedes tener
contenido
que sea
pensado en el usuario
por ejemplo
la home
jamás podríamos tener
que fuese estática
tendríamos que hacer
el fetching
en el cliente
o en el servidor
pero tenemos que saber
que es para ese usuario
no podríamos tener
un HTML estático
para ese usuario
para la home
porque va a ir cambiando
¿no?
entonces
es importante
que este contenido
solo puede ser
para contenido
que pueda ser
pues por ejemplo
un tweet
el tweet
siempre va a ser el mismo
podemos hacer
que ciertas partes
que sí que son dinámicas
en el sentido de
el usuario
el avatar
que sale arriba
cuando está logado
pues eso lo hagamos
en el cliente
pero la parte
del tweet
y su contenido
puede ser estática
pero ya os digo
que esto
no le gusta
esto no funciona
hay diferentes cosas
que aquí
no están bien
lo primero
es el concepto
de tener el response
porque si hemos dicho
que estamos en build time
es imposible
que tú en el método
puedas hacer nada
en el servidor
porque no va a estar
en el servidor
esto no está en el servidor
está cuando tú generas
todo el paquete
de tu aplicación
así que tendríamos que eliminar
todo lo que es el response
porque esto no funciona
eso por un lado
así que lo guardamos
así
pero vamos a ver
el problema real
ahora que vamos a hacer
una empaquetación
de nuestra aplicación
vamos a hacer
voy a cortar
el entorno de desarrollo
voy a limpiar esto
y voy a hacer
a ver un mpn run
voy a hacer una build
voy a hacer una build
y vamos a hacer
mpn run build
y esto nos va a generar
nos va a empaquetar
la aplicación
para que vaya a producción
directamente
esto va a generar
todo lo que necesitamos
y que pasa
que si tenemos
un get static props
lo que va a hacer
es intentar generar
esas páginas estáticas
pero ya está viendo
que hay problemas
uno de los problemas
seguramente
va a ser justamente
el tema
de que no existe
la API
esta API
que tenemos aquí
esta API
en realidad es nuestra propia
de next.js
pero en el momento
de hacer build
esta API no existe
una solución
voy a hacer esto
más chiquitito
una solución
que podríamos hacer
y que tiene sentido
es que lo que estamos
haciendo
en la API
realmente lo hagamos
en el get static props
porque no estábamos
haciendo nada
del otro mundo
o sea
esta información
todo este
Firestore
todo esto
lo podríamos hacer aquí
en lugar de hacer esto
podríamos hacer esto
solo nos faltaría
importar el Firestore
así que importamos
Firestore
de Firebase
barra admin
esto funcionaría
exactamente igual
no deja de ser
node
solo que no nos está
creando la API
ese servidor
no está levantado
y ahora
en lugar de
hacer este
response.json
claro
no es una respuesta
así que aquí
lo que tenemos que hacer
es que esto sea
estas son las props
y esto
es lo que tenemos
que devolver
las props
aquí podríamos hacer
por ejemplo
props
y voy a poner
por ahora un objeto vacío
pero podríamos mirar
si hay algún error
porque ha petado
que ha hecho
y todo esto
no me he fijado
a ver
creo que esto
debería funcionar
si no
lo vemos ahora
pero creo
ah
hay que hacer
un return
de esto
vale
porque queremos
devolver
la promesa
y lo que devuelve
por dentro
la promesa
vale
entonces vamos a hacer
ahora otra build
y vamos a ver
si esto funciona mejor
compilado
y ahora
está haciendo
vale
ahora sí que ha funcionado
y aquí nos está
indicando ya
qué es lo que ha generado
para cada una
de las páginas
y cuánto carga
cada una de las páginas
y qué es lo que hace
cada una de las páginas
y aquí es donde está
la magia
de next10
podemos ver
las diferentes rutas
que tiene nuestra página
bueno
ha creado una 404
que igual la vemos más adelante
de cómo puede funcionar
una 404
vale
que además nos iría bien
con lo que hemos comentado antes
luego
aquí tendríamos
las dos APIs
estas dos APIs
aquí que tienes el símbolo
de lambda
esto es porque
cuando hagamos el deploy
de estas APIs
pues nos generará unas lambdas
si lo hacemos por verser
y en páginas
aquí
tenemos lo interesante
también
tenemos el compost tweet
y la home
estas dos páginas
digamos que funcionen
con server side rendering
solo que no estamos llamando
nada en el servidor
vale
pero aquí tenemos
la magia nuestra
la del status ID
y además te dice
cuánto ocupa
nos dice que ocupa 3K
y que la primera carga
de javascript
solo son 65K
pero cómo puede ser esto
la diferencia
está que esa página
es estática
no necesita
nada
no necesitas
inicializarla
así que ya está todo el HTML ahí
o sea no tienes que hacer nada más
ahora veremos esa página
pero el problema
entre comillas
es que solo nos ha creado una
solo nos ha creado esta página
nos ha creado la página
que nosotros le hemos puesto
en el get static props
get static path
get static path
a ver si ahora
get static path
exacto
porque
no puedes saber
NextGS
antes de tiempo
cuál es la página
que tiene que generar
vale
si tenemos un millón de tweets
claro alguien me diría
bueno y qué
voy a poner aquí un millón de tweets
voy a hacer eso
no
no vas a hacer eso
no tiene sentido
seguramente
oye
en mi opinión
puede tener sentido más
hacer el server rendering
pero con un sistema de cacheo
bastante potente
eso puede ser una
pero veremos
que esto que estamos haciendo ahora
luego puede tener
otro nivel más
pero por ahora
vamos a ver una cosa
aquí hemos visto
que se está generando
una página
de hecho aquí está bien
porque tienes como una leyenda
de lo que ha hecho
cada una de las cosas
vale
de que una hecha
bueno estoy yo encima
pero
a ver lo que pongo aquí
pone server static
o sea nos dice cada una
como ha sido cada página
claro
estas
una cosa es que sea
la página estática
porque
a ver la página es estática
aunque la está sirviendo
un servidor
pero que no tiene initial props
que son nuestras páginas
como la del compose
y la home
y luego tendríamos
la que se ha generado
un HTML estático
y con un JSON
plano
y ya está
vale
entonces
esta página
somos capaces
de verla
si vamos aquí
a punto next
server
pages
status
y aquí la tenemos
esta página
que tiene esta idea
en concreto
es la que se ha generado
porque le hemos dicho
no tienes que generar esta
si le hubiéramos puesto 50
hubiera generado 50
vale
así que aquí es donde está
la magia
de generar páginas estáticas
como digo el problema
es que si ahora
intentamos utilizar
una URL
que no hayamos puesto aquí
pues no funcionaría
y no tendría tanto sentido
esto
y sería bastante triste
porque veríamos
pues que no
no funciona
¿no?
entonces
lo interesante de esto
está en
tiendas online
de hecho
esto sería como
la competencia
de Gatsby
esto sería la competencia
de Gatsby
pero hay una cosa
que lleva esto
al siguiente nivel
voy a volver a levantar
el entorno de desarrollo
y aunque hoy
no lo vayamos a ver
porque ya
es tarde
pero me gustaría
comentaroslo al menos
es el tema
del fallback
cuando hemos estado
hablando antes
y os he dicho
bueno ahí hay un fallback
pero no te olvides
olvídate
cuando hemos dicho fallback
y le hemos dicho false
lo que estamos diciéndole aquí
básicamente es
si el path
que has intentado acceder
no está ahí
es un 404
o sea
ya está
esto es lo que hay
no se puede hacer nada
y punto
pero
una cosa que se podría hacer
es decirle
el fallback true
el fallback a true
lo que va a decir es
bueno
vamos a ver una cosa
si no está aquí
si por lo que sea
esto no está aquí
lo que voy a hacer
o sea
esto lo podemos dejar vacío
voy a guardar los cambios
y si intento acceder ahora
a una url
que me dice que no existe
ahora me da un error
totalmente diferente
y es que ahora
está intentando
renderizar la aplicación
aunque no está en los paths
voy a poner una
que sí que es correcta
voy a intentar ir aquí
a la home
voy a
voy a hacer un click
bueno esta
hemos visto
la de esta foto
es la que tenemos
esta idea
es la que tenemos aquí
en get static path
vale
pues vamos a ir a la home
y en la home
voy a darle click
a otra cosa
por ejemplo
a este
que es la otra imagen
vale
ahora le voy a dar a refrescar
y ahora está petando
vamos a ver
si esto lo podemos arreglar
porque
porque está petando
o sea
porque esta url
que tenemos aquí
esta id
no está haciendo match
con los paths
que tenemos aquí
lo que está pasando aquí
y es súper interesante
es que lo que va a hacer
next.js por ti
es que si no hace match
con ninguna de estas
va a generar
el archivo
va a intentar generar
el archivo estático
en el servidor
va a ejecutar esto
y lo va a generar
pero que pasa
no lo genera exactamente
el servidor
lo que va a hacer
para ir todavía más rápido
y para ser todavía más inteligente
no va a hacer como
el get initial props
o el get server side props
lo que va a hacer
es
él va a dar una vuelta aquí
y va a decir
bueno
voy a intentar ejecutar
aquí con lo que tengo
y luego
en el cliente
voy a llamar
al get static props
para generar esta página
y realmente
guardar esa información
y generar la página estática
y lo vamos a ver así
si yo pongo aquí
un console log
vale
y aquí
un console log
a ver
igual
igual no lo vemos
a ver
es raro
pensaba que íbamos a ver
el console log fácilmente
pero ya veo que no
porque claro
no si si
está aquí
vale
pero ya vemos que
está haciendo
ya decía yo
que raro
vamos a ver console log
vale
este es el console log que he puesto
o sea que se está
ejecutando aquí
aunque esta página aquí
esta idea no está macheando
pero claro
como puedo saber yo
si realmente
estoy ahora
en el fallback
o que estoy intentando hacer
porque
si todavía no tengo
la información
de las props
que tengo en este método
va a intentar renderizarlo
con información
que no existe
claro
una cosa que podría intentar
es decir
vale
si props
punto id
si esta información
no la tengo
voy a hacer un reto
un loading
voy a hacer aquí
loading
voy a guardar los cambios
¿no?
y vamos a ver
si esto
funciona
¿vale?
pues ahí podemos ver
que hemos visto el loading
y luego
ha aparecido la información
el tema es que
como estamos en modo desarrollo
y como os he dicho antes
cada vez que hacemos
las requests
esto lo está refrescando
pero lo que está pasando aquí
es que
si esto fuese producción
y lo veremos
en un siguiente vídeo
si esto fuese producción
al hacer refrescar
y una vez que ha tenido los datos
ya hubiera generado
ese archivo estático
y ahora lo que estaríamos viendo
es el archivo estático
ya no volvería a ejecutar
todo esto
ya no veríamos el loading
directamente nos daría
el archivo estático
y eso es lo que lo hace
súper potente
porque lo que está haciendo
es generar
al vuelo
archivos estáticos
ya no nos tenemos que preocupar
del número ilimitado
de tweets
lo que va a ocurrir aquí
es que lo va a generar
bajo demanda
lo que va a pasar aquí
es que vamos a tener
estas páginas
que se van a ir generando
cada vez que se necesiten
no hace falta
que generemos todas
aún así
no sé
hasta qué punto
en algo tan grande
como twitter
o algo así
que queramos hacer con twitter
queramos hacer algo así
pero podemos ver
esta potencia
ahora
se puede hacer
con este props.id
o sea
se puede hacer
mirando una prop
que sepas
que tiene que existir
y así
poner un loading
un playholder
o lo que sea
o puedes utilizar
el router
en el router
tienes este
useRouter
from nextRouter
y el router
tiene
una
un método
creo que era
para
router
eso
isFallback
isFallback
es una propiedad
no es un método
¿vale?
que te dice
si realmente
la página
en ese momento
está en modo
fallback
está en un modo
en el que
no ha hecho match
no está generada
la página estática
todavía
por lo tanto
tiene que ejecutar
el getStaticProps
pero lo va a ejecutar
en el cliente
y mientras hace eso
mientras genera
esa página
lo que va a hacer
es
vas a poder
renderizar lo que tú quieras
para darle algún tipo
de visibilidad
al usuario
para que el usuario
pueda ver
que está cargando
pero una vez
que ya esté
esa información
disponible
ya no verá
más
ya no entrará
nunca más
en este if
si alguien ha generado
ya esa página estática
ya no volverá a ver
ya te digo
que aquí se ve
este cargando
esto se ve
pero como podremos ver
más adelante
esto no
en producción
no sería así
porque se guardaría
¿vale?
además
otra cosa
que podemos
que se puede hacer
porque alguien puede decir
y además
eso es lo que veremos
como vamos a hacer
que se pueda editar
el tweet
en nuestro caso
el debit
vamos a hacer esto
vamos a intentar
generar las páginas estáticas
pero veremos
que las páginas estáticas
claro
una vez que se han generado
¿qué pasa?
que ya no se vuelven a generar
o sea
se quedan estáticas
pero justamente
recientemente
desde la versión
de Next Years
la 9.5
han creado una cosa
que se llama
incremental static regeneration
o generation
incremental static
eso seguro
regeneration
creo que es así
o sea
claro
tiene que ser regeneration
porque vuelve a regenerar
la página estática
que puede ser
cada x segundos
o lo puedes hacer
o lo puede hacer
cada vez que alguien
entra a esa página
y utiliza un poco
la estrategia
del style
while revalidate
que es que
cuando entra alguien
pues va a ver
la página estática
pero en ese momento
lo que va a hacer
Next Years
es decir
vale
esta página
la están visitando
por lo tanto
la voy a actualizar
otra vez
por lo tanto
la siguiente persona
verá la versión
actualizada
pues no
creo yo
que no ha estado mal
el pedazo de repaso
hace tiempo
que no me paso por aquí
¿estáis viendo
server side rendering?
sí
estamos viendo
server side rendering
con NextES
luego
Sergiedo
dice
¿qué problema tiene
el get in shell props
versus el get server side props?
get in shell props
no tiene ningún problema
solo que
a ver
es que
es que ellos no hablan
de que sea deprecated
hablan de que
recomiendan utilizar
get server side
y
get static props
¿por qué?
porque te queda
mucho más claro
cómo va a funcionar
el get in shell props
si te fijas
no habla de servidor
no habla de static
entonces ha quedado
como obsoleto
porque antes
anteriormente
solo hacías
server side rendering
y ahora tienes
las dos opciones
por lo tanto
te recomiendan
get server side
lo primero
porque tienes
la API nueva
que yo creo
que tiene más sentido
el hacer el export
de la función
de forma nombrada
que además
tienes la nueva forma
de acceder al parámetro
en lugar de utilizar
query
utilizas params
que además
devuelves
un objeto
con una propiedad props
esto les da
les da
pie
a poder
mejorar
poder
poner opciones
ahí
esto es una cosa
que no tiene
con el get in shell props
entonces
creo que
no estamos lejos
de ver
que el get in shell props
está deprecated
va a ser
no difícil
pero
ya está
la recomendación
si ya lo tienes
no pasa nada
pero
si tuvieras que hacer
ahora el método
por supuesto
utilizar
get server side props
porque queda mucho más claro
y además
tienes la habilidad
de utilizar
el get static props
que ya sabes
para lo que sirve
que es crear
páginas totalmente
estáticas
así que no hay ningún problema
pero se está quedando
atrás
naro me dice
cuando es conveniente
usar SWR
o SWR
os lo voy a enseñar
SWR
es un hook
que es también
de los creadores
de next.js
que lo que te permite
también es hacer
el fetching de datos
y utiliza
el stale
while revalidate
esta estrategia
de que básicamente
lo que significa
es primero
devuelve
la data
o la información
que ya tiene
cacheada
que es la última
que se pidió
y mientras
va a recuperar
la nueva
para que la próxima vez
que se la pidan
toma
aquí tenés la nueva
¿vale?
¿cuándo es interesante
utilizarlo?
pues es muy interesante
utilizarlo
cuando tienes que hacer
el fetching de datos
en el cliente
¿vale?
no en el servidor
esto no sirve
para el servidor
sobre todo
es para el cliente
porque
puedes cachear cosas
funciona muy bien
para compartir estados
y quiero hacer un vídeo
y he invitado
a un amigo
a ver si
si se anima
y queremos hacer
algunas pruebas
algunos ejemplos
y seguramente
haremos un live
o no
pero un vídeo
seguro que haremos
en el canal
¿vale?
porque me parece
muy potente
y muy muy muy interesante
también pues
se va recargando
totalmente
solo
si alguien
por ejemplo
pide
una nueva versión
pues esa nueva versión
también te llega a ti
o sea es que
tiene cosas muy interesantes
el SWR
y lo veremos
pero
claro
tiene sentido
para cuando haces
el fetching
sobre todo en el cliente
está pensado más
para hacer el fetching
en el cliente
¿vale?
¿qué más?
¿qué más?
ok
es más semántico
y para extinguirlo
sí pero también
es el que va a evolucionar
exacto
he visto que lo he puesto aquí
magnífica clase
como siempre dice
José Manuel Romero
muchas gracias
por cierto
Sergio Serrano
muchísimas gracias
llego tarde
pero soy interesante
pero él ha dejado ya
sus dos dólares ahí
más majo
muchas gracias
Sergio
es un crack
no fallas ni una
es brutal
una pregunta
¿crees que es mejor
usar Firebase en cliente
o a través de Cloud Functions?
un saludo desde Barcelona
dice Jorge
es muy buena pregunta
depende
a ver
depende mucho
yo creo que
yo creo que depende
de
o sea
no creo que sea binario
¿sabes?
no creo que sea mejor
uno u otro
creo que dependiendo
de la tesitura
es mejor
uno u otro
por ejemplo
hoy hemos visto
hemos tenido que crear
el Firebase Admin
que nos da
la posibilidad
de fuera del cliente
acceder a ciertos datos
¿por qué?
porque vamos a querer
hacer renderizados
fuera del cliente
por lo tanto
para acceder a esa información
no tenemos otra
o sea no es que sea mejor
es que es esa
no hay otra
¿vale?
es mejor en el cliente
cuando sobre todo
queremos
por ejemplo
en nuestro proyecto
en la home
porque queremos
que sea información
muy nueva
y que además
si alguien añade
nueva información
automáticamente
le aparezca
y eso viene de gratis
en el cliente
y ahí vale la pena
temas de rendimiento
seguramente
valdría más la pena
intentar evitar
la dependencia
en el cliente
pero pierdes
muchísimas cosas
que son muy interesantes
también para autentificación
por ejemplo
viene muy bien
y eso
creo que lo simplifica mucho
el hacerlo en el cliente
en el servidor
es un poquito más
coñazo
así que
no creo que sea
cual creo que sea mejor
depende de la situación
una es
impepinable
y la otra
te da
ciertas ventajas
por ejemplo
en la home
podríamos haberlo hecho
con Firebase Admin
podríamos haber hecho
un endpoint
pero el hecho
de
cuando alguien
hace un nuevo tweet
que aparezca ahí
automáticamente
pues ya
tendría que haber
tendría que haber
hecho desarrollo
para eso
y eso pues es
un poquito más
rollo
muchas gracias
Adolfo
un rubia
por ese euro
muchas gracias
te lo agradezco un montón
muchas gracias
a todos los que
os habéis pasado por aquí
AKS
dice que llega tarde
una pregunta
si tengo una página
creada en HTML
CSS
y JavaScript
la puedo utilizar
en Next.js
¿cómo la agrego?
¿la puedo agregar?
necesito que hay algo más
la puedes
sí
a ver
tienes diferentes opciones
podrías copiar y pegar
directamente
y envolverlo
en un componente
y eso seguramente
sea la forma
más fácil
no sé
si hay una forma
no sé si
a ver
tendrías la opción
de hacer un custom server
y que para ciertas rutas
devolver directamente
ese HTML
devolver páginas estáticas
seguramente esa sería
la mejor opción
el añadir las rutas
en el custom server
y decir
cuando voy a esta ruta
directamente devolves
ese HTML
y olvídate de todo
creo
recordar
que hay plugins
que también hacen esto
que comentas
el hecho más fácil
en tu next.config.js
decirle
vale
tengo esta ruta
pues cuando tengas esta ruta
devuelve este estático
creo que eso
hay plugins
que lo hacen
lo puedes mirar
a ver
devuélvete
que te pasaste
que explicación
amando este live
muchas gracias
constanza
te lo agradezco
y te mando un saludo enorme
también a diana
que dice muchas gracias
como siempre
mi dúo
el mejor profe
y vosotros
los mejores estudiantes
y los que mejor
me acompañáis
en los live
genial explicaciones
live
siguiendo la next.conf
de octubre
vale
me la apunto
venga
me parece muy bien
guillermo
me la apunto
pero solo si os apuntáis
a ver si voy a estar aquí
solo viendo la next.conf
pero si me decís
que vais a estar aquí todos
la hago
así que
cuenta con ella
rafnix
que no pasa nada
que llegas tarde
si se graba
así no pasa nada
pedro
como siempre
excelente mi dúo clase
nos vemos la próxima semana
cuenta con ello
ya sabéis
dejadme en los comentarios
si queréis
alguna cosa
de ir haciendo
también ideas
que me ayudan
y si no estás suscrito
suscríbete
dale a la campanita
porque creo que entre semana
vamos a hacer el tema
de las imágenes
que quedó ahí a medias
ya más o menos
tengo pensado
como hacerlo
y a lo mejor
no es un live
como de dos horas
como estos
a lo mejor dura menos
pero aún así
creo que será muy interesante
así que os mando
de corazón
un saludo enorme
un abrazo
a todas y a todos
los que os habéis pasado por aquí
que os agradezco
siempre que me acompañéis
espero que os haya gustado
clase
creo que hemos visto
un montón de cosas
que hemos estado
dos oracas
y que bueno
es verdad que
visualmente nuestra aplicación
no ha dado un vuelco
pero bueno
ya tenemos una ruta nueva
tenemos el tweet
tenemos
hemos visto
diferentes formas
de hacer el data fetching
rutas dinámicas
hemos visto el firebase admin
bueno
creo que no está nada mal
creo que no está nada mal
pues nada
muchísimas gracias
por acompañarme
ya sabes
sigue cuidándote
como siempre
en estas fechas
de
de cuidarnos
y de distancia social
y todo esto
pero bueno
que os siento cerca
y eso se agradece
en todas las redes sociales
muchísimas gracias
por estar ahí
y ya sabes
no dejes
nunca
nunca
de darle al frontend
aquí
en mi dude
muchas gracias
un abrazo
chao
un abrazo