This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Este vídeo es una guía para pasar una prueba técnica real de React.
Además, vas a aprender de una vez por todas para qué sirven los hooks UseRef, UseMemo y UseCallback.
Y poder crear tu propio custom hook.
Te recuerdo que esta clase es de una colección de vídeos para que aprendas React de una forma práctica y totalmente gratis.
Te dejo todos los enlaces con todo el material y el código de esta prueba técnica en la descripción del vídeo.
Espero que lo disfrutes, que lo compartas con tus amigos y te dejo con la prueba técnica que es...
Crear una aplicación para buscar películas.
Tiene su historia por qué.
Uno, por los requerimientos más básicos, pero luego por la iteración que te dice evitar que se haga la misma búsqueda dos veces seguidas,
hacer que la búsqueda se haga automáticamente al escribir y además evitar que se haga la búsqueda continuamente al escribir.
Hay que hacer un debounce.
Entonces, vamos a empezar desde cero, lo vamos a ir haciendo increchendo, increchendo, ¿vale?
Vamos a ver unas cosas interesantes que os voy a recomendar como buenas prácticas que tenéis que tener en cuenta cómo yo haría la prueba, ¿no?
La estrategia que yo seguiría para ir haciendo la prueba, para que os sirva, para cuando os enfrentéis a la prueba, pues también las podáis seguir.
Mira, a mí también me han mandado a hacer esta tarea.
Esta prueba es como la de la semana pasada.
Esta prueba es súper típica.
¿Por qué?
Porque tienes que tocar un formulario, porque tienes que validar muchas veces el formulario, porque te tienes que enfrentar a hacer el fetching de datos y luego además, además, tienes que evitar hacer el fetching de datos porque no siempre lo tienes que hacer.
Y entonces aquí empiezan algunos conceptos muy interesantes como el hecho de crear una función o evitar volver a crear la función cada vez que se renderiza.
Esta es para juniors, ¿vale?
Esta ya no diría que es para trainees, porque vais a ver que cuando empecemos con el useRef, el useMemo y el useCallback, son conceptos que no voy a decir que son avanzados, porque son sencillos y hoy los vas a entender y vas a ver cuál es la ventaja que te dan, ¿vale?
Pero vamos a ver que seguramente como trainee sería más useState o useEffect.
El enunciado, crear una aplicación para buscar películas.
La API que vamos a usar es la de omdbapi.com.
Los requerimientos básicos.
Normalmente, las pruebas técnicas lo que nos dicen es esto.
Requerimientos, ¿vale?
Nos ponen los requerimientos y esto que he puesto yo ya aquí en la primera iteración, esto nos lo dicen cuando terminamos, ¿sabes?
Como para ver cómo lo haríamos, lo cual es bastante interesante.
Así que yo ya lo he puesto para que os hagáis una idea, pero muchas veces os lo dejan aquí y luego trampa, ¿vale?
Pero bueno, yo ya lo he puesto.
Tenemos que mostrar un input para buscar la película y para tener que buscar.
O sea, al principio vais a ver que es sencillo, pero vamos a ir creciendo y se va a complicar.
Tenemos que ir aprendiendo React, ¿vale?
A nuestro repositorio, nos vamos a Project y dentro de proyectos aquí, ves que tenemos ya nuestros cuatro proyectos.
Voy a traerme los cambios por si hay alguna cosa que...
Vamos a crear un nuevo proyecto y ya vamos a tener cinco proyectos que hemos hecho con React.
O sea, que no hay nada como hacer proyectos, amigos, ¿eh?
Hay que mover las manitas.
Venga, vamos a poner aquí 05 React buscador película, que también es una prueba técnica, pero bueno, para diferenciarlo de la 04, ¿vale?
Nosotros lo vamos a hacer con React y vamos a utilizar JavaScript más SWC.
SWC es una alternativa a Babel más rápida porque está hecha con RAST.
Vamos a entrar aquí, React buscador de películas.
Hacemos PNPM install, pero puedes utilizar NPM install, el que tú prefieras.
NPM, JARN, el que quieras, ¿vale?
Yo voy a utilizar PNPM install porque va más rápido y a mí me funciona bastante bien.
Así que le damos cambio.
Perfecto.
Y ahora voy a abrir el proyecto con esto.
Vale, un repositorio de Git, ¿te gustaría abrir el repositorio?
Le voy a decir que no.
Y este enunciado que tenía por aquí lo voy a copiar, lo voy a cortar, cierro esto y lo vamos a dejar aquí en el Ritmi, ¿vale?
Ritmi.md, le ponemos el enunciado y así al menos lo tenemos.
Vais a ver que cuando estés solucionando esto, yo os voy a explicar cosas que yo haría para solucionarlo.
O sea, no solo quiero explicaros React, sino que os quiero dar herramientas que cuando tengáis que hacer este tipo de pruebas en tiempo real,
las podáis hacer con una estrategia detrás que os pueda ayudar a resolverla, ¿vale?
Son, no sé, a mí me hubiera gustado como me hubieran contado su día, pero si no os gustan esos pasos y tal, pues podéis hacer lo que quieras.
Pero yo os lo voy a recomendar para que lo podáis seguir.
Vamos a ejecutar el pnpm run dev o npm run dev, el que prefiráis.
Ya nos deja aquí en esta URL nuestro proyecto.
Lo dejamos por aquí.
Esto lo ponemos para acá.
Entonces, lo primero que vamos a hacer, vamos a limpiar todo nuestro proyecto para tener como un clean slate.
El linter ya lo tengo descargado, se supone.
Ahora veremos si nos da problemas si está encontrando.
Sí, ¿ves? Sí que lo tengo instalado ya.
Porque lo tenemos a nivel del proyecto.
Como estamos en un monorepo multipaquete, ya hemos instalado el linter una vez y se utiliza en todo.
Podemos empezar por diferentes sitios.
Yo lo primero que voy a hacer es crear los primeros componentes.
Ya sabemos lo que necesitamos.
Así que en el app CSS, mira, voy a hacer una cosa.
Voy a quitar todos los estilos.
Esto lo vamos a dejar vacío.
Aquí también.
Quitamos todos los estilos.
Queda así.
Una cosa que os recomiendo a veces, ¿ves?
Os quiero dar recomendaciones.
Existen un montón de lo que se llaman frameworks classless.
O sea, son frameworks CSS que no utilizan class.
Hay un montón.
Está Water, está Vault, CSS.
Hay un montón.
¿De qué tratan?
Estos son frameworks CSS que te va a estilar un poquito tu página.
Tampoco te pone grandes cosas.
Te va a estilar un poquito la página y te puede sacar de un apuro para que se vea más o menos bien,
que tengan dark mode y tal y no te quede tan perra tu página.
No es que te vaya a quedar súper bonita, pero le puede dar un toquecillo al menos.
Entonces, yo voy a utilizar water.css.
Hay un montón.
Usa la que te dé la gana porque esto nos va a hacer que, sin estilar absolutamente nada,
sin preocuparnos de mucho del CSS, pues bueno, le va a poner unos estilos por defecto que no va a quedar mal.
Entonces, yo aquí en el index le voy a poner todo esto para que, al menos, ¿ves?
Ya no está mal.
O sea, quiero decir, entre esto y esto, pues bueno, ya tenemos aquí el botón un poco mejor,
tiene dark mode, pues algo es algo.
Y además, como eso es un momentito, pues ya lo tenemos, ¿vale?
Así que este es un ejemplo muchas veces porque veo que mucha gente se pone a perder tiempo con los estilos.
No sé, yo si hacéis algo así, se lo podéis preguntar al entrevistador.
Normalmente no les va a importar que lo hagan.
Entonces, todo esto, lo que se está renderizando aquí, obviamente no vamos a necesitar nada de esto.
Lo vamos a quitar.
Voy a quitar también el React logo.
Vamos a quitar el UseState por ahora.
Vamos a dejar esto vacío.
Almohadilla, miro truco.
Vamos a quitar aquí la prueba técnica.
¿Vale?
Ya empezamos aquí.
Vale, prueba.
¿Qué es lo que nos dice el enunciado que necesitamos?
Es un buscador de películas, así que, obviamente, necesitamos un input.
Ya nos dice input y botón.
Siempre.
¿Qué tenemos que hacer siempre que podamos en nuestras pruebas técnicas?
Enseñar cosas.
¿Vale?
Que quede claro lo que estamos haciendo y que poco a poco vayan viendo resultados.
Así que lo primero que vamos a querer hacer es poner aquí el formulario.
Por ahora le voy a poner un class name, por si lo estilo después.
Y dentro del formulario, pues nada, ya el input.
Podéis ponerle el text o no, porque por defecto es text.
Podéis hacer lo que queráis.
Le podéis poner el playholder, Avengers, Star Wars, The Matrix, ¿vale?
Punto, punto, punto.
Que, por cierto, una cosa interesante del playholder es que mucha gente pone aquí, por ejemplo,
Put your movie name, ¿no?
Normalmente el playholder se pone lo que pondrías directamente.
Queda como mejor.
Porque es el label donde deberías poner, ¿sabes?
El label es donde deberías poner, pon la película aquí, ¿no?
Aquí deberías poner Put the movie name o movie name to search, lo que sea.
Pero bueno, esto es lo que queráis.
Si os gusta lo otro lo podéis hacer.
Pero creo que así queda un poquito mágico.
Vale, vamos a poner un botón.
Esto es otra cosa interesante.
Por defecto el botón, el último botón de un formulario, es del type submit.
Entonces ya no lo tenéis que poner.
Pero bueno, nosotros lo vamos a poner por ahora para tenerlo así.
Al menos ya tenemos aquí esto, ¿vale?
Nuestro input con el buscar.
Bueno, algo es algo.
Si queréis, sabiendo que vais a tener que renderizar más cositas, pues igual lo que podéis poner esto es en el header.
Y ya separar, más que nada, para que vea que sabéis un poco de semántica web.
Porque esto sería el header y aquí vais a tener el contenido, digamos, principal.
No hay un error muy típico también en semántica, que la gente pone el main aquí.
Puede ser, no pasa nada, ¿vale?
Puede ser.
Pero en este caso, si esto se supone que va a estar en todas las páginas...
A ver, no pasaría nada.
Yo creo que la prueba técnica se lo van a comer con patata.
Entonces, ya tenemos aquí el header y en el main aquí vamos a poner nuestras películas.
Por ahora no hay películas, ¿vale?
Pero yo qué sé, si lo queréis poner, pues aquí irán los resultados.
Al menos para que vayamos viendo un poquito cómo van saliendo aquí las cositas, ¿vale?
Así que aquí irán los resultados y tal.
Podemos hacer, yo qué sé, vamos a poner aquí, buscador de películas.
Para que se vea bien esto y podemos hacer un poquito de CSS.
No perdáis el tiempo con CSS, que no es lo que quieren ver muchas veces, a no ser que os lo digan, ¿vale?
Pero igualmente, este tipo de CSS, este que estamos haciendo aquí, es súper importante que lo sepáis hacer.
Porque si no, pues la vais a liar.
A ver, vamos a poner aquí...
Vamos a poner que esto es el class...
Page.
Vamos a poner page.page.display.flex.
Vamos a hacer que todo quede centrado.
Normalmente, todo lo que queda centrado, queda bien.
Así que lo ponemos todo centrado, ¿vale?
Justify, Content Center, ¿vale?
Items...
Hostia, Items...
Estaba pensando en...
Ah, no, ¿ves?
Estaba pensando en Tailwind, en Align Item Center, ¿vale?
Y luego de todo, también del formulario, vamos a centrarlo, por Align Item...
Estaba pensando en Tailwind y quería poner al Item Center, ¿vale?
Ya, más o menos.
No hace falta que sean los mejores estilos de tu vida.
Pero normalmente centrado, todo queda mejor.
Así que, bueno, aquí tienes un estilo rap.
¿Qué es lo que yo haría una vez que tenemos esto?
¿Qué es lo que yo haría una vez que ya tenemos esto?
Ah, y sí, he puesto class y esto es class name.
Gracias por avisar.
Y aquí también, ¿vale?
Una vez que tenemos esto, que al menos se ve algo, ¿qué es lo que yo haría?
Ya hemos hecho como esto, ¿no?
Necesitaba mostrar un input para buscar la película.
Check, ¿vale?
Check, check.
Yo ahora...
Dice lista de las películas encontradas y muestra el título, año y póster.
Importante aquí, ¿no?
Ya tenemos lista de las películas encontradas y muestra el título, año y póster.
Pero fijaos en una cosa que aquí, aquí un error muy común que hace la gente...
Os voy a decir cuál es.
Nos dicen la API.
Uno, tenemos que entrar a la API, tenemos que buscar, tenemos que entenderla.
Así que lo primero que tenemos que hacer antes de volvernos locos es ir a la página de la API.
Oye, y entender a ver qué es lo que hace, ¿vale?
Entonces, ¿qué necesitamos?
Vale, es crear una aplicación para buscar películas.
Pam.
Vale, buscar películas.
Así que, ¿qué tenemos que buscar?
Vale, tenemos que buscar la API que nos permita buscar.
¿Ok?
Súper importante.
O sea, antes de volvernos locos con la API, antes de escribir fetch, ¿vale?
Que muchas veces la gente se pone a escribir fetch y tal.
No.
Ve a la documentación.
Entiende la documentación y ten clarísimo cuál es el endpoint que tienes que utilizar antes de seguir.
Ya tenemos claro que es este, bySearch.
Y nos dice que tiene requerido el parámetro con la S.
Segunda cosa que vamos a querer hacer.
Bueno, vamos a intentar conseguir utilizar nuestra API.
Así que nos copiamos esto, por ejemplo.
Vale.
Y vais a ver.
Os voy a comentar un error muy común también, pero lo veremos después.
Por ahora, ten en cuenta que yo me he copiado justamente esta URL.
Me la he copiado.
Yo ya tengo una API key.
La API key que podéis conseguir.
Normalmente la prueba técnica os da una API key.
Pero esta API key la podéis conseguir.
Es totalmente gratis.
Y os la recomiendo para que practiquéis bastante.
Y además, para que no me petéis la mía.
Porque entonces nos vamos a quedar sin la posibilidad de hacer la prueba.
Entonces, ya he visto que necesitaba la query de la S.
Y pues yo aquí le vuelvo.
¿Vale?
Avenger.
Y aquí lo diferencial.
Lo diferencial.
Aquí ya estamos viendo cómo es el JSON.
¿Vale?
Bueno, aquí JSON formatter Chrome extension.
Voy a poner, voy a instalar una extensión para que lo veamos mejor.
El JSON.
Si no tenéis esta extensión, la recomiendo un montón.
En la vida.
¿Vale?
Porque así la podéis ver así.
Y la podéis seguir viendo de la otra forma.
Además, tiene dark mode.
Está súper bien.
¿Vale?
Bueno.
Entonces, ya veo cómo es el objeto.
Ya de esta forma me voy preparando.
Y digo, vale, ¿cómo es el objeto?
No empecéis importante.
Nunca os pongáis a utilizar console.log para ver cuál es la forma del objeto.
Que te conozco.
En una prueba técnica, mira la forma del objeto.
Y nunca, jamás, te pongas a hacer fetch continuamente para ver la forma del objeto.
No lo hagas.
¿Vale?
No lo hagas.
No lo hagas.
Es que queda, no solo queda mal, sino que queda raro.
Y estás mucho rato perdiendo tiempo.
¿Qué es lo que yo te recomiendo?
Hemos entrado aquí.
Hemos visto la respuesta.
Vas aquí al row.
Te copias la respuesta.
¿Vale?
Te copias la respuesta.
Y lo que haces es, te creas una carpeta y te pones aquí la respuesta.
Que, por ejemplo, le podríamos llamar, yo qué sé, withResults.json.
¿Vale?
Te lo pones aquí.
Si lo puedes formatear, lo formateas.
Que en este caso veo que no me lo formatea, no sé por qué.
Pero porque no tenéis formateador, normalmente te lo debería formatear.
Y lo dejas aquí.
Ya lo tienes.
Ya tienes el JSON.
Lo tienes en tu proyecto.
Ya no tienes que buscarme.
Otra cosa que te recomiendo es que también pienses en el caso de que no tengas resultados.
¿Vale?
Vamos a poner noResults.json.
Imagínate que buscamos aquí midudev.twitch.
Obviamente no tienes resultados, pero ya sabemos cuál es el objeto si no tienes resultados.
Esto que parece una tontería, te va a ahorrar una de tiempo mientras haces una prueba técnica en la que estás nervioso.
Y además, o sea, vas a ver que esto te da un montón de beneficios, como vamos a ver ahora.
¿Vale?
Súper importante que hagáis esto y no estás haciendo fetching constantemente.
Porque con esto, ahora, ya podemos empezar sin tirar y sin hacer un fetch.
Ya podríamos empezar a construir nuestra aplicación y enseñar cosas cuanto antes.
Imagínate que no tienes ese tiempo a hacer el fetch.
Pero es que al menos habrías construido tu aplicación, aunque sea con un mocking de datos.
Que el día de mañana se puede hacer el fetch, se puede hacer otra cosa e incluso lo puedes explicar.
Bueno, pero mi aplicación está hecha, o sea, lo cambia todo.
Que no, que si empiezas a hacer un fetching de datos, pasa una hora y media y se te queda así el proyecto.
Pues es diferente.
¿Vale?
Entonces, ¿por dónde vamos a tirar?
Ahora que ya tenemos esto, lo que podemos hacer, nos vamos aquí a la app.jsx.
Y fíjate que con esto ya podríamos decir, bueno, es que ya tengo las películas.
Porque tenemos aquí una con resultado, mocks barra withresults.json.
Y tardas nada y menos.
WithoutResults y WithResults.
O sea, que tú aquí ya con el WithResults ya podrías estilar esto.
Y lo mejor de todo, y esto es muy importante a la hora de ir bastante rápido, es que te va a chivar los tipos.
Y eso que no estamos citando TypeScript.
Pero como es un JSON, fíjate lo que pasa.
Imagínate que aquí lo vamos a llamar ResponseMovies.
Porque es lo que es, ¿no?
Vale, es ResponseMovies.
Muy bien.
Vamos a decir aquí que aquí irán los resultados.
¿Cuándo tenemos que mostrar los resultados?
Cuando tengamos películas.
¿Cuándo hemos visto que tenemos películas?
Pues tenemos películas.
Vamos a ver rápidamente.
¿Cuándo tenemos películas?
Cuando tenemos un Search y es un Array.
Porque aquí no tenemos Search y no es un Array.
Pues venga, vamos a sacar, por ejemplo, las Movies están en el ResponseMovies.search.
¿Y cuándo tiene películas?
Cuando Movie tiene el length mayor a 0.
Con esto ya tenemos al menos un poquito.
Y ya decimos, vale, HasMovies.
Lo ponemos aquí.
Y hacemos un renderizado condicional.
¿Tiene películas?
Bueno, pues si tiene películas, vamos a renderizar.
Y ahora te voy a explicar otra cosa súper importante.
Vamos a renderizar un UL.
¿Vale?
Una lista desordenada.
Y dentro de la lista desordenada, vamos a mapear.
Hacemos Movies, Map.
Mapeamos cada película.
Y vamos a renderizar para cada película la lista.
Importante, que no se nos olvide la aquí.
Movie.
Punto.
¿Qué ha pasado aquí?
Que cuando he puesto punto, me está diciendo los campos que tiene el JSON.
Cosa que no haría sin utilizar TypeScript.
Esto no lo tendrías de otra forma.
Fíjate que no he tenido que preocuparme en ningún momento de acordarme cómo era el objeto.
Porque ya me está diciendo cómo es el objeto.
Esto es diferencial a la hora de hacer una prueba técnica.
Porque hemos perdido cero segundos en saber cómo era el objeto.
No he tenido que hacer un fetch para revisarlo.
No he hecho ni un console.log para ver esto.
De verdad, amigos.
Esto es súper importante.
¿Vale?
Aquí.
Aquí.
Porque esto te acelera un montón en el desarrollo.
Todo lo que te acelere el desarrollo, especialmente en pruebas técnicas, marca la diferencia.
Así que, tenéis el JSON.
Empezáis con el JSON y no os preocupéis.
Ya haremos el fetch.
Vamos a tener tiempo para hacer el fetch.
Pero el fetch lo vamos a construir una vez que tengamos nuestra aplicación ya funcionando perfectamente.
¿Ok?
Trucazo.
Fíjate.
Ya, yo no tenía ni idea, ¿no?
O sea, que muy, pum.
Cuando he hecho el punto, ya tenía aquí IMDBID.
Ya sé que esa es la idea.
Y yo aquí, pues, puedo empezar otra vez a seguir.
Digo, vale.
H3.
Pues, venga.
Movie punto.
Vale.
Pues, aquí quiero el title.
Vestite mi, Duque.
¿Qué quiero?
Pues, el año.
Movie punto.
Mira.
Pues, el año es con mayúsculas.
Perfecto.
Pues, ya está.
¿Qué más quiero?
La imagen.
Pues, source.
Movie punto.
Fíjate.
Si tengo aquí el póster.
Buenísimo.
Y aquí, con el alt title.
Y ya está.
O sea, en un momento, pues, al menos ya estamos renderizando cositas.
Ahora, ¿qué es lo que tenemos que hacer?
Que si no tenemos resultados, pues, bueno.
Ponemos el, no se encontraron resultados o no se encontraron películas para esta búsqueda.
¿Vale?
Guardamos los cambios y, ¿cuánto hemos tardado?
¿Cuánto hemos tardado en enseñarle ya resultados?
Que no son resultados reales, pero esto ya lo que nos está permitiendo es, oye, no está mal.
Ya te he renderizado.
Bueno, básicamente, acabamos de renderizar todo lo que va a haber en toda la aplicación y no llevamos ni una hora.
O sea, ha sido súper rápido.
Súper rápido.
Lo que hemos hecho es, sin hacer grandes excedencias, tenemos todo lo que nos ha pedido mostrar.
Fijaos que nos lo estaba diciendo en el Ritmi.
Nos estaba diciendo, necesitas mostrar un input para buscar la película y un botón para buscar.
Vale.
Es verdad, todavía no le hemos dado la funcionalidad.
Pero tenemos la aplicación.
A partir de aquí, podemos construir la funcionalidad.
Lista las películas encontradas y muestra el título de año y póster.
Pues aquí lo tienes.
O sea, check.
Obviamente, no son las encontradas.
Estamos listando las películas y podemos hacer que el formulario funcione.
Bueno, pero lo hemos separado.
¿Vale?
No nos hemos vuelto locos.
Lo hemos separado.
¿Ok?
Venga.
Os leo.
Por si tenéis alguna duda por aquí, que ahora os voy a comentar también una cosa muy importante
sobre lo que hemos hecho.
De lo hemos hecho mal.
Lo vamos a refactorizar si hace falta.
Si hace falta.
Yo os voy a explicar cómo hacerlo mejor.
¿Es mejor usar el índice de las películas que te da la API o mejor el índice?
Lo mejor es la ID de la API.
No es lo mejor.
Es lo correcto.
El índice está mal.
De hecho, luego lo vas a ver porque está mal.
Recuérdame cuando hagamos el short, que vamos a hacer un short.
Recuérdame eso.
Y vas a ver por qué está mal utilizar el índice de un array.
Está mal.
Normalmente está.
¿Vale?
Bueno, ya tenemos aquí resultados pintados.
Pero, a ver.
Yo te voy a comentar cómo yo lo haría.
Pero, ¿cómo es?
¿Regular?
¿Un poquito mejor?
¿Y cómo está bien?
Esto que hemos hecho aquí, a mí no me gusta normalmente.
¿Por qué?
Hemos puesto una ternaria.
Es como un poco complicado.
Entonces, hay mucha gente que hace, por ejemplo, render movies.
Aquí sacaría en una función este render movies.
Y te voy a explicar por qué esto.
Si eres junior, no pasa nada.
Pero te quiero explicar cómo se hace bien esto.
Porque esto, yo casi que te diría que es una mala práctica.
Esto lo hace muchísima gente.
¿Vale?
Hace esto.
Y es verdad que al menos es mal legible.
O sea, esto al menos lo podríamos sacar aquí.
Hacemos render movie.
¿Vale?
Y podríamos sacar esto también.
Podríamos render no resolve.
Esto es una mala práctica que hacen mucha gente, muchas empresas, en cualquier sitio.
¿Y por qué lo hacen?
Porque, bueno, es muy rápido, ¿no?
Se hace súper rápido.
Lo haces aquí, pim, pam.
Y, bueno, pues ya lo tienes arreglado.
Y es verdad, es verdad que sigue funcionando.
Es mal legible.
Y ya lo tienes aquí.
Pero, ¿por qué es una mala práctica?
A ver, que alguien me diga.
¿Por qué es una mala práctica?
A ver si alguien lo sabe.
Muy bien.
El primero.
Eizen.
Muy bien.
Esto debería ser un componente.
Cualquier función, cualquier método que veas que se llama render lo que sea.
Y justamente lo que hace es renderizar como un componente, esto debería ser un componente.
Lo mejor es que fuese un componente.
Hay un montón de motivos por los que debería ser un componente, ¿vale?
No me da tiempo explicártelos todos, pero uno de los más importantes es justamente que es más óptimo.
Si al ser un componente, esto no se va a volver a crear cada vez que se renderiza la aplicación.
Si no, estas funciones, lo veremos más adelante y lo vas a entender mucho más claro,
estas funciones, cada vez que se renderiza la app, se vuelven a crear.
¿Vale?
Además de esto, ¿qué pasa?
Si el día de mañana a Movies quieres pasarle una prop o lo que sea, va a ser mucho más beneficioso
y además lo puedes utilizar fuera de este componente.
O sea, son todo beneficios y son todo ventajas.
Normalmente un método se llama renderMovies y hace justamente esto, debería ser un componente.
Vamos a crear nosotros una carpeta components y yo voy a poner aquí movies.jsx y aquí vamos a poner un poco de todo, ¿vale?
Todo lo que tenga que ver con Movies por poner algo.
Vamos a ponerlo aquí.
Vamos a tener por aquí, por ejemplo, list of Movies.
A mí me gusta utilizar en el cuerpo de la función, o sea, en el cuerpo del fichero, me gusta utilizar function.
Si a ti te gusta la constante, pues oye, déjala.
Y aquí le podemos pasar justamente las Movies y ya está.
Con esto funciona la idea bien.
Y aquí, pues lo mismo, ¿no?
Export function, pues no Movies Resort.
¿Vale?
Le ponemos esto, le quitamos esto por aquí.
Si le quieres dejar el const, déjalo, que no hay ningún problema.
Incluso una cosa bastante interesante que puedes hacer es, en lugar de exportarlas, lo que podrías hacer es exportar la función que haga esta lógica de aquí.
O sea, esta lógica que parece una tontería, al final puede ser export function Movies y así ya te olvidas a nivel de aplicación tener que hacer esta lógica.
Ya la dejas aquí con el HasMovies.
Lo dejamos así.
Esto lo movemos aquí y ya.
Aquí, en lugar de Movies, pues vamos a triar con Movies, Movies, Movies.
¿Vale?
El componente Movies le pasamos los Movies.
Y aquí, si no tenemos, pues no Movies Resort.
Este HasMovies es este cálculo que estamos haciendo aquí.
También lo podríamos pasar.
Así que lo ponemos por aquí.
Pam, pam, pam.
Y ahora lo que tenemos que mirar es, bueno, y de dónde sacamos esto del Movies, Responsive Movies y tal.
Una cosa que podemos hacer, mira, esto ya lo dejamos así, Movies.
¿Vale?
Fíjate que en realidad este Response Movies, esto lo podríamos sacar del componente Movies.
O sea, en lugar de a nivel de aplicación que tenga todo esto, lo podríamos sacar.
Tienes diferentes formas de hacerlo.
Hazlo como tú quieras.
Entonces, yo en este caso, como para simplificar y no tener que tocar muchos componentes,
se lo vamos a pasar esto por Props, ¿vale?
De forma que estos Movies, sea el Responsive Movies tal, esto lo vamos a dejar así.
Y esta lógica sí que la tenga aquí, ¿vale?
Como la lógica de decidir qué componente es el que va a tener que renderizar, se la vamos a dejar aquí.
Y que sea aquí la que haga solo esta parte de aquí.
Porque, total, esto es bastante fácil y lo podemos dejar aquí.
Y esto lo haremos también en otro sitio.
Así que, al menos, de esta forma, lo vamos a dejar así.
Vamos a ver también...
A ver, hay alguna cosita que no le ha gustado.
Has Movies, Movies...
Porque no se encontraban películas para esta búsqueda.
Ah, vale.
Espérate.
El List of Movies este, este va aquí, ¿vale?
Que la había llamado Movies y es listo.
Y luego aquí, en el Has Movies...
Aquí le estamos pasando Movies, Movies...
Ta, ta, ta...
Espérate.
Porque le falta...
Uy, se ha quedado penchado.
Que se me ha quedado penchado la cosa esta, ¿no?
A ver.
No sé si es que Vite se ha ido también la...
Se ha quedado, ¿veis?
Ahora funciona bien.
Se había quedado como penchado, ¿no?
Se había quedado como pensando alguna cosa.
Vale.
Ya está.
Pues ya está.
Ya lo tenemos funcionando.
Voy a dejar este Without Results por si lo queremos ver.
Porque también es interesante.
Fíjate que lo interesante de esto es que...
Si le pones aquí el Without Results...
Eh...
Bueno.
Lo podríamos cambiar después.
Lo podemos cambiar.
Luego os enseño.
Para ir probando si se renderiza o no se renderiza.
¿Vale?
A mí me pasa es una entrevista y me pongo a llorar.
No, hombre.
Tampoco hay que llorar, joder.
Mientras se entienda más o menos, pues ya está.
A ver.
Esto sería la forma...
Os digo una cosa.
Esto que hemos hecho es porque os quería explicar cómo sería la forma más correcta.
¿Vale?
La forma en la que habría que separarlo con...
Habría que separarlo en componentes.
Pero como en una prueba técnica si el tiempo es el que es...
Pues a lo mejor lo hubiera dejado como lo hemos visto al principio.
¿Vale?
Eso es lo que os diría.
Pues ahora que ya tenemos esto, una cosa que también podemos hacer en este punto, justamente para tener que evitar todo esto.
Os voy a explicar otra mala práctica que muchas veces se hace ya a nivel fuera de prueba técnica, pero que si lo queréis tener en cuenta también os puede ayudar.
A ver.
Esto normalmente, esto de movie.title, year, poster...
Esto que hemos hecho aquí...
A ver.
¿Alguien me puede decir por qué es una mala práctica?
¿Por qué esto que hemos hecho aquí del movie.title, que tiene aquí title en mayúscula, el punto year, de estructuración?
No es por la estructuración, porque puede variar, dice Jesper, por las mayúsculas.
A ver.
Lo que os diría, lo peor, lo peor de esto, en realidad, es que estamos utilizando el contrato de la API.
Estamos utilizando como el contrato de la API dentro de nuestro componente.
Entonces, es como que este componente, list of movies, está, tal y como lo tenemos, está atado a cómo funciona nuestra API.
Y está como en la parte de la UI.
O sea, que está como muy introducido dentro de nuestra aplicación.
Deberíamos evitar que esto ocurriese.
Lo mejor que se suele hacer en estos casos sería, pues una vez que tienen movies, sería hacer algo así.
Mapped movies.
Esto lo sacaremos de aquí, pero ahora mismo para que os hagáis una idea.
Lo mejor que se puede hacer en estos casos muchas veces es mapear desde un punto y evitar que en un componente muy profundo utilice el contrato de la API.
Porque imagínate que el día de mañana quieres cambiar la API.
Si tú has estado utilizando el contrato de la API en todos los sitios, te va a ser muy costoso justamente después cambiar.
Entonces, una cosa que puedes hacer, ahora lo vamos a hacer aquí, luego lo sacaremos de aquí porque tendrá más sentido.
Vamos a hacer un mapeo de datos, ¿no?
Vamos a mapear los datos de las movies.
Lo vamos a meter en esta constante, le llamamos Mapped Movies, como le puedes llamar, como tú quieras.
Y que sean estos Mapping Movies los que les pasamos aquí.
Entonces, esto ya lo estamos controlando nosotros.
Si esto por lo que sea luego cambia, lo estamos controlando desde un solo sitio.
Y aquí ahora ya sabríamos que podemos utilizar el id, el title, el year y no sé cómo lo he puesto aquí.
Title y el poster.
Alguien dirá, bueno, pero lo único que has hecho es ponerlo en minúscula.
No es simplemente eso.
¿Por qué?
Porque esto en realidad lo podríamos sacar a un archivo totalmente aparte.
Y esto es solo este código es el que decide cómo se hace la transformación de estos datos que vienen de la API.
Si cambiamos de API, solo tendremos que cambiarlo en un solo sitio.
En lugar de tenerlo en todos nuestros componentes constantemente que se refieran, como lo decía la API,
que si cambia la API vamos a volvernos locos, ¿vale?
Así que esto es una cosa que te comento más que nada para que lo sepas.
Y de hecho, vamos a hacer otra cosa.
Vamos a sacar esto en un custom hook.
Le vamos a llamar export function use movie.
Y esto va a ser también uno de los beneficios que tenemos con los custom hooks.
Porque vamos a hacer un custom hook que es el que se preocupe de hacer todo el fetching de datos de la película, el estado y todo eso.
Así que esto que es lo que estamos decidiendo que se hacía aquí, lo vamos a sacar.
Y aquí vamos a retornar movies, como mapeed movies.
Y así podemos utilizar ya, como si fuese una caja negra, este custom hook, el de use movies.
Y ahora no tenemos que preocuparnos de lo que está haciendo por dentro.
Que si mapea los datos, que se hace un fetching, que se hace un import.
Para dejarlo todavía más claro, lo vamos a sacar aquí en hooks.
Vamos a crear aquí el use movies.js y vamos a sacarlo de aquí, porque ya no tiene sentido que esté aquí.
Así lo dejamos.
Y ahora aquí podemos sacar esto, que son los json que teníamos, ¿vale?
Exportamos el use movies y así tenemos el custom hook.
Ya tenemos el custom hook.
Lo importamos y ya lo utilizamos.
¿Vale?
A ver, ah, tenemos que cambiar aquí el punto a punto.
¿Vale?
Porque ha cambiado los paths relativos.
Todo sigue funcionando bien, no hay ningún problema.
Lo interesante que estamos haciendo aquí es que ahora ya nuestra aplicación es totalmente agnóstico a qué estamos haciendo aquí dentro.
Entonces podemos empezar a trabajar en el use movies sin necesidad de tocar todo lo que estamos haciendo aquí en la aplicación.
¿Vale?
Esto sería un poco, pues si queremos separar, si queremos hacer cualquier...
Midu, comienzo las prácticas de FP superior en un mes de nervioso por el nivel.
Estoy tratando de aprender RIA para llegar con el mayor bagaje posible.
¿Qué me recomiendas de cara a unas prácticas de FP superior en Frontend?
Que muevas las manitas, que estudies.
Eso es lo que te diría.
Que estudies, ¿qué te puedo recomendar?
Que estudies mucho, que practiques y cuanto más practiques, pues mejor preparado llegarás.
Ya queda encapsulado para cuando se haga el fetch.
Ahí está.
¿Es mala práctica usar clases para realizar un mapeo?
Hombre, no es mala práctica, pero creo que puede ser innecesario.
Midu, ¿por qué no usas const para declarar las funciones?
Utilizad lo que os dé la gana.
Podéis utilizar const, podéis utilizar funciones.
A mí me gusta en el cuerpo de los archivos utilizar funciones porque se lee mucho mejor.
Cuando tú utilizas un const aquí, que es que no sé por qué me preguntáis tantas veces esto,
como si fuese algo tan importante y la verdad es que qué más da.
A ver, esto, el problema que tiene para mí visualmente es que esto es una constante
y aquí también tiene una constante.
Y visualmente cuesta como un poco más.
A mí me gusta que en el cuerpo de la función se puede utilizar function para justamente lo que es,
que es una función, pues ya está.
Utilizo function y queda como mejor visualmente, donde se separa lo que es la función con las constantes.
A mí me gusta.
Si te gusta más el const, utiliza el const.
No a ningún punto.
En useMovies, mapeMovies no está de más.
Es un archivo ya retorna así, creo.
No, no retorna así porque lo que estamos haciendo aquí es transformar, mapear los arrays
y lo estamos pasando de mayúsculas a minúsculas.
Pero imagina que aquí en lugar de póster ponemos image, por decir algo.
Pues ya está, o sea, estaríamos haciendo otro mapeo y ya está.
O sea, ese es el tema, ¿vale?
Hola, Midu, también gusta así.
Claro.
Midu, ¿cómo se haría para existir una URL que no sea los que tengo definida y no se muestra un componente?
No lo sé, pero ahora no lo vamos a ver.
¿Por qué el const?
Si no sería lo mismo hacer un const Movies.
A ver, ¿qué hemos hecho aquí?
Ay, perdón.
Aquí es porque he hecho esto porque aquí estamos utilizando el MuppetMovies.
Pero a ver, podríamos quitar esto y aquí entonces cambiar Movies.
Es lo mismo, ¿no?
Sería lo mismo.
Sería lo mismo, ¿no?
En pruebas técnicas deberíamos contar lo que hacemos para que el examinador entienda nuestra lógica.
Si podéis, sí.
Es una buena práctica que mientras vais pensando, vayáis hablando.
Cuanto más contexto le dais al entrevistador o entrevistadora de lo que estáis haciendo,
por qué lo estáis haciendo, por ejemplo, imagínate que no os da tiempo a hacer algo.
Oye, está bien comentar.
Oye, igual, si tuviese más tiempo, esto le separaría en un componente, pero voy a enfocarme en terminar la prueba y si me da tiempo luego lo hago.
Estas cosas suman puntos porque si te callas es imposible que sepa leerte la mente, ¿entiendes?
Entonces, es buena práctica que yo creo que si sois capaces de hablar mientras...
Mira, os voy a decir un buen ejercicio que podéis hacer.
Que hagáis pruebas técnicas con amigos, amigas, compañeros, compañeras y que mientras lo hacéis lo expliquéis.
Es una cosa que cuesta de dominar, pero fijaos, yo ahora, pues mientras voy hablando, pues os lo voy diciendo.
Pero es una buena práctica que mientras lo vais explicando, pues que lo vais haciendo.
Y esto se lo podéis hacer con amigos, compañeros.
Os podéis ir turnando, por ejemplo, empezar alguien la prueba técnica, luego la sigue otra persona.
Así que es súper interesante.
Súper interesante que eso lo practiquéis, pues que es una buena práctica.
Vale, si no tengo amigos, un patito.
Bueno, si no, pues en el Discord, hombre, hay un montón de gente.
Vale, pues venga, vamos a darle un amigo imaginario sirve total.
Bueno, obviamente hemos llegado hasta aquí a nuestra prueba técnica, que no está mal, ¿no?
Pero en el Ritmi nos dice que el formulario funcione.
Y nuestro formulario no funciona.
Vamos a hacer que funcione y entonces te voy a explicar cómo puedes manejar formularios en React.
Cómo puedes utilizar un nuevo hook que te voy a presentar ahora.
Y además la diferencia de cómo se puede manejar un formulario en React, porque hay dos formas.
Controlada y no controlada.
Así que vamos a verlas, ¿vale?
Lo primero, voy a presentarte un nuevo hook.
Y te voy a dar la explicación mala, que es la que da todo el mundo, y la explicación buena, ¿ok?
El nuevo hook que te quiero presentar se llama useRef.
¿Para qué sirve yourRef?
La explicación mala, que es la que dice todo el mundo, es useRef te permite crear una referencia a un elemento del DOM.
Esa es la explicación mala, porque además de que es sesgada y es incompleta, no es cierto del todo.
O sea, es cierto, pero no sirve para eso.
No es que... no.
Esa es una explicación un poco incompleta.
UseRef es un hook que te permite crear una referencia mutable que persiste durante todo el ciclo de vida de tu componente.
Y lo que es mejor, que es muy útil para guardar cualquier valor que puedas mutar, como un identificador, como un elemento del DOM, como un contador, como lo que tú quieras.
Y que cada vez que cambia, no vuelve a renderizar el componente.
Y eso es lo que lo hace totalmente diferente al useState.
Porque el useState, cada vez que cambia, se vuelve a renderizar el componente.
Pero el useRef, cada vez que cambia, no renderiza el componente otra vez.
No dispara un nuevo renderizado.
Así que es útil para todo esto.
O sea, crea una referencia mutable, y luego veremos lo que es, qué significa mutable y tal,
que persiste en todo el ciclo de vida del componente.
O sea, ¿qué significa que persiste?
Pues que su valor no es reiniciado, no se reinicia.
Por ejemplo, si yo pongo aquí let igual a 1, y yo voy poniendo aquí i++, ¿vale?
Imagínate esto, ¿no?
i++, y aquí ponemos console.log1, console.log i, y aquí, pues, miramos en la consola.
Vamos a mirar en la consola qué es lo que sale de esto.
Vamos a la consola, ¿vale?
Claro, el problema es que esto no se vuelve a renderizar.
Esto no se vuelve a renderizar.
Bueno, luego lo podríamos ver.
Pero veríamos que cada vez que se renderiza nuestro componente,
i sigue siendo 1, porque se vuelve a reiniciar.
Esta variable no es una referencia constante y persiste durante todo el ciclo de vida,
sino que se reinicia en cada renderizado.
El urref nos va a permitir crear un valor que persista entre renderizados.
Y esa es la diferencia importantísima que tiene con el useState,
porque el useState, cuando cambia su valor, vuelve a renderizar,
en cambio, el urref puede cambiar su valor y no vuelve a renderizar.
Y también es útil para guardar referencias de un elemento del DOM.
¿Por qué?
Porque va a persistir esa referencia, va a obtener una vez ese elemento,
y siempre que queramos utilizar ese elemento del DOM en nuestro componente,
lo vamos a poder utilizar.
Así que, súper importante, porque no es solo y simplemente para crear una referencia
de un elemento del DOM, sino que nos permite eso y muchas otras cosas.
Como vamos a ver hoy.
Hoy lo vais a ver que hay un montón de ejemplos de para qué utilizar el urref.
Vamos a utilizar el más típico, que es utilizarlo para guardar una referencia del DOM.
¿Cómo se utiliza?
Pues diríamos un useRef, lo utilizamos así.
Aquí tendríamos el valor inicial, en este caso lo vamos a pasar vacío.
Y aquí estaríamos guardando el inputRef.
¿De dónde queremos guardar este inputRef?
Pues de este input.
Vamos a hacer aquí, vamos a tener aquí la referencia de este input,
lo vamos a poner aquí, ¿vale?
InputRef.
Y lo que podemos hacer ahora es que en este botón vamos a poner que cada vez que se haga un clic,
vamos a poner aquí una constante con el handleClick y vamos a sacar el valor de la referencia
y fíjate que tenemos que acceder a la propiedad current.
Tenemos que acceder a la propiedad current.
Esto es una cosa que es nativa de React.
Esto lo está haciendo React porque cada vez que tú intentas acceder a una referencia,
siempre tienes que acceder al valor desde la propiedad current.
Y esto es porque al ser un objeto puede mutar, puede cambiar el valor de value
sin necesidad de que lo tenga que volver a reasignar.
O sea, lo que está haciendo aquí, el truco, es que está creando un objeto
que simplemente desde el current tú lo que vas a cambiar siempre es lo que viene después.
O sea, que tienes inputRef.current y ahí es donde teníamos justamente la referencia de este input.
¿Vale?
Aquí, esto, hasta aquí, esto sería el input, para que lo veamos claro.
InputRef.current.
Este sería el inputElement.
Y para recuperar el valor de un input, pues al elementor accedemos al value.
Esto es vanilla JavaScript.
Esto no tiene que ver con React.
Esto es una cosa muy básica que deberías saber del DOM.
Pero bueno, lo que estamos haciendo es recuperar el elemento del DOM así
en lugar de hacer lo típico del query selector y todo.
Ahora, cada vez que hagamos un clic, deberíamos ver que si yo hago aquí Avengers, por ejemplo.
Hostia, se ha quedado esto.
Y le doy a buscar.
Fíjate que le doy a ven y cuando le doy a buscar, aquí rápidamente aparece aven.
Bien, pero no lo vamos a ver con tiempo.
Así que voy a poner un alert y ahora te explicaré por qué pasa esto.
Ponemos el alert.
¿Vale?
Vamos a poner aquí matrix.
Car.
¿Ves?
Y ya tenemos aquí nuestro mat.
Lo que estamos haciendo es recuperar el elemento del DOM y lo estamos leyendo.
Y lo estamos guardando en una referencia.
Para eso estamos utilizando el UREF, pero luego lo utilizaremos para otras cosas también muy interesantes.
Ahora, ¿cómo podemos hacer mejor esto?
Porque ya veis que nos pasa que el formulario está haciendo el submit, que bueno, esto tiene arreglo.
Primero, una buena práctica normalmente es que si tenemos un formulario, eso, siempre que pongas el input y el button, utiliza un formulario.
¿Vale?
Tiene sentido que utilices un formulario porque los formularios justamente lo que nos permiten es englobar todos nuestros inputs y determinar toda la información que tienes.
Así que vamos a poner en lugar de un handle click, lo mejor es que pongas un handle zoom.
Aunque el handle click, como lo hemos puesto en el botón que es del tipo submit, va a funcionar con el teclado.
O sea, si yo pongo Avengers y le doy al enter, ¿ves? Funciona igual que si le diese con el mouse.
Pero normalmente lo mejor es que en el formulario, como vamos a tener que hacer un prevent default y tal, en lugar de leer o escuchar el evento de click, lo que puedes hacer aquí es que tengamos el on submit.
Además de que visualmente lo vas a ver mucho más fácil que no, te quieres buscar en el on click, vas a ver que tienes otras ventajas que te va a permitir recuperar toda la información mucho más fácil.
Así que en el submit vamos a poner el handle submit, vamos a crear el on click este, ¿vale?
Y ahora en el handle submit, vamos a llamar handle submit, vamos a poner aquí event, event, prevent, prevent, default, ¿vale?
Para evitar el comportamiento por dentro.
Ahora podemos poner aquí el console log del value, ¿vale?
Guardamos esto, vamos a poner Avengers y al enter, ¿vale?
Y ya tenemos aquí el console log que justamente, ¿vale?
Esto no está mal, pero te voy a contar otra cosa que es bastante importante.
Hay mucha gente que abusa, abusa de esto, ¿no?
Y empieza a poner referencias de sus inputs aquí como si no hubieran mañana.
Esto sin utilizar dependencias.
Si utilizas dependencias hay un montón de dependencias que te facilitan esto mucho la vida.
Pero hay muchas veces que ni siquiera necesitas y de hecho yo te recomendaría si fuese una prueba técnica de que lo hiciese de otra forma.
Porque hay una forma muy sencilla que puedes recuperar esta información sin necesidad de utilizar este hook de una forma nativa, sencilla, rápida.
¿Y cómo lo haríamos? En lugar de utilizar la referencia del input que tenemos por aquí, no utilizaríamos la referencia.
Y fíjate que aquí tenemos el evento del submit.
Esto es una cosa que es básica también de JavaScript, que no sé por qué no lo explican en la escuela.
Pero cuando tenemos aquí el evento de un formulario que se hace submit, puedes recuperar todos los datos que tiene ese formulario.
En este input, por ejemplo, para poder recuperar este input tendríamos que ponerle un nombre, que también es buena idea ponerle un nombre.
Vamos a poner aquí query, por ejemplo.
Y aquí en este evento tendríamos la posibilidad de recuperar todos los datos.
¿Cómo lo hacíamos? Pues hacemos un new form data y esto lo hacemos justamente del formulario.
Event.target. Target porque es este evento el que lo está recibiendo, es este target, que es el propio formulario.
Así que no tenemos que crear ninguna referencia.
En este data lo que podemos hacer, o data o fields, como le quieras llamar, o input.
Vamos a ponerle fields.
En este fields podemos recuperar la query, súper fácil.
Fields.get, le decimos el nombre que tiene el input.
Y ahora con esto ya tendríamos la query.
¿Por qué te explico esto?
Bueno, esto vamos a poner el window.
¿Por qué te explico esto?
Porque muchas veces, mucha gente aprende React, pero no aprende Java.
Y hay muchas veces que aprendiendo JavaScript en realidad te facilita mucho la vida.
Esto es mucho más portable, no dependes de React, es mucho más rápido, no tienes que utilizar el hook.
Claro, lo tienes que conocer.
O sea, y tiene un montón de ventajas porque imagínate que tuvieras 10 inputs.
Si tuvieras 10 inputs, si tuvieras que utilizar 10 referencias, te ibas a volver tarumba.
Así que no lo harías.
De hecho, si tuvieras 10 inputs, una forma que podríamos recuperar todo de golpe, simplemente con este fields, igual que hacemos este new form data, no sé qué, lo que podríamos hacer es transformar todos los campos.
Con el object from entry, le pasaríamos esto y ahí tendríamos los fields y aquí podríamos recuperar directamente la query.
Y aquí también tendríamos la query.
Imagínate, mira, para que lo veas clarísimo, si ahora ponemos aquí, yo que sé, wick, ¿ves? La query es wick.
Imagínate que ahora utilizas otro input, otro, ¿vale?
Y aquí tenemos wick y aquí john.
Y le das a buscar, espérate, ah, claro, es que solo estoy haciendo, mira, vamos a poner aquí todos los fields para que lo veas clarísimo, ¿vale?
Y esto lo que te va a crear es un objeto con todo, wick, john, ¿ves?
Ya tenemos wick, john, el otro.
Y aquí podrías estar haciendo inputs como si me hubieran mañana, ¿vale?
Como si me hubieran mañana y ya los podrías recuperar sin necesidad de hacer ninguna referencia, sin hacer absolutamente nada, ¿vale?
Todos estos, le das al enter y ya tienes un objeto aquí con toda la información del formulario.
Hay muchas veces, muchas veces, esto lo enseña en preescolar.
Polémico, Juliox, polémico, polémico, ¿eh?
Porque la verdad, muchas veces yo creo que he visto muchos códigos que hay 15 uref para poder leer todos los campos.
Todos los campos.
Así que, bueno, si me dice que a ti no se ha enseñado en preescolar, perfecto.
A la gente que no lo sabía, pues nada, genial, mejor que hayáis aprendido algo nuevo.
Obviamente, si lo sabíais, pues genial, si no, pues ya lo tengo.
Bueno, dicho esto, vamos a poner aquí, vamos a recuperar el query, que es el que nos interesa, ¿vale?
Lo ponemos aquí el query.
Además, aquí, en este punto, podríais intentar hacer todo tipo de validaciones.
O sea, podríais poner, si la query, por ejemplo, la query es diferente a vacío o si es lo que sea,
si es vacío, pues podríamos hacer aquí un retum para no hacer nada o podríamos incluso setear un error.
Podríamos hacer set error, no se ingresó ninguna película, lo que sea.
Aquí podríais hacer las validaciones que necesitan.
Todo lo que hemos visto, todo lo que hemos visto hasta ahora, hemos estado utilizando más el DOM que no React, ¿no?
O sea, para hacer esto, voy a quitar todos estos inputs, estamos utilizando más el DOM, el árbol de elementos del DOM,
que esto, pues es bastante básico de JavaScript, que muchas veces, pues mucha gente, pues dice,
no, yo quiero aprender React y se salta estas cosas, pero no hay, no hay, no hay atajos, ¿vale?
No hay atajos.
Así que no hagáis atajos porque entonces luego lo pagaréis en algún momento.
Entonces, todo lo que hemos hecho hasta ahora es gestionar el formulario, pero lo estamos haciendo de forma que se dice descontrolada o no controlada.
O sea, esto es que estamos gestionando el formulario a través del DOM.
Lo estamos haciendo directamente desde el árbol de elementos.
O sea, estamos confiando que el DOM va a tener la información, vamos a acceder con el UREF, eso sería no controlada,
o estamos aquí a partir del evento, pues estamos leyendo la información.
O sea, esto es una forma no controlada.
Lo bueno de la forma controlada es la forma más sencilla y la forma más óptima.
Es la forma más óptima, va súper rápido.
Muchas veces, muchas dependencias, normalmente, mi recomendación sería utilizarla de forma no controlada.
Pero existe otro concepto, que es utilizarla de forma controlada.
La forma controlada lo que quiere decir es que React va a controlar qué es lo que se escribe en nuestros inputs,
cómo lo hace, cuándo vamos a validarlo, y esto lo hacemos gracias al estado.
Vamos a crear un estado para tener el control de lo que se está dibujando en el input.
Así que vamos a crear el estado para que veamos la forma controlada.
Creamos un estado y en el estado vamos a tener la query.
Query, setQuery, ¿vale?
Y aquí tenemos el state.
Para hacer que sea de forma controlada, lo que vamos a tener aquí en el input,
le vamos a pasar el value y le vamos a pasar la query.
Y el setQuery va a cambiar cada vez que el input cambie.
O sea, que cada vez que tengamos un onChange, vamos a tener aquí handleChange.
Creamos un nuevo método aquí, handleChange.
Y aquí tendríamos también el evento, el event.
Y vamos a tener setQuery, event.target, porque es el input que ha recibido el evento, punto value.
O sea, estamos guardando cada vez que recibimos un cambio aquí.
En el onChange, lo que estamos haciendo es actualizar el estado.
El estado se actualiza y cuando se actualiza es lo que vamos a ver en el input.
Eso es lo que estamos haciendo, controlar justamente en el estado cómo funciona.
Ahora, vas a ver que aquí, ves, esto funciona perfectamente.
Parece que no hay ningún cambio.
Le damos a submit y aquí todavía esto ya no hace falta que hagamos esto.
¿Por qué?
Porque sacamos aquí del console.log de la query que tenemos en el estado.
Aquí deberíamos tener el valor que tiene el input.
Exactamente el mismo.
Así que refrescamos, ponemos aquí Avengers, ¿vale?
Y ya tenemos aquí la query de los Avengers.
Esta es la forma controlada.
Controlada porque React está controlando, porque hemos creado un estado para esto.
Y esto tiene desventajas porque obviamente esto hace que sea mucho más lento
porque cada vez que se actualiza el input vais a ver que vamos a tener un render.
Si yo pongo un console.log aquí de render, fíjate que cada vez que cambia el input
vamos a ver aquí un nuevo render.
Vamos a ver.
Pam, pam, pam, pam.
¿Ves?
Se está renderizando cada vez, cada vez que estamos cambiando cada uno de los textos.
Esto sin nuestra aplicación.
Ánimo mío, te queremos.
No pagues a los trolls.
Podría ocurrir que el input se sintiese lento.
Esto tiene alguna forma de arreglarlo.
Más adelante veremos un hook que te pueda ayudar con esto.
Pero aún así, lo más ideal es evitarlo directamente.
Y la forma no controlada, ya hemos visto que esto no es un problema.
Pero claro, ¿cuál es la ventaja que tiene?
Que te puede ayudar a simplificar la validación de formularios.
De la forma no controlada, puedes verificar formularios perfectamente.
O sea, no es imposible.
Pero es verdad que de forma controlada tienes un montón de posibilidades a la hora de validar el formulario
y tener el código un poquito más recogido y no tener que preocuparte tanto de depender del DOM
para hacer este tipo de validaciones.
Pero aún así, yo lo he hecho muchas veces.
De forma no controlada, validaciones sin ningún problema.
Pero bueno, te explico cómo podríamos validar, por ejemplo, el formulario de forma controlada.
Podríamos tener un efecto, por ejemplo, y aquí lo que podemos hacer es que detecte
que cada vez que cambia el search, vamos a ver qué es lo que ocurre.
Fíjate que lo puedes hacer de dos formas.
Podríamos hacer en setQuery aquí, podríamos hacer aquí la validación, validación,
o lo puedes hacer con un efecto.
Lo vamos a hacer de las dos formas para que lo veas,
pero por ahora lo vamos a hacer con el efecto para que veas cuál es la idea también del efecto otra vez.
Tener la query, imagínate aquí.
Podríamos decir, si la query es vacía, entonces vamos a tener un estado con el error,
setError, useState, vamos a ponerle null por defecto.
Si esto está vacío, pues setError y decimos no se puede buscar una película vacía.
Y aquí hacemos un red para que no siga ejecutado.
¿Qué más tendríamos aquí?
Pues si query.match, y aquí podríamos poner un poco de reggae.
Bueno, Avengers, no se puede buscar la película Avengers, eso sería buenísimo.
Le podemos decir que si no, si empieza, vale, si es decimal, si todo lo que se hace son números,
le decimos no se puede buscar una película con un número.
¿Qué más podríamos decirle?
Si es más pequeño que 3, la búsqueda debe tener al menos 3 caracteres.
Podríamos estar así todo el día, ¿vale?
Podríamos poner aquí todas las validaciones que queramos.
Esto para que entiendas un poco cómo funciona React.
Obviamente hay un montón de dependencias y tal que te puede facilitar esto.
Hay una que está muy chula, que es de bastante bajo nivel, que se llama Zot,
que te recomiendo que le eches un vistazo.
Va a hacer este tipo de validaciones.
Igual más adelante la vemos.
Pero bueno, esto para que veamos un poco cómo sería lo del formulario.
Y ya está.
Sí, lo que podríamos enseñar aquí es el error.
Vamos a poner aquí el error.
Ponemos el class name del error.
Bueno, no vamos a poner ni el class name, vamos a ponerle el style,
para que quede de color rojo y que al menos pegamos ahí el error.
¿Vale?
¿Ves?
Como ahora está vacío, dice, no se puede buscar una película vacía.
Si tú vas escribiendo, la búsqueda debe tener al menos tres carácteres.
Puedes ir escribiendo y va cambiando.
Puedes ir cambiando y ya está.
Lo bueno que estamos controlando estas validaciones las estamos haciendo aquí.
Esto mismo, y de hecho no sería mala idea, que las podríamos tener aquí también.
Directamente cada vez que cambie podríamos hacer esto.
Incluso, incluso, Avengers, ¿ves?
Funcionaría exactamente igual.
¿Por qué?
Porque es justamente aquí donde estamos haciendo justamente el cambio de ese query.
Lo único que hay que tener en cuenta aquí es que esto podría llegar tarde.
¿Qué quiere decir?
Que aquí estamos tirando del estado.
Y este estado que dijimos en una clase, que es asíncrono.
Por lo tanto, aquí en realidad lo que deberíamos tener que chequear...
Bueno, fíjate, para que veas el error.
Para que veas el error.
No se puede...
¿Ves?
He puesto la A y me dice, no se puede buscar una película vacía.
Esto es porque ha detectado el estado anterior.
Para asegurarnos que siempre está utilizando este query, está utilizando el valor correcto,
lo que podríamos hacer aquí es new query.
Esto del event.target.value.
Y este new query, pues lo podríamos poner aquí.
Y aquí, y aquí.
O sea, para asegurarnos que estamos utilizando el último valor.
Y ahora sí, debería funcionar perfecto.
Así que esto sería un poco la validación.
Obviamente esto, lo bueno que lo podríamos separar totalmente en un...
Lo podríamos separar en un custom hook.
De hecho, para que veamos lo del custom hook, lo vamos a separar con el useEffect.
¿Vale?
Aunque mi recomendación, en este caso, sería seguramente hacerlo así.
Una cosa interesante de la forma controlada.
Lo bueno de la forma controlada es que otra cosa que podéis hacer, imagínate que no quieres...
Quieres evitar que se actualice el estado si empieza por A.
Yo qué sé.
Porque...
Por lo que sea.
Pero puedes hacer algunas cosas interesantes, ¿no?
Por ejemplo, aquí, en el new query, que tenemos eventarget.value, podrías decir, si la new query empieza con espacio vacío, pues no lo pongo.
Entonces, ¿qué pasa?
Que ahora si tú empiezas por espacio vacío y tú pones cosas aquí...
A ver, new query starts with...
Esto, espacio vacío.
Hace los retos.
Igual los que no han guardado cambios.
¿Vale?
Si yo intento poner un espacio vacío, fíjate que no lo hace.
¿Ves?
Yo estoy dándole el espacio y no lo hace.
¿Por qué?
Está evitando...
Estoy haciendo una prevalidación.
Y no estoy seteando el estado.
Esto es una cosa que, de la forma no controlada, se podría hacer, pero tendrías que preparar bastante más JavaScript.
Lo bueno de esto es que podemos evitar actualizar el estado si vemos que lo que intentamos setear no es algo que nos gusta.
Puede ser que empiece con un espacio vacío, que empiece con un número, que empiece con lo que quiera.
Alguna prevalidación que queramos hacer que no está permitida.
Esto es una cosa que podríais hacer.
Para que veáis un poco para qué te puede permitir hacer uno controlado contra uno no controlado.
¿Ok?
A ver, que os pregunto...
Os leo.
A ver qué me comento.
Claro, tri, me voy, pero aprendí más que en tres años de carrera.
Joder, pues te vas en el mejor momento, pues.
Mañana tengo un examen de C y no me sé nada.
Pues aquí tampoco vas a aprender mucho más, malo.
Y si lo pones en español, cumple con la búsqueda.
Por ejemplo, Vengadores.
No lo creo.
Linter, ¿cómo lo instalaste?
Lo instalamos en un día, en un principio.
¿Se ha retenido una validación con uno no controlado?
A ver, validaciones con uno no controlado es que tenéis un montón.
Podéis hacer, por ejemplo, esto.
Es una validación ya con uno no controlado.
Podéis poner aquí el require, podéis poner patterns, patterns.
También hay una API que te permite hacer en el on-submit, puedes hacer el on-validate, on-validate, no, on-invalidate, por ejemplo.
O sea, puedes hacer un montón de...
Hay formas de hacerlo de forma no controlada también.
¿Re perdido soy nuevo?
Hombre, la verdad es que tienes que saber un poco de React, al menos.
Gracias, Midu, intentamiento se entendí UREF en un año de carrera nada.
Bueno, mira, Midu, si un candidato me hace la prueba así, antes de terminar, le meto a arquitecto.
Bueno, claro.
Obviamente os estoy intentando explicar todo esto para que lo entendáis.
O sea, no controlado sería lo que es no controlado por React, efectivamente.
Cuando se dice no controlado es que no está controlado por React.
¿Se podría decir que se setea el espacio, pero como todo ocurre tan rápido, React restablece el valor del input?
No, Dartiles.
No, porque al estar controlado, fíjate que no lo setea.
No lo permite.
Porque este value nunca se actualiza y por lo tanto nunca jamás lo setea.
Nunca lo setea.
Si quiero que los estilos de input cambien de acuerdo a los errores, ¿cómo lo haría?
Súper fácil.
Pero es que al final eso es un renderizado condicional.
O sea, tampoco quiero...
O sea, no voy a hacer todos los corner cases de cómo lo queréis validar.
Pero fíjate, si tuvieses un error aquí, podrías poner un class name.
A lo mejor en el input, podrías decir, mira, style, para que te hagas una idea.
Pero es que al final esto es muy sencillo y a partir de lo que queráis hacer, podéis hacer mil millones de cosas.
Podéis poner borde, un pixel solid transparent y aquí border color.
Imagínate, si tienes error le vamos a el red y si no le ponemos transparent, por ejemplo.
Y ahora, si tengo un error, ¿ves que ha cambiado el borde?
Si no tengo un error, se arregla.
Una vez que tienes en el estado esto y lo tienes controlado,
es cuestión de que tú seas creativo de qué es lo que quieres cambiar.
Y lo puedes hacer utilizando React.
En este caso hemos cambiado el estilo del input.
Cuando tenemos un error, pues lo ponemos con el borde rojo.
Y si no, lo ponemos transparente.
Esto en el caso del input, pero es que puedes hacer lo que quieras.
Puedes hacer que aparezca en el botón, que aparezca lo que sea.
Lo que queráis, ¿no?
¿Cuál es la diferencia de poner on submit en la form o un on click en el button?
Lo hemos comentado antes también.
Pero, básicamente, que uno mira el submit del formulario.
El otro sería en el on click del submit, hace algo similar,
pero el evento que reciben no es el mismo, claro.
El de bounce lo vamos a hacer manualmente y lo vamos a hacer después.
Podría mostrar un momento el movies.js.
Entonces, ¿cuál es la mejor forma?
No controlados o no controlados.
A ver, no hay una bala de plata.
No hay una bala de plata.
Yo os puedo decir cuál es la que yo recomiendo.
Yo recomiendo casi siempre, casi siempre, yo recomiendo no controlados.
Suele ser más fácil, suele ser más rápido, más óptimo, suele dar menos problemas.
Y, además, vais a aprender más JavaScript.
O sea, win-win, ¿vale?
Pero hay veces que controlado puede tener sentido porque se pueden hacer un montón de cosas.
Pero no hay una bala de plata, no hay uno perfecto.
No te voy a decir uno es mejor que el otro.
Os puedo recomendar en general el no controlado.
Pero está bien que conozcáis los dos, ¿vale?
¿Cuál era la diferencia de uref con la variable let?
Luego os explico un ejemplo.
Ah, mira, lo podemos ver ahora.
Mira, lo vamos a ver ahora.
Ahora que tenemos un estado, ahora que tenemos un estado,
mira, ahora que tenemos un estado aquí, ¿vale?
¿Veis que, mirad, cada vez que escribo hay un render, ¿verdad?
Cada vez que escribo hay un render.
Vale, imagínate que hago let i y hago i más más.
Y hago un console.log de la i.
Vamos a ver el valor de la i.
El valor de la i siempre va a ser el mismo, ¿ves?
Uno.
Por más que yo escriba, siempre es uno.
Porque el valor no persiste, ¿vale?
Esto se está recreando cada vez que se renderiza el componente.
En cambio, si tú tienes un urref, urref, tengo que importar el urref.
Esto es súper importante que lo entendáis.
El urref es una referencia que persiste a un valor que puede cambiar,
que puede ser mutable y que cada vez que cambia,
no vuelve a renderizar el componente porque si no sería un loop infinito.
Entonces, ahora que tenemos este counter, imagínate,
el counter lo empezamos a cero y vamos a decir que el counter.current,
siempre que acceder al punto current, hacemos un más más, ¿no?
Y ahora hacemos un console.log del counter.current.
Y en este caso, sí que deberíamos ver, ¿ves?
Que los valores se van sumando, ¿vale?
Se van sumando cada vez que hacemos un renderizado,
pues podemos ver que se va renderizando y ya está.
En el caso de por qué salen dos veces esto,
en realidad no tiene nada que ver con esto.
Es más que nada, puede ser por este, el useEffect,
que está actualizando dos veces el estado.
Tiene más que ver con eso que no con otra cosa.
Pero lo importante que tenéis que entender aquí,
porque cambia de, o sea, sí que lo está haciendo 16, 17, 18,
o sea, lo está haciendo bien,
se ha renderizado dos veces porque hay dos set states, actualizaciones,
pero esto es un valor que persiste entre render.
Y por eso, justamente para eso, sirve el UREF.
El strict mode en realidad es la primera vez.
No es por el strict mode, esto será por otra cosa.
Que se renderiza dos veces la...
No sé si es porque se ha renderizado la primera vez dos veces
o que siempre se ha renderizado dos veces.
Ahora tengo dudas.
Pero bueno, no importa.
Puede ser por una cosa o la otra, pero tampoco es tan importante.
Lo importante es que sepáis que el UREF sirve para eso.
¿Vale?
Ok, ya tenemos el UREF.
A ver, voy a sacar también otra vez aquí el useSearch este que hemos hecho.
Más que nada para que sigamos dejando súper vacío nuestro...
Nuestro...
Mira, ah, bueno, le he llamado useSearch.
Vale, le voy a llamar useSearch, ya que lo he dejado así.
Esto lo quitamos.
Vamos a ponerle error.
Básicamente para que veáis, os tenéis que acostumbrar a la tónica de dejar vuestros
componentes limpios y hacerlo a través de custom hooks para sacar la lógica de vuestros
componentes fuera.
¿Vale?
Esto es súper importante.
Y vais a ver que es que es muy fácil.
O sea, que no es difícil.
Que si dijésemos, no, es que es súper difícil.
Pero es que es muy fácil.
Porque ahora hemos extraído súper fácil tanto todo el tema del search, la validación
y todo lo hemos sacado.
Y esto os tenéis que acostumbrar, porque si no, lo que os va a pasar siempre es que
vais a pecar de tener un montón de lógica dentro de vuestros componentes.
Y eso, pues, no es lo que queremos, obviamente.
¿Vale?
Así que, bueno, le he llamado query.
Aquí la he liado porque me he puesto aquí con...
Vale, esto lo voy a quitar, que ya no lo necesitamos.
Aquí vamos a poner updateSearch.
Esto tampoco lo necesitamos.
Vale, ta, ta, ta.
A ver, y me falta una query que he puesto por algún sitio.
Tu, tu, tu.
¿Dónde he puesto aquí la query?
Query.
Vale, aquí tenemos que poner search.
Bueno, le llamo al query, pero ya lo dejamos con el search.
¿Vale?
Vale.
Y ya lo tendríamos.
Vale.
Vamos a ver otro uso del UREF, que esto también es importantísimo.
Y vais a ver, ¿para qué se usan los custom hooks?
Para lo que acabamos de hacer, Pablo.
Para extraer lógica de los componentes.
Para extraer lógica de los componentes.
Eso es lo que hemos hecho.
O sea, lo que hemos hecho es extraer la lógica del componente, la gestión del estado,
el useEffect, validaciones, y convertirlo en una caja negra.
En una caja negra, que ya...
Como separarías los custom hooks en la carpeta hooks cuando la app sea más grande.
Y esto, ya habéis visto lo fácil que ha sido.
O sea, lo he hecho aquí en vivo en directo.
El extraer, ya hemos extraído dos, no uno, dos.
Dos custom hooks.
Lo voy a dejar este aquí para no liarla mucho.
Vale.
Os voy a explicar otro pedazo de trucazo con el tema del UREF.
Porque un problema que muchas veces os vais a encontrar es esto, ¿no?
Fijaos, yo acabo de entrar y pone...
No se puede buscar una película vacía.
O sea, me está haciendo la validación directamente al principio.
¿Por qué?
Porque si miramos en el useSearch, aquí podéis ver que el estado inicial es un string vacío.
Y aquí tenemos que, si mira el string vacío del search, dice...
Vale, setError, no se puede buscar una película vacía.
¿Cómo podemos evitar esto?
Lo vamos a evitar también con un useRef.
Esto es para que veáis las utilidades que tiene un useRef.
Mucho más allá de la típica explicación de...
Sirve para guardar referencias del DOM.
Es que no es verdad, ¿vale?
Es solo una de las razones.
Tienes que entender que el useRef es para lo que es.
Entonces, ¿cómo vamos a hacer esto?
Pues vamos a tener como esto muy típico de los ref, tener una banderita que se le llamaría.
Podríamos tener aquí para saber si es el first render.
Yo lo voy a llamar si es el first input.
Para saber si realmente el usuario ha utilizado o no ha utilizado todavía el input.
Para que valide a partir de que el usuario utilice el input.
Y no antes.
Porque si no, fíjate, yo nada más entro a la página y me dice...
No se puede buscar la película vacía.
Y digo, hombre, cálmate.
Déjame vivir.
No me estreses.
Entonces, vamos a poner un useRef que vamos a poner su valor inicial como true.
Para decir, ¿es el primer input del usuario?
Por ahora sí.
Por lo tanto, vamos a decir, vale, si es el primer input del usuario, ¿vale?
Lo que vamos a hacer es, vale, si es el primer input del usuario, el primer input del usuario,
vamos a cambiar su valor en el caso de que el search sea igual a string vacío.
¿Qué significa esto?
Si es el string vacío, esto va a ser true.
Pero en cuanto ponga una A, imagínate, el search pasa a ser una A, entonces esto será el search.
Esto será false.
Ya el useRef input será false porque ya ha hecho algún input y ya.
De esta forma vamos a evitar que siga por aquí.
Y lo bueno es que al utilizar una referencia y no un estado, esto no va a hacer un setState.
Sino que no va a volver a renderizar el componente.
Porque no necesitamos que lo renderice.
Lo que necesitamos es que lo controle.
Así que con esto, lo que vamos a hacer es que me deje fatal.
Porque aquí vemos que me ha dejado fatal.
A ver, ¿qué he hecho yo aquí?
¿Lo he hecho bien, no?
¿O no lo he hecho bien?
InputCurrent.
A ver si alguien sabe las comillas.
Ay, perdón, que he dejado las comillas esta.
La he liado parda.
Ahora sí.
Coño, digo, joder, estaba súper seguro, pero he dejado el ejemplo en las comillas, ¿vale?
O sea, estaba bien el código, solo que cuando os he puesto el ejemplo este, la he liado con las comillas.
Gracias a alguien que lo ha dicho.
La cueva del lot, muchas gracias.
Bueno, con esto lo que estamos haciendo, esto es una cosa muy típica que muchas veces se utiliza
simplemente para saber si es la primera vez que se renderiza el componente,
si es el primer input del usuario, para saber que es la primera vez de algo, ¿no?
Y fíjate cómo lo hemos hecho.
Con un UREF, con un boleano, y aquí hemos hecho a partir de este USEffect que se ejecuta cada vez que cambia el set,
pues hemos dicho, si es el primer input del usuario, voy a ver si esto todavía, este flag todavía está true,
voy a ver si he puesto algo en el set para asegurarme que lo cambio y hago un return para evitar que me haga la válida.
Y con esto ahora, si aquí hacemos, escribimos, ya ves que ahora sí, está, ahora si lo dejo vacío,
sí que me dice, no se puede buscar la película, pero si tú entras de primera, no lo válida.
Solo cuando ya es escrito, ¿vale?
Así que ahí tendríamos un poco la válida.
Venga, preguntas.
Esto está, eso está súper interesante.
¿Cómo saber cuándo usar un custom hook en una función helper para separar lógica?
Normalmente un custom hook, o sea, normalmente, si tú tienes un USEffect en tu componente, es un custom hook.
O sea, yo siempre que veo un USEffect, digo, es un custom hook.
Muy pocas veces, es que siempre, casi siempre que ves un USEffect, es un custom hook.
Luego, como mínimo, un custom hook, lo mejor que puede ser es que tengas un USEstate, o sea, que estés usando hooks.
Si tú no estás usando ningún hook y lo que quieres es separar lógica, lo mejor es un help.
Pero si ves que tiene algún tipo de lógica, lo mejor es que lógica algún hook es un custom.
Haciendo eso, no lo vuelve a renderizar.
Como hemos explicado anteriormente, las referencias, cuando se actualizan, no vuelve a renderizar.
El ref no se debería poner como dependencia del USEffect, depende, porque en nuestro caso no queremos que sea una dependencia.
Esto, esto de las dependencias, esto es como nosotros le decimos, este efecto queremos que se ejecute cada vez que cambien estas dependencias.
Pero realmente esto me da igual y realmente no quiero que se vuelva a ejecutar.
Todas las variables que están en un custom hook se generan nuevamente cada renderizado, se generan después de un renderizado.
¿Es tan rápido que no entendí nada?
Bueno, pues, pero no se trata de rapidez, se trata que ahora, en el momento de decir, en lugar de decir, es tan rápido que entendí nada, que aproveches y hagan las preguntas.
Tampoco vamos tan rápido.
Sobre todo, a ver si no sabes React, obviamente.
Pero, muy bien, se venía perfecto a usarlo en el hackathon anterior.
Bueno, pero ahora ya lo sabes.
¿Y si damos un tiempo al error de los tres caracteres?
Un tiempo al error de los tres caracteres.
Podés hacerlo en un setTimeout y ya está.
¿Cómo separaría los custom hooks en la carpeta hooks cuando la app sea más grande?
Pues como lo hemos hecho ya.
O sea, es que justamente hoy lo hemos hecho en vivo y en directo.
UseMovies.
Lo hemos separado en un hooks y hemos puesto export function, useMovies.
O sea, con el patrón módulo.
¿Qué opinas de crear barres para importar más cómodamente?
Que si te funciona, me parece genial.
Mostra de nuevo en dónde llamaste el useSearch.
Pues lo estamos llamando dentro de la app.
Hemos extraído la lógica de todo el tema del useSearch.
¿Cómo saber cuándo diferencia un custom hook de un context?
Porque son cosas totalmente distintas.
Y más que cómo saber cuándo diferencia un custom hook de un context,
la pregunta sería, ¿debería aprender qué es un custom hook y qué es un context?
Pues son dos cosas totalmente distintas.
Puedes utilizar un context dentro de un custom hook,
pero es que los custom hooks pueden ser useState, useEffect, como hemos comentado.
Súper interesante, precisamente quería saber cómo se hace algo así.
¿Todos los custom hooks necesitan useEffect?
No.
De hecho, puedes no utilizar ningún hook,
pero ya os digo yo que lo mejor sería utilizar al menos un hook, un useState.
También se podría inicializar en estado null sin ningún problema.
El return sin nada detrás de retorna, el return sin nada retorna undefined.
Si me recuerda un watch, entonces se usa debounce, luego lo vemos.
¿Podríamos separar la llamada de la API del custom hook?
Claro que sí, no habría ningún problema.
De hecho, lo vamos a hacer.
Primero veo las clases, las aprendo, las analizo,
luego las operativo sobre el match y luego las hago sin ver.
Muy bien, me parece muy buena técnica.
Vale.
¿Crees que para una aplicación que tenga muchos formularios Angular es una mejor opción?
No, no creo que una sea mejor que la otra porque tenga muchos formularios o más.
No, no lo creo, la verdad.
¿Uref persiste a lo largo de cualquier renderizado?
Sí, dentro del componente, obviamente.
¿Se puede acceder a los atributos del m elemento con uref?
Obviamente sí, porque hemos accedido.
O sea, ahora es que haceros ejemplos un poco tal, pero obviamente sí.
O sea, puedes acceder a todo el elemento.
A todo el elemento.
Muy buen directo, mi, tu trabajo con view, pero acá ando repasando React.
Muy bien, hombre.
Me alegro.
Vale.
Vale, pues hasta aquí, cada vez que escribir se renderiza el componente, sí.
De hecho, es una cosa que vamos a ver ahora.
Si os parece, voy a hacer una cosa rápida y ahora sigo un poco viendo las preguntas.
Porque ponía, haz que las películas, bueno, ya tengo que el formulario funcione, pero todavía
no estoy haciendo el fetching de datos, pero bueno, os quería explicar todo el tema del
formulario.
Funcionar funciona, pero lo que tengo que hacer ahora es hacer el fetching de datos a la API.
¿Vale?
Luego dice, haz que las películas se muestren en un grid responsive.
A ver, esto lo voy a hacer en un momento y además os recomiendo mucho que esto, no
sé si lo que lo memoricéis, pero este grid que os voy a enseñar es clave, es clave
en la vida.
Porque es un grid muy típico a la hora de hablar de resultados y si sabéis utilizarlo
en una prueba técnica, va a ser diferenciador.
Porque no vais a tener que buscarlo y tal y os lo tenéis que saber de memoria.
No es muy difícil, pero lo recomiendo mucho.
Vamos a Movies, que tenemos aquí los componentes.
Voy a asegurarme que tengo como las clases.
Creo que lo vamos a poner aquí, en Movies, ¿vale?
Y vamos a poner que cada clase aquí tenga Movie, ¿vale?
Vamos a poner ahí unas clases.
Ahí, perdón.
Esto es ClassName, ClassName, ¿vale?
Vale.
Vamos a poner aquí, vamos a estilar esto.
Voy a hacer esto un poquito más chiquitito.
Aquí, vamos a quitar esto.
Vamos.
A ver, primero, ¿qué pasa?
Nos dicen, si os fijáis en el Ritme, nos dicen que tienen que ser...
Las películas se muestran en una grid responsive.
Esto es súper típico en las pruebas técnicas, te lo dicen, porque todo el mundo utiliza
una grid responsive.
Entonces, si esto lo sabes hacer, vas a sumar puntos.
Y, al final, es recordar muy pocas líneas de...
Primero, vamos a poner que esto sea una grid, ¿vale?
Le vamos a decir que ocupe el 100% del espacio, ¿vale?
Vamos a ver si esto está ocupando ya el 100% del espacio.
A ver si le dejamos esto por aquí.
Vale, puede ser con el root, header, main.
Vamos a poner que esto sea...
Vale, vamos a poner con el main, ¿con el main o con toda la página?
Con la página.
Vamos a poner mac with 100%, max with 200, ¿vale?
Vamos a ver si esto ya está haciendo su magia.
Page.
Vale, ahí lo...
Vale.
Ahora que tenemos eso, le vamos a decir...
Esto es para que tenga un ancho en nuestra página.
Y asegurar.
Grid.
Mira, si es que ya te lo dice hasta el Gijacopalo.
Pero bueno, grid.
Template Column.
Lo que le estamos diciendo es cómo tienen que comportarse las columnas dentro de esta grilla, ¿no?
Y le decimos que repita.
Le decimos que tenga que hacer autofit, ¿no?
Como que se tiene que...
Tiene que pillar el espacio disponible.
Y el espacio disponible va a ser entre 200 píxeles.
En el caso de que ocupe...
Pueda ocupar 200 píxeles, lo va a tomar.
Y si no, pues que ocupe una fracción.
Y con esto, lo que debería...
Ahora va a salir un poco regular.
Ah, pues no.
Ni regular ni nada.
No ha salido de ninguna forma.
A ver, ¿le ha liado parda con alguna cosa?
Bueno, espérate.
Porque también...
Espérate.
Porque como no tengo...
Esto vamos a poner non y margin.
Esto normalmente te lo dan CSS reset.
Eso por lo que...
Y el movies...
A ver, voy a poner aquí...
Espérate.
Porque a ver si tengo aquí el movies...
Vamos a poner el padding 0 este.
Anda, que yo también que he dicho que os lo tenéis que saber de memoria.
Y yo soy el primero que...
Es que este...
Ah, es que este...
Este main...
Este main es el que tiene que estar al 100% del Wii.
Este main tiene que estar al 100%.
Pues no.
Ahora sí.
Claro, lo que está pasando es que no le había dicho que el main tiene que ocupar todo el espacio.
Entonces está ocupando el espacio mínimo para que metese el contenido.
Le decimos que pille el 100% del width porque así lo que va a pillar es todo el espacio que le hemos dicho.
Y ahora sí se va justo.
De hecho, vais a ver que ahora conforme vamos bajando, ves, ya haciendo esto.
Como mínimo, pilla una fracción, pero cada vez que pueda ocupar con dos columnas los 200 píxeles, si ocupan 200 píxeles, dice, ah, pues entonces caben dos.
¿Por qué?
Porque como mínimo tiene que ser 200 píxeles.
Si no caben 200 píxeles, entonces lo que voy a hacer es esperar y hacerlo más grande hasta que quepa.
Y ya está.
Así con esto, pues al menos ya tenéis una great response.
A partir de aquí, al menos podéis empezar a poner lo del gap, ¿vale?
Para que tenga espacio entre ellos.
Hemos quitado el padding.
Bueno, le podríamos empezar a hacer más cosas, pero bueno, con el gap podéis ponerle bastante gap.
Y ya aquí, pues podéis estilar un poco.
Tampoco hace falta que estiléis mucho, ¿eh?
Pero lo que os ocurra, que no sea muy raro, lo podéis.
Por ejemplo, a ver, en el movie, para que quede bien, vamos a poner text align center.
Vamos a poner esto por aquí, ¿vale?
Por ejemplo, esta separación es muy exagerada.
Pues le podéis poner movie h3, margin bottom 0, ¿vale?
Bueno, no sé, margin o padding, es un h3, ¿qué he hecho aquí?
Esto es un h3, sí, es un h3, movie h3, padding 0, margin 0, ¿vale?
Y luego teníamos la p, ¿vale?
O sea que vamos a poner aquí el movie y el movie p, ¿vale?
Vamos a ponerle padding 0 y ya está.
Al menos para que quede un poquito más juntito y el margin 0.
Bueno, este es necesario.
Y, bueno, lo que sí podéis hacer aquí, que tenga más separación entre la imagen y tal,
lo podéis hacer con gap, lo podéis hacer con...
Pero bueno, simplemente que tengamos la grilla y que más o menos nos quede algo así, ¿vale?
En un momentito.
Y lo importante es, primero, lo del contenedor, que tengamos el 100% del ancho.
Si no se nos ocurre porque estamos muy, ostras, porque no se ve, no funciona,
pues a ver, si lo hubiera puesto aquí a mano los 500 píxeles, pues hubiera funcionado
y ya está, ¿vale?
Subirá quedando 500 píxeles y ya está.
Lo mejor que pongáis aquí el 100%.
La clave es el display grid del contenedor, que ocupe todo el ancho que podáis,
para que se note, para que sea responsive justamente, lo mejor es que sea,
con un tanto por ciento.
Y el grid template columns para decirle que se tiene que repetir,
que se tiene que...
Te puedes utilizar autofit o autofill.
La diferencia...
Bueno, en este caso es autofit.
Porque aquí en este caso...
Espérate, que ahora le he liado porque me lo he roto.
¿Qué he hecho?
Si estaba funcionando mi querido...
¿Qué he tocado?
Creo que la diferencia está aquí.
Creo que la diferencia...
Ah, no, está aquí.
Está aquí.
El autofill y auto...
Está aquí en el final.
¿Puede ser?
Bueno, pues no tampoco.
Nunca me acuerdo cuál es la diferencia de autofill y autofill, la verdad.
Porque fijaos que se...
Creo que es cuando queda uno, pero veo que no es la diferencia.
Creo que...
Pensaba que la diferencia era cuando quedaba solo uno.
Pero bueno, creo que no.
Seguro que en el chat me está diciendo.
Autofill, déjale espacio.
Bueno, pero ya habéis visto que...
Otro día dijiste que la ibas a estudiar.
Que la ibas a estudiar la diferencia.
Sí, sí, pero ya veis que tampoco me ha dado tiempo.
O sea que...
Bueno, autofill y autofill.
Yo normalmente utilizo autofill.
Y ya veis que con esto ya lo tenéis.
Pero sí, le preguntaré a Manz, que es el tío que sabe aquí CSS.
Y ya está.
O sea, con esto ya tendríamos lo del Ritmi.
No es muy fastidioso.
Pero lo importante yo creo que es que os acordéis de estas dos.
Porque con estas dos ya lo demás, más o menos, os quedará mejor, peor.
Por ejemplo, con esto, ¿ves?
Quedará mejor o peor.
Pero ya empezará a ser responsive.
Y luego ya podéis empezar a ajustarlo.
¿Vale?
Se nota cuando hay menos elementos que el total de columnas.
Cuando hay menos elementos que el total de...
Claro, claro.
Tienes razón.
Tienes razón.
Es cuando, por ejemplo, cuando solo hay dos, ¿no?
Vale, vale.
Sí, tiene sentido.
Tiene sentido.
Vale.
Bueno.
¿Qué pasa?
¿Se me ha olvidado un punto y coma en algún sitio?
Está todo el mundo punto y coma, punto y coma.
No sé dónde se me ha olvidado.
¿Qué es FR?
FR significa fracción.
Y es el espacio.
Tú puedes...
Imagínate que tienes un espacio de 100.
Imagínate que tienes 100 píxeles.
Pues una fracción serían 100 píxeles, ¿no?
Pero si tú dices que son...
Tienes una fracción, una fracción, una fracción, una fracción...
Cada fracción sería de 25 píxeles.
Y tendrías 4 columnas.
Entonces, una fracción tienes que entender que depende cómo tú fraccionas el contenido.
Si te refieres a una fracción, pues solo se va a referir a 100 píxeles.
Pero una fracción y una fracción, si las pones al lado, significa que son dos columnas de 50 píxeles.
¿Vale?
Esa sería la explicación de hace.
Es interesante porque la unidad de fracción funciona como al revés, ¿sabes?
O sea, normalmente lo que tú le dices es lo que ocupa.
Pero la fracción es...
Siempre es una fracción.
Obviamente puedes decir, pues 100 píxeles.
Tienes una fracción y tres fracciones.
Estos son 25 píxeles y 75 píxeles.
¿Sabes?
Es bastante interesante.
Vale.
¿Qué diferencia hay entre padding y el gap?
El gap es la separación entre elementos.
Lo cual, siempre que utilicéis GrittyFlex, si queréis separar entre elementos, os recomiendo que utilicéis el gap.
¿Vale?
Ok.
Además, el padding es que tienes otros problemas.
Porque la separación entre elementos, el padding, tendrías una separación de aquí a la izquierda.
En cambio, es esto lo que separas entre.
Lo puedes ver.
¿Ves aquí?
Lo puedes ver con el color ese.
Ese es el gap.
En cambio, el padding sería una...
Podrías hacer entre elementos, pero tendrías que decir abajo a la derecha.
Y tendrías que saber cuándo está cada uno.
Es mucho más fácil el gap cuando quieres separar entre elementos.
Ya tenemos esto.
Venga.
Ya tenemos esto.
Vamos a seguir con nuestra prueba técnica.
Vamos a hacer que se busque, por fin, cuando hacemos el click.
Más estrategia.
A ver.
Aquí vamos a hacerlo en el Use Movies.
Cuando hacemos el click, lo tenemos aquí, ¿no?
Cuando hacemos el button, cuando hacemos el Handle Summit, básicamente.
Aquí, en lugar del console.log, lo que queremos es que haga la búsqueda.
Aquí habíamos hecho que devuelva las movies, ¿no?
Aquí tenemos mapeed movies y esto es lo que devolvía porque mapeaba toda la información y todo.
Vamos a crear aquí un get movie que lo que hace es simplemente que, bueno, si tiene búsqueda,
o sea, si no es un string vacío, vamos a crear un estado.
Vamos a crear un estado que sea response movies, set response movie, use state.
Y empezamos con un string, con un array vacío, ¿vale?
Esto, esto por ahora, esto lo vamos a quitar porque esto no lo necesitamos aquí.
Este movie.
Bueno, este movie, bueno, sí, vamos a dejarlo.
Lo que vamos a hacer es que tenemos una función que se llama get movie,
que cuando la llamemos la vamos a extraer aquí, vamos a exportar.
Cuando tengamos un search, vamos a hacer un set response de response movie.
Y cuando no tengamos, pues vamos a hacer un without results.
Así vamos a poder ver fácilmente si tenemos resultados o no tenemos resultados.
Ahora, ¿dónde sacamos este search?
¿Dónde sacamos el input?
Pues se lo vamos a pasar a un custom hook, le puedes pasar parámetros.
Así que se lo vamos a pasar por aquí.
Y este use state lo tenemos que importar de React aquí.
Y este response movie, vamos a poner with result.
En lugar de response movies, with result.
Y ya está.
O sea, tenemos un estado inicial con un array vacío.
Lo que hacemos aquí, que este response movies, le sacamos el search.
Esto lo arreglaremos después para que veáis cómo sería lo ideal hacerlo.
Esto aquí estamos metiendo una lógica que podríamos separar mejor.
Mapeamos esto si realmente tenemos un array.
Pues lo mapeamos, le cambiamos las propiedades.
Y este método que tenemos aquí, que le llamamos get movies, lo vamos a extraer, lo vamos a exportar para que desde la app podamos utilizar esto.
Así que tenemos aquí este movies que tenemos aquí.
Vamos a tener ahora get movies.
Y a este use movies le vamos a pasar el search.
Ahora este get movies lo vamos a ejecutar aquí.
Y ya lo tendríamos.
Vamos a ver.
Ahora, dice, no se encontraron películas para tu búsqueda, porque el search está vacío.
Voy a empezar a escribir, Avengers, buscar.
¿Vale?
Pues ya tenemos Avengers.
Ahora, elimino, buscar.
No se encontraron películas para esto.
Todavía no estoy haciendo el fetch.
Alguien dirá, pero es que no estoy haciendo el fetch.
Claro, yo lo sé.
No estoy haciendo el fetch, pero al menos ya estoy comprobando que me funciona sin resultados, con resultados.
Y ya estoy haciendo aquí todo ese tipo de información.
No me tengo que preocupar de hacer ninguna cosa.
O sea, fíjate que lo bueno del custom hook es que, obviamente, yo no quiero hacer el search response.
No quiero hacer esto.
Lo que quiero es poder hacer el fetch.
Bueno, pues es que ahora es tan fácil como quitamos esto, hacemos el fetch, ¿vale?
Vamos a hacer HTTP, OMDB.
Esto lo tenemos en el Ritmi.
Esto lo habíamos puesto aquí.
Lo copiamos por aquí, ¿vale?
Y entonces seguimos haciéndolo en crescendo, ¿no?
Vamos poco a poco con pequeña victoria.
En la S, en lugar de Avengers, le vamos a pasar el search.
Ya lo tenemos por aquí.
Y ahora, yo lo voy a hacer con promesas.
Si lo quieres hacer con la Sinkaway, hazlo con Sinkaway, hazlo con lo que te guste más.
Yo lo voy a hacer con promesas, ¿vale?
Vamos a poner setResponseMovies.
Yo por ahora voy a setear directamente todo el JSON.
¿Por qué?
Porque yo, con los mocks que hemos hecho al principio, lo estaba haciendo con todo el JSON.
Entonces, ahora no puedo mapear ahí en medio y tal.
Lo haremos, pero por ahora lo vamos a dejar igual para que nos funcione tal cual.
Si tengo un search, entonces busco la película y si no tengo el search, pues setResponseMovies y ya está, ¿vale?
Ahora, un error que a veces puedes tener, que es este de acá.
Avengers...
Vamos, pues es que hacer un redirect.
Hay veces que puedes tener bastantes problemas.
Uno, que se te olvide que hagas esto, ¿vale?
Y entonces hagas Avengers, haces el return, no pasa nada.
¿Qué ha pasado?
Me pongo nervioso, estoy llorando, no voy a pasar la prueba técnica.
¡Ay, Dios mío!
Me van a echar.
Y todavía no me han contratado.
Bueno, a ver, muchas veces nos ponemos un poco nerviosos porque no funciona nuestro fetch, ¿qué pasa?
A ver, si hemos hecho el fetch con toda la URL y lo hemos visto, ¿sabes?
Que muchas veces la gente hace esto, lo copia, lo pega, lo pone aquí, aquí pone Avengers, ¿no?
Y dice, ostras, aquí me funciona y luego hace esto.
A lo mejor copia esto, no copia todo el HTTPS y tal.
Y dice, aquí me ha funcionado.
Lo pega aquí y no le funciona.
No pasa nada, no pasa nada, ¿vale?
No pasa nada.
¿Qué es lo que tienes que hacer?
Lo que tienes que hacer, primero, es relajar.
Segundo, respirar.
Y tercero, abrir las herramientas de desarrollo.
Las herramientas de desarrollo son tus amigos.
¿Qué es lo que hacemos?
Si primero nos aseguramos que estamos haciendo realmente la petición de datos.
Así que, abrimos la herramienta de desarrollos, ponemos Avengers, buscar.
Aquí veo una petición, ¿vale?
Fíjate aquí que tienes el fetch y te recomiendo que en lugar de tener el todo, que hagas aquí fetch XHR, porque así los tienes.
Ya hemos visto que sí lo está haciendo.
Algo está haciendo.
¿Por qué no está funcionando?
Bueno, vamos a ver.
Le hacemos un clic y siempre, siempre, siempre vamos a ver en este orden.
Uno, ¿cuál es la URL que estamos solicitando?
La revisamos para ver si está bien.
¿Está bien esta URL?
No.
¿Por qué?
Porque está haciendo un fetch relativo al localhost.
Esto está mal, ¿vale?
¿Qué es lo segundo que miraríamos?
Lo segundo que vamos a mirar es la respuesta.
¿La respuesta realmente es lo que estamos esperando?
No.
Porque nos está devolviendo un HTML y no es lo que necesitamos.
Pero bueno, con lo primero ya hemos visto que la URL está mal, pero aún así, miramos la respuesta, la respuesta está mal.
De hecho, puedes ver, te podrías dar cuenta, que lo que está haciendo es importar como nuestra página web.
Pero esto es súper importante, ¿vale?
Las dos cosas más básicas que tienes que saber mirar aquí es, aquí tienes las respuestas, le das un clic, en el general, la URL que hemos solicitado y la respuesta lo que ha devuelto la app.
¿Por qué?
Porque puede ser que te encuentres que sí que ha devuelto lo que esperabas.
Oye, ¿que ha devuelto lo que esperabas?
Perfecto.
Algo has hecho mal en el código.
Oye, ¿que no ha devuelto lo que esperabas?
Vale.
Igual has hecho algo que no está bien.
¿Otra cosa que te puede ayudar?
Pues, oye, ¿cuál es el estado que te está dando?
Aquí hay 304, 200.
Lo malo, que normalmente si te dan 200 es porque está tirando de lo tuyo.
En tiempo de crisis, el panico no ayuda a vivir.
Normalmente, yo te recomiendo que te mires primero esto, la URL, la respuesta.
Porque el status code, en la respuesta, normalmente el error que te des, si es un error, te va a ser bastante descriptivo.
Sobre todo es una API.
No tienes API Key, no estás pasando bien la API Key, lo que sea.
Para que te hagas a la idea.
Imaginemos que arreglo bien esto, ¿vale?
Y lo de la API Key lo he hecho mal.
Fíjate.
Yo pongo Avengers, buscar, de nuevo no aparece.
Claro, me sale en rojo.
No me dice mucho.
Pero si vas encabezado, ¿has hecho bien la URL?
Parece que sí.
401.
Pero no te vas a enterar, no te vas a acordar.
401, ¿qué es?
Que no tengo...
No te vas a poner a entrar a HTTP cat.
Es que no te da la vida, ¿vale?
No vas a estar aquí.
Una authorize.
Bueno, puede ser que te dé tiempo, pero lo mejor que puedes hacer, primero, rápido, lo tienes al lado, respuesta.
Y te lo va a decir, oye, error, no API Key.
Pum, te vas a enterar al momento, ¿vale?
Yo te recomiendo, si te lo sabes de memoria, pues bueno, te va a ayudar.
Pero es que hay veces que te va a poder aparecer un 401 y no te vas a enterar.
No vas a saber.
O te pone un 401 y ya está mal.
Normalmente la respuesta te va a ayudar mucho más.
A partir de que has mirado la URL y la respuesta, a partir de ahí, entonces, le das cañita, ¿vale?
A ver, cañita a mirar otra.
Pero esto te va a evitar el 98% de problemas que vas a tener con fetch de una API, ¿vale?
Bueno, con esto, con esto de aquí, con esto de aquí, amigos, ya tenemos nuestra API.
De hecho, fíjate, estamos aquí, ponemos Matrix, buscar, ¿vale?
O sea, ya tenemos esto funcionando.
O sea, que no está nada mal.
Ahora bien, en una prueba técnica, quizás no te da tiempo, pero por buena práctica,
todo lo que hemos hecho aquí, yo personalmente lo sacaría en un servicio.
Un servicio porque todo el fetching de datos, pues a ver, no tiene mucho sentido que esté dentro del custom hook
cuando lo podemos extraer fácilmente.
Entonces, podríamos tener un servicio de movies.
Aquí podrías poner export const, search movies, que sea síncrono,
que le podamos pasar lo que queremos buscar.
Y aquí, pues nada, todo lo que hemos hecho, algo parecido a todo lo que hemos hecho aquí.
Pero, ojo, de esto jamás me voy a cansar de comentaroslo.
Ya separamos la API key, ya que estamos, ¿no?
Porque tiene sentido.
Si nos diese tiempo, lo podríamos sacar incluso a una variable de entorno.
Eso ya sería de nota, pero bueno, eso no creo que nos dé tiempo.
Y muchas veces ni siquiera controlamos esto.
Si os da tiempo, pues lo hacemos.
Cosas importantes.
Uno, no le pasamos el estado, ¿vale?
No pasamos el estado por aquí.
Siempre lo que hacemos es devolver el fetching de datos.
En este caso, devolver si es without results.
A ver cómo es without results.
Bueno, claro, es que esto lo deberíamos hacer dentro.
O sea, que vamos a hacer un montón de cosas aquí.
O sea, en lugar de este map, en movies, todo esto que hemos hecho aquí, esto lo vamos a hacer.
O sea, ¿qué vamos a hacer?
Vamos a hacer que si el search es vacío, devolvemos null.
O sea, ni siquiera hacemos el fetching de datos, porque ya sabemos que no lo he...
Como sé que os gusta mucho el async await, seguro que en el chat me habéis empezado a petar.
Oye, ¿por qué no utilizas el async await?
Te odio, no sé qué.
¿Por qué no lo usas?
¿Pero por qué no lo usas?
Pero dime, ¿por qué no lo usas?
¿Por qué no lo usas?
Seguro que me lo habéis dicho.
Lo vamos a hacer, ¿vale?
Vamos a utilizar aquí el await, con el fetch, con la piki.
Luego aquí vamos a tener el JSON, await response del JSON.
Y lo que vamos a hacer para quitar todo esto, vamos a hacer otra.
Aquí es un buen sitio donde hacer el mapeo de datos.
Porque tienes que pensar, ¿el mapeo de datos en realidad debería estar en el custom hook?
Por lo cierto, es que no.
No es necesario.
Así que mucha de la lógica que habíamos echado, esta lógica de aquí, esta la podríamos sacar aquí.
En lugar de response movie, aquí tenemos el JSON.
Estos movies lo tenemos aquí.
Y este map en movies, pues mira, ya podríais devolver esto directamente si queréis.
Ni siquiera le tenéis que dar un nombre.
Y podéis poner aquí un catch, que si hay un error, pues lo que siempre os recomiendo, ¿no?
Que al menos tengáis un new error.
Que no dejéis que el error original sea el que llega, ¿no?
Pues error searchinmovies, podéis utilizar modelos, podéis custom errors.
Que esto lo vimos en un directo, cómo utilizar custom errors.
Pero bueno, se sale un poco de la clase.
Pero al menos que controléis los errores y sepáis lo que ha pasado, ¿vale?
Porque si no, aquí haría el throw del fetch.
Y hombre, no es lo que creéis.
Así que ahora este searchmovies, que sería como un servicio que tenemos totalmente externo.
Ya no necesitamos los mocks.
Fíjate, que habíamos empezado los mocks.
Ya nos podemos olvidar de los mocks totalmente.
Importamos el searchmovies.
Y simplemente lo que podemos hacer aquí, todo esto ya lo quitamos.
Vamos, el responsemovies le llamamos setmovies, setmovies.
Y en el getmovies este, lo que vamos a hacer es llamar al searchmovies pasándole el set.
Ahora, como esto es asíncrono, ¿qué tenemos que hacer?
Async await, aquí vamos a poner el await.
Vamos a poner también que esto sea movies.
Y una vez que tenemos el movies, setmovies, o new movies.
Vamos a llamarle new movies, que me gusta.
Este map es movie, ya no lo utilizamos.
Y ya con esto, si todo ha ido bien y no lo hemos liado mucho,
ya funciona todo exactamente igual que como lo teníamos ahora.
O sea, ya tenemos esto.
Fíjate lo que ha cambiado el usemovies, pero solo hemos tenido que tocar.
Con todo lo que hemos tocado, solo hemos tenido que tocar el custom hook.
No hemos tocado para nada nuestro app.jsx.
Nada, nada de esto lo hemos vuelto a tocar.
Hemos estado con el usemovies, le hemos dado vuelta, lo hemos extraído, lo hemos hecho.
Porque esta es la clave de los custom hooks.
Hemos creado una caja negra en la que constantemente estamos iterando en ella,
sin necesidad, mientras se cumpla de nuevo el contrato que hemos dicho que,
oye, en movies vas a tener la lista de películas.
Y en getmovies vas a tener una forma de recuperar las películas.
Fíjate que con algo tan sencillo hemos creado una cosa súper potente.
Porque cumpliendo siempre ese contrato, nos hemos encajado aquí en el usemovies
y hemos transformado algo que era un mock a un fetching de datos.
Hemos extraído el servicio.
Y a partir de aquí, incluso, lo bueno es que ahora lo podemos extender.
Podemos llevar más allá este custom hook.
Podemos ponerle un loading.
Le podemos poner el error también, por si queremos que esto nos diga si tiene algún error.
Y para empezar a generar todo esto, sin romper en ningún momento la compatibilidad,
aquí podríamos poner el try catch, para tener esto por aquí.
Cada vez que antes del try, pues hacemos setLoading.
O sea, siempre que intentamos recuperar las películas.
Aquí tenemos el true.
SetError.
Antes decimos el null para volver a refrescar el valor ese.
Si tenemos un error, pues ponemos el setError.
Le ponemos el e.message.
Aquí podéis hacer un montón de cosas.
Y podemos utilizar el finally para pasar el softLoading a fall.
En el finally, que es una cosa que mucha gente no conoce, pero tienes trash, try, catch, finally.
Y el finally sería lo que entraría tanto si esto ha sido correcto como si pasa por el catch.
O sea, esto se va a ejecutar tanto en el try como en el catch.
¿Vale?
Es una cosa que se haría después del try y después del catch.
¿Vale?
A ver, está cambiando de lista de reproducción y como tenga.
Así que es súper importante porque de esta forma hemos asegurado de que siempre...
Una cosa, un error que veo muchas veces, ¿no?
Que es esta...
Yo no soy muy fan.
Hay gente que no le gusta el finally, pero en este caso yo creo que te dé todo sentido el mundo.
¿Por qué?
Porque semánticamente como que te dé más sentido el hecho de decir, oye, pase esto o pase lo otro,
yo haría finalmente el loading pasa a ser fall.
Si lo preferís, lo podéis hacer así.
No hay ningún problema.
Si lo veis más claro que en el finally, podéis utilizar el finally.
¿Vale?
Pero cualquiera de los dos, que lo tengáis claro.
Con esto, en un momentito, en un momentito de nada, lo que hemos hecho ya es, pues...
Vale, es verdad que no estoy enseñando el loading, pero fíjate, si ahora me vuelvo a mi app,
yo aquí en el movies ya tengo un loading.
Y en este loading, yo aquí en movies ya podría poner en lugar de movie, pues loading.
Vale, si está haciendo loading, tal.
Mira, cargando.
Y si no, vamos a poner el movies, no sé qué, no sé cuál.
Por ejemplo, con esto tan sencillo...
Bueno, ha sido un poco rápido.
Un poco rápido ese loading, me parece.
Claro, es que no se va a ver.
Es que tarda muy poco la app.
Que podemos buscar, que sea algo que...
Yo qué sé.
Igualmente no se ha visto, ¿no?
El loading.
Igual es que algo no hemos hecho ahí.
Bien.
A ver...
Ah, coño, es que no lo estoy sacando.
Perdón, ¿eh?
Que lo he hecho así...
Vale, ahora sí que se ve el loading.
El loading.
Muy poco, ¿vale?
Muy poco, pero ahora sí que se ve.
¿Veis?
Cargando.
Pero bueno, en un momento hemos hecho el loading.
Y esto es muy importante que entendáis esto.
Porque muchas veces esto dice, bueno, es que React Query, es que no sé qué.
Oye, está súper bien.
Luego más adelante veremos alguna de estas herramientas.
Pero esto es para que vea realmente cómo funciona por detrás, ¿vale?
Cómo funciona por detrás es básicamente tiene tres estados donde el loading lo haces
justo antes de hacer el fetching de datos y después el loading lo pasas a false.
Cambia el estado en el custom hook y esto lo puedes recuperar.
Punto.
Pim, pam, pum.
Ya está, ya lo tienes, ¿no?
Ahora, vamos a empezar a trabajar con los conceptos de UREF.
Use callback, use memo.
Y vamos a volver otra vez con el UREF porque te quiero enseñar de nuevo por qué es importante
el UREF.
Mira, si te fijas tenemos un problema.
Porque en el Ritme nos dice, bueno, esto lo tenemos, ¿no?
Check y check.
O sea, ya los requerimientos los hemos hecho.
Dice, evitar que se haga la misma búsqueda dos veces.
Esto lo preguntan en pruebas técnicas y es muy chulo porque lo que te hacen es ver si
has entendido el UREF.
Se puede hacer de otras formas, piratas, que te voy a enseñar también, pero con el UREF
es como tema.
Entonces, fíjate que yo, si le doy aquí al buscar, otra vez.
Ahora entramos a los sitios, a cosas muy chulas.
Si le doy a buscar, ¿vale?
Fíjate que otra vez cargando, cargando, cargando.
O sea, estoy volviendo a hacer otra vez la misma petición.
Pero no tiene mucho sentido porque dices, a ver, si estás buscando lo mismo, estás
buscando lo mismo.
¿Cómo podríamos asegurarnos que hay muchas formas?
Lo podríamos hacer de muchísimas formas.
El hecho de evitar que busquemos exactamente lo mismo.
Te voy a enseñar una, podrías hacerla de otras formas, yo te voy a enseñar esta y ya.
¿Por qué?
Porque muchas veces podemos jugar con el UREF para tener el estado anterior.
Entonces, por ejemplo, podríamos utilizar aquí el UREF.
Vamos a poner UREF.
¿Qué era el UREF?
A ver, ¿alguien se acuerda?
Que me lo diga en el chat.
¿Qué era el UREF?
Con Redux.
Con Redux.
Sí, la madre que os parió.
Con Redux.
La madre que os trajo.
Capaces seríais encima.
Lo guardas en estado y si es igual, return.
O sea, muy mal.
O sea, tener dos estados para lo mismo.
O sea, tiene muchos.
Algo mutable que persiste.
Muy bien, programador 420.
Algo que persiste aunque se rendirice nuevo.
Muy bien.
Ay, te mato.
Una función para referenciar el nodo del DOM.
Otro, de Fenapuros.
También te mato.
Que no es eso.
Que eso está mal, ¿eh?
Crear una referencia de un elemento del DOM.
La madre que os parió.
Que no es para guardar una referencia de elemento del DOM.
Es que no sé si me lo está diciendo en broma o si me lo está diciendo en serio.
Y lo peor es que creo que mucho me lo está diciendo en serio.
Porque como lo dicen todos los tutoriales que hay ahí en internet, ahí fuera.
Me ponen los nervios.
Porque seguro, seguro.
Es que lo dicen en tantos sitios que seguro que mucho me lo está diciendo en serio.
Os mato.
A ver.
En este caso, vamos a utilizar el UREF.
Para guardar la búsqueda anterior que habíamos.
Entonces, aquí podemos inicializarlo como que queráis.
Lo voy a inicializar con el search.
Total.
Esto se lo inicializa una vez.
El PreviousSearch, lo que podemos hacer antes del try.
Podría decir, if el search que queremos hacer es igual al PreviousSearch.Current.
Hacemos un return.
Y ya está.
Y obviamente, antes de hacer...
Lo podemos hacer...
Yo creo que lo ideal sería hacerlo antes.
Antes de hacer la llamada, pues podríamos actualizar el PreviousSearch.Current.
Y con esto, ahora, si nos ponemos por aquí y ponemos Panther, Enter y le damos otra vez.
Vale.
Fíjate que sí, le das al botón, pero ahora no está haciendo la llamada.
O sea, aquí podemos ver que ya no está haciendo la llamada.
Si ahora, por lo que sea, cambio esto y pongo Avengers y le doy aquí a buscar, ahora sí que ha funcionado correctamente.
Pero si intento darle otra vez, ya no me deja.
Porque hemos guardado la referencia gracias a esto.
Y como no se cambia por renderizados, esto nos está permitiendo que funcione.
Claro.
De nuevo, imagínate que hago esto.
PreviousSearch.
¿Vale?
Imagínate que hacemos esto.
Vamos a ponerle search.
Se le puede poner lo que te haga.
Pero imagínate que hacemos esto.
Y esto PreviousSearch.
Esto no funcionaría.
Esto, obviamente, no funcionaría.
Esto...
Bueno, aparte de que...
A ver.
AvengersCurrent.
Bueno, ni siquiera...
A ver, no sé por qué ahora ha petado.
No sé si es que me ha petado la app y ya me ha...
Bueno, es que antes se me ha quedado penchado.
Pensa aquí que se vuelve un poco loco.
A veces me da la sensación que se queda tonto, ¿eh?
Bueno, de hecho...
Bueno, claro, es que aquí...
Claro, es que, claro, esto no tiene sentido.
Es que no tiene sentido porque siempre está entrando en el...
Es que no va a funcionar.
No va a funcionar porque no tiene sentido que funcione, ¿eh?
Buscar...
¿Ves?
Es que no funciona.
Esta no es la forma de hacerlo.
Entonces, os voy a explicar una forma mala de hacerlo.
Y os voy a explicar por qué.
Alguien puede decir...
Oye, ¿y si en lugar de usar el UREF lo ponemos aquí y fue?
Y entonces te quitas el UREF y haces eso.
Y esto, haces eso.
¿Esto funcionar funcionaría o no?
¿Qué decís?
¿Funciona o no funciona?
¿Funcionaría esto o no?
Y Valoliniers dice que no.
Agus dice que sí.
Hay gente que no, dice que sí.
Hay gente que no.
O sea, estoy por hacer un predict, ¿eh?
Estoy por hacer una predicción, va.
Iniciar predicción, va.
¿Esto funciona?
A ver si soy capaz de hacer la predicción porque tengo tan poco espacio aquí.
¿Esto funciona?
¿Sí?
¿No?
Venga, tenéis un minuto.
Dos minutos para participar y os voy leyendo, ¿vale?
Os voy leyendo.
Venga, venga.
Predigan, ¿vale?
Hay gente que dice que siempre sería el stream vacío.
Falta la opción, no sé.
Depende de tu corazón.
Depende de tu corazón.
Si lo miras con mucho cariño, como siempre depende.
Ah, bueno, esa es una buena.
Pero funcionar, ¿funcionaría?
En este caso, ¿funcionaría o no?
Depende de bit.
Está claro que funciona, pero es mala práctica.
Dice Dani BCN.
Yo he visto que funciona, pero sentía que estaba mal.
No sé, pero aquí estoy.
Alejandro, muy bien.
¿En mi duda de dónde sacas estos retos?
¿De dónde sacas retos?
De la vida.
Vale, usted con Dios sí funciona, pero solo si tienes una única instancia del componente.
Dicen por aquí.
¿Creería que no?
¿En mi local funciona?
¿Pon el código?
Pongo el código, pongo el código.
La pregunta es, ¿este previous search funcionaría y evitaría que hagan?
Haga lo que vuelva a hacer la misma búsqueda.
¿Funcionaría o no funciona?
¿El render del componente afecta a todo, no solo a la función?
Eso creo.
¿Midu, podrías pasar página donde hacer pruebas técnicas?
Bueno, pues aquí estamos, Iván.
Qué bonito, retos de la vida.
Si JavaScript lo permite aunque no esté definido antes.
No está definido antes.
¿Y se agrega una nueva película después de la primera búsqueda?
¿Se actualiza la lista?
No, obviamente no, Ortega, porque no hacemos otro fetch, pero tiene sentido.
O sea, no esperamos que se añadan películas ahí constantemente, ¿no?
También podemos hacer que eso se guarde X tiempo, por ejemplo.
Podríamos hacer.
Podríamos hacer que solo se evite la búsqueda durante un minuto o 30 segundos.
O sea, se pueden hacer un montón de cosas.
No porque no se guarda el search de la prop.
No porque no se guarda el search de la prop.
Dice que no se guarda el search de la prop, pero está aquí, ¿no?
Se está guardando el search de la prop.
Aposté todos mis ahorros.
Conociendo a JavaScript te deja.
Esta madre te deja hacer de todo.
Y si quiero mostrar resultados filtrados por carácter en el input,
¿serían muchos consultas?
No lo sé.
Mostrar resultados filtrados por carácter en el input.
Bueno, eso lo vamos a hacer después, ¿eh?
Eso lo vamos a hacer.
No porque no están en RAM.
Sí funciona.
Bueno, bueno.
Bueno, pues ahí hemos tenido la predicción.
Vamos a probar si funciona o no funciona, ¿vale?
Vamos a Avengers.
Sí que funciona.
La predicción es que sí que funciona.
O sea, sí que funciona.
Esto nos ha evitado justamente lo que queríamos.
Sí que funciona.
Pero, pero, funciona.
Pero está mal.
Lo siento.
Pero está mal.
Entonces, funciona.
Sí, completad predicción.
Ahí los tenéis.
¿Por qué sería mala práctica?
Porque alguien, alguien ha dicho, y lo ha dicho muy bien, que funcionar funciona.
Es verdad.
Funciona.
Pero esto funciona porque solo estamos utilizando el custom hook una vez.
¿Qué significa esto?
Esto significa que los módulos, esto es muy importante y muy básico de JavaScript.
Pero, como muchas veces a la gente le gustan los atajos.
Vamos a ver.
Los módulos en JavaScript son instancias únicas.
Son como Singleton.
Y, por lo tanto, esta variable se va a compartir allá donde importemos este custom hook.
¿Qué significa?
Que, claro, nosotros en este app.jsx estamos utilizando este useMovies.
Y aquí funcionaría.
Pero imagínate que por lo que sea, por lo que sea, aquí dentro de Movies, pues también queremos importar esto.
Imagínate que cuando no hay resultados, vamos a hacer esto.
Cuando no hay resultados, también queremos enseñar esto.
Y lo queremos utilizar aquí, porque yo qué sé, por patata.
Claro, cuando tú estás utilizando esto, se estaría utilizando exactamente la misma variable.
Por lo tanto, estaríamos como utilizando la misma, el mismo valor para todas las veces que utilices ese hook en diferentes archivos.
Por lo tanto, estaría mal.
O sea, no es una buena plata.
Por eso hay que evitarlo muchas veces.
A no ser que tengas clarísimo que quieras que sea algo único en toda tu aplicación, esto es una cosa que deberías evitar.
Y en el caso de este custom hook, está clarísimo que queremos evitarlo.
Porque este custom hook tiene que funcionar sin esto.
Tiene que funcionar allá donde se quiera utilizar.
Este custom hook, a lo mejor no lo utilizamos una sola vez en la aplicación.
Quizás sí, pero no debe depender de eso.
Así que en este caso, tened en cuenta que lo correcto sería utilizar el UREF.
Funcionar funciona, pero lo correcto sería utilizar el UREF.
Y así el UREF, como es algo interno del hook, aunque tú este hook lo utilices en dos, tres, ocho sitios diferentes, siempre va a tenerlo de forma interna.
Así que, tenedlo en cuenta.
Súper importante.
Súper, súper, súper, súper importante.
Vale.
Entonces, ya hemos hecho lo de evitar la misma búsqueda.
O sea, que esto, evitar la misma búsqueda, check.
Vamos con más cositas.
Mira, vamos a hacer publicidad en Discord.
Que a lo mejor la gente se quiera en el café.
Hola, everyone.
Vamos a empezar, porque sé que la...
Vamos a empezar a explicar, use memo, use callback de Ria.
Luego no me digas que no te avisé, que os conozco.
Luego, es que no mentiré, es que no sé qué.
No me gusta el café.
Pues bebe, de a gato.
¿Cómo no te va a gustar el café?
Hombre, si eso le gusta a todo el mundo.
Dios mío, ¿cómo no te va a gustar el café?
Bueno, ahí lo...
Vale.
Haz que la búsqueda se haga automáticamente al escribir.
Bueno, esto es una cosa que nos van a comentar 80.000 millones de veces.
Pero, os quiero comentar, os quiero explicar otro hook muy interesante, que es el de use memo.
Y cómo lo podéis utilizar, cuándo utilizarlo, porque a veces es buena idea, porque a veces no es tan buena idea.
Vamos a hablar de todo eso y mucho más.
¿Qué vamos a hacer?
Mira, vamos a hacer un app.jsx y vamos a añadirle un nuevo estado, pequeñito, para ordenar las películas por año.
Vamos a poner short, short, set short y vamos a poner aquí false.
Lo único que hace es ordenar, nos va a indicar si ordena o no por año las películas.
Vamos a poner el handle short.
Esto es lo que va a cambiar el set short entre estados, ¿vale?
Para hacer activo o desactivo, para activarlo o desactivarlo.
Y vamos a poner al lado del input, este...
Bueno, no sé si al lado del input, un input de tipo checkbox, ¿vale?
Que se va a cambiar, vamos a hacer handle short y el check sea el short.
Así que vamos a ver.
Vale, aquí ya tenemos nuestro pedazo de checkbox.
Ahora, ¿qué queremos hacer con esto?
Lo que queremos hacer con esto es que este short lo vamos a pasar a use mode, ¿vale?
Le pasamos este parámetro y en use movies lo vamos a tener aquí, en short.
Y lo que hacemos en este short, una vez que tenemos las películas, antes de devolverlas,
vamos a hacer una...
Short movies.
Vamos a...
Bueno, vamos a hacerlo por título.
En lugar de año, porque creo que hay algunas que tienen...
Vamos a hacerlo por título, ¿vale?
Vamos a hacer que este checkbox las ordene por título, de forma alfabética o no.
Entonces, si lo tenemos, el short lo tenemos activados, aquí es súper importante.
Vamos a hacer una copia del array de objetos, ¿vale?
Y ponemos short.
Tenemos A y B.
Ya sabéis que el short lo que hace es comparar entre A y B.
Pero aquí vamos a utilizar el título de cada uno.
O sea, el A.title lo vamos a hacer con el local compare del B.title, ¿vale?
Vamos a comparar los strings.
El local compare lo que hace básicamente es comparar de forma local, o sea, con acentos,
porque si no vamos a tener problemas.
Si no utilizamos el local compare, imagínate que tiene la A un acento.
Si no utilizas el local compare, va a hacer la comparación incorrecta,
porque no va a tener en cuenta que el A con acento debería estar al lado de la A.
Y si no, va a pensar que está mucho más adelante, ¿no?
Esto, si tenemos el short, pues los ordenamos.
Y si no, pues le pasamos las películas exactamente igual.
Y este movies se lo pasamos por aquí, ¿vale?
Vale, vamos a ver si esto funciona.
Primero, Avengers.
Y ahora le doy aquí.
Está ordenando ahora por título.
Le doy otra vez.
Sale como viene con el orden.
O sea, le doy, ¿vale?
Fíjate que cuando le doy clic, me lo está ordenando por título.
Aquí lo tenemos ordenado por título y parece que todo funciona bien.
O sea, el último es la U, tiene sentido.
Y cuando lo quitamos, pues está ordenado por como viene la A.
Vale, fíjate.
Fíjate, ¿qué pasa?
Fíjate que vamos a ver unas cuantas cosas.
Voy a poner aquí un console.log.
Console.log es de render, por ejemplo.
Render.
Y vamos a poner sorted mode.
Muy bien.
Vamos a poner aquí un console.log.
Esto se está quejando, Betta, ¿sabes por qué?
Cada vez que yo le doy, es normal que vuelva a renderizar.
O sea, tiene sentido porque al final, cada vez que le doy, tiene que volver a renderizar y cambiar el orden de mis películas.
Claro, si cada vez que le doy al check, cambia este sort, tiene que volver a ordenarlas y tal.
Pero resulta que si yo cambio el input, también se vuelve a renderizar.
Se vuelve a renderizar y vuelve a ordenar las películas.
Vuelve a ejecutar todo este código.
Está volviendo a hacer el sort.
Imagínate que tuviéramos que hacer un sort de 10.000 películas.
¿Qué es lo que está pasando?
Como el search le llega aquí como parámetro, cada vez que cambia el search, dice, ah, pues voy a volver a ejecutar el cuerpo de la función.
Y esto lo tenemos en el cuerpo de la función.
Y por lo tanto, cada vez que escribimos aquí, fíjate que está volviendo a hacer el mismo sort.
Si no te lo crees, vamos a verlo de otra cosa.
De forma, hace otra forma, ¿no?
Vamos a hacer getSortedMovies.
Vamos a hacer esto.
Esto lo vamos a meter dentro.
Vamos a hacer aquí, returnSortedMovies.
¿Vale?
Y aquí vamos a devolver getSortedMovies de movie.
¿Vale?
Y vamos a poner aquí un console.log, getSortedMovies, para ver si se ha ejecutado o no se ha ejecutado.
Entonces, buscamos Avengers.
Fíjate que se está ejecutando ya, aunque buscar.
Ahora, si yo le doy aquí, es normal que se ejecute.
¿Vale?
Tiene sentido que se ejecute porque quiero cambiar el orden.
Pero fíjate que cambio el search y se ejecuta también.
O sea, esto es una cosa que a mucha gente en React le cuesta.
Que no entiende que el cuerpo de la función de React es el render.
Todo lo que está en el cuerpo de la función, en este caso no es un componente, es un custom hook, pero le pasa lo mismo.
Si esto lo hiciésemos también en un componente, lo hiciésemos aquí, también pasaría.
También pasaría exactamente lo mismo.
Y es porque todo el cuerpo de la función es el render.
¿Qué pasa?
Que los hooks son un poco especiales porque estos hooks, que justamente todo da React, esto no se vuelve a inicializar.
Sino que guarda la referencia anterior.
Que como hemos visto que pasa con el useRef, con el useState, el useEffect.
Esos tienen como unas reglas especiales.
Pero esta función que veis aquí, se está recreando cada vez que se está renderizando el cuerpo del componente o del custom hook.
Y este método que lo estamos ejecutando aquí, getSortedMovies, se está ejecutando cada vez que se vuelve a renderizar el componente o el custom hook.
O sea, súper importante tener esto cristalino.
Porque obviamente vamos a querer evitar que esto ocurra en algunas ocasiones.
Entonces, imagínate de nuevo que tenemos en lugar de 20 películas, tenemos 1000 películas.
¿Tú te crees que si tuviéramos 1000 películas, cada vez que yo cambio el input, voy a querer que si no cambia esto, las vuelva a renderizar?
¿Que vuelva a ejecutarlo todo y a ordenarlas?
No tiene sentido.
Estaríamos haciendo trabajo de más.
No tiene sentido.
Para eso existe el custom hook de useMem, que lo que hace es memoizar, no memorizar, memoizar, memoizar un valor para no tener que volverlo a calcular dependiendo de unas dependencias.
O sea, de una lista de dependencias.
¿Cómo lo tenemos que utilizar?
Mira, lo que tenemos que hacer aquí, voy a poner esto por acá para que lo veamos clarísimo.
Lo voy a comentar.
He importado useMemo de React.
Lo que vamos a hacer es evitar tener que volver a ordenar esta lista si no ha cambiado.
Así que aquí lo que vamos a hacer es tener, vamos a tener otra vez la constante de sortedMovies.
Pero lo que hacíamos antes aquí era justamente esto, ¿no?
Esto de aquí lo hacíamos aquí, lo hacíamos sin esto, claro.
Hacíamos algo así, hacíamos algo así, ¿no?
Teníamos el sortedMovies, no sé qué.
Ah, vale.
Y aquí le pasamos el sorted.
No, hacíamos algo así.
Y con esto ya teníamos lo del sorted, así lo estábamos ordenando.
Este cálculo, esto es un cálculo que queremos memorizar, que queremos decirle,
este cálculo, esta computación, quiero que la evites y que solo la hagas cuando cambia cierta información.
¿Qué información la que queremos que cambie?
Vale, le decimos useMemo.
Le pasamos un callback y le decimos cuál es el cálculo que queremos que hagas solo cuando cambian las dependencias.
Aquí tendríamos como useEffect las dependencias.
Por ejemplo, ¿qué dependencias son las que queremos que tengan en cuenta y que esto se vuelva a ejecutar y se vuelva a calcular cada vez que cambien esas dependencias?
Lo que queremos es que cuando cambie el sort, ¿por qué?
Porque cada vez que cambia el sort, obviamente, las películas tienen que cambiar de orden.
O también cuando cambien las películas.
Así que cuando cambia el sort o que cuando cambien las películas, entonces me vuelves a calcular eso.
Si no cambia el sort o no cambia las películas, el valor de sorted movies lo mantienes exactamente.
Y para eso, vamos a verlo, MemoSortedMovies.
Voy a poner esto aquí, ¿vale?
Vamos a poner esto por acá.
Ponemos aquí Avengers, ¿vale?
En normal han cambiado las películas.
En normal ha cambiado el orden.
Y ahora, ahora no está volviendo a calcular el sort.
¿Por qué?
Porque aunque estamos cambiando el search, el search está haciendo que se ejecute de nuevo todo esto.
Pero esto no lo necesita.
Porque fíjate que como no es una dependencia, está diciendo, vale, ha cambiado el search.
Pero el search no es una dependencia que tengo aquí, por lo tanto, no me interesa.
Voy a mantener que lo que había calculado antes sigue estando vigente.
Y voy a devolver exactamente lo mismo.
Y no está entrando a este console.log.
No está ejecutando el cuerpo de esta función.
Esta es la forma en la que estamos haciendo, obviamente, que nuestro componente,
ahora sea mucho más óptimo.
Porque en lugar de tener que hacer todo el cálculo cada vez que se está renderizando,
solo lo hace cuando lo necesita.
Por ejemplo, que cambiamos el orden dándole aquí.
Claro, es normal.
Cada vez que cambiamos el orden, es normal que lo vuelva a renderizar.
Que cambiamos las películas, que ponemos Matrix y le damos a buscar, ¿vale?
Es normal.
Pero fíjate que ahora cuando cambio el search, ya no tenemos el problema.
Ahora no está volviendo a calcular todo el sort.
Así que para eso es justamente el useMemo.
El useMemo es para poder memorizar computaciones que hemos hecho
que queremos evitar que se hagan a no ser que cambien las dependencias
que nosotros le estamos indicando.
¿Se podría haber usado useEffect para ese mismo ejemplo?
¿Qué diferencias se tiene con useMemo?
Son totalmente distintos, ¿no?
UseEffect es para ejecutar efectos.
Y el useMemo es para guardar, como hemos dicho, para memorizar totalmente
dependiendo de las dependencias.
Claro, ¿se puede utilizar useEffect?
A ver, podríais hacer el useEffect utilizando una referencia.
Podrías utilizar con el useEffect, con una referencia, pero mucho más difícil.
No creo que tenga mucho sentido.
Pero bueno, esto es el useMemo, que muchas veces mucha gente se vuelve loca con el useMemo.
Ahora, aviso para navegando.
El useMemo, como hemos visto, sirve para eso.
Pero el useMemo no tienes que utilizarlo en todos los sitios.
No pasa nada.
Muchas veces vale más la pena que se haga un pequeño cálculo cada vez que se renderiza,
que pueden ser microsegundos, no milisegundos, microsegundos, que no el hecho de utilizar
el useMemo en todos tus componentes, en todos los sitios.
O sea, asegúrate que realmente tienes un problema de rendimiento antes de utilizar useMemo en todos los sitios.
Ahora no te vuelvas loco en todos los sitios que está utilizando un filter o lo que sea,
estar constantemente utilizando useMemo.
¿Dónde tiene sentido?
Pues aquí, imagínate.
Aquí, imagínate que tuviésemos un array de mil elementos.
Pues seguramente tiene sentido porque queremos evitar que cada vez que cambia el input se vuelva a hacer el sort.
Pero si tenemos un array de 10 elementos, seguramente te vale más la pena que lo hagas y ya está.
Y que no te hagan ningún tipo de... ¿Vale?
Así que este sería el tema del use.
Ahora bien, estamos viendo una cosa muy interesante, ¿no?
Porque hemos guardado un valor.
Estamos guardando un valor, lo estamos memorizando.
Pero, ¿qué pasa?
Como te he dicho, este getMovies se está volviendo a recrear cada vez.
Cada vez que estamos tocando aquí, cada vez que yo escribo una letra, se está volviendo a crear este método.
Esta función se está destruyendo y creando, destruyendo y creando.
Y si no me crees, lo podemos ver muy fácil.
Mira, vamos a poner un useEffect en el app.jsx.
Y vamos a decirle que tiene dependencia el getMovies.
Fíjate, vamos a poner aquí new getMovies receive.
El useEffect ya sabéis que es un hook que te permite ejecutar código cada vez que cambian sus dependencias o la primera vez que se renderiza el componente.
Vamos a decirle, oye, este efecto se tiene que renderizar cada vez que reciba un nuevo getMovies.
Pues vamos a ver cuántas veces se ejecuta este console.log.
Vamos a ver.
Voy a quitar este console.log de aquí, ¿vale?
Vamos a dejar esto por aquí.
Venga.
Nada más empezar, ya sabéis que aparecen dos veces las cosas porque estamos en stripMode.
Para que no liéis, lo voy a quitar porque tampoco es muy útil en este caso y no le estamos sacando mucho partido.
Vamos a quitar esto, esto por aquí, ¿vale?
Y así lo veremos una sola vez y no volveré a irlo.
Entonces, vamos a ver.
Cada vez que recibe un nuevo getMovies, vamos a ver esta console.log.
Vamos a ver cada vez cuándo lo recibe.
Ojo, fíjate.
Cada vez que estamos escribiendo en el search, cada vez que escribes en el search, se está volviendo a crear una nueva función getMovies.
Pero, ¿realmente esto es necesario?
O sea, ¿realmente tiene sentido que se esté volviendo a generar esta función en cada renderizado?
Seguramente no, ¿no?
Porque lo que estamos viendo es que, fíjate el trabajo por haber hecho el input controlado, todo el trabajo que estamos haciendo.
Claro, ahora vemos que cada vez que yo estoy escribiendo en el input, se está volviendo a generar esta función getMovies todo el rato.
¿Por qué?
Porque está cambiando el search.
También cuando cambia el search.
Claro, cuando tú le das aquí, pues también new getMovies.
Porque, como te he explicado antes, el cuerpo del custom hook o del componente se vuelve a ejecutar cada vez que se renderiza.
Así que, como esto es una función que tenemos aquí, pues cada vez que lo estamos haciendo, pues ahí lo tenemos, ¿no?
¿Qué podemos hacer?
Bueno, ya hemos aprendido con el useMemo aquí que podemos evitar que lo genere a no ser que lo necesitamos.
Y esto no solo funciona con computaciones, también funciona con funciones.
Y lo vamos a poder hacer aquí.
Aquí podemos hacer, en el getMovies, podemos decirle, bueno, pues quiero tener aquí un useMemo, ¿vale?
Que esto devuelve una función.
En lugar de un valor, como estábamos haciendo en el sort, ¿no?
Aquí estamos devolviendo un valor.
Lo que vamos a hacer es que devuelva una función.
Entonces, cerramos esto aquí, ¿vale?
Aquí tenemos el useMemo.
Y lo que vamos a decirle es cuáles son las dependencias que tienen que cambiar para que esta función se vuelva a crear.
En este caso, si nos ponemos a mirar, ¿ves?
Tenemos aquí el search.
Tiene sentido, ¿no?
Cada vez que cambia el search, tenemos que volver a generar esta función.
Porque dentro estamos utilizando el search.
Si no generamos la función cada vez que cambia el search, vamos a tener problemas.
Que ahora lo veremos, si queréis.
Pero vamos a tener que generar esta función.
Esta función que devolvemos, la generamos cada vez que cambie esta dependencia aquí, que es el search.
Cada vez que cambia el search, vamos a ejecutar este cuerpo de la función.
Devolvemos una función y getMovies tendrá esta función, ¿vale?
Guardamos los cambios.
Nos vamos aquí.
Y vamos a ver ahora cuántas veces se genera.
Avengers.
Esto tiene sentido porque está cambiando el search, ¿no?
O sea, tiene sentido que por ahora pasa.
Le damos a buscar.
Pero fíjate que ahora, si le doy aquí, ojo, ahora no se está volviendo a crear.
Al menos, ya hemos evitado, fíjate que hemos evitado, que cuando hago el search, ahora no pasa.
También cuando, por ejemplo, si ves, ahora sí que pasa porque estamos cambiando el search, ¿vale?
Matrix.
Quitamos esto.
Pero si le doy a buscar, se han actualizado las películas y no se ha vuelto a crear la función.
¿Por qué?
Porque hemos hecho que solo cuando cambia el search, realmente lo tenga que hacer.
¿Qué pasa?
Que si esto lo dejamos vacío, vamos a asegurarnos, Avengers, claro.
Le doy al enter y ¿qué ha pasado?
No funciona.
No funciona.
¿Por qué no funciona?
Porque como solo hemos creado la función la primera vez, la primera vez que se ha renderizado,
ha dicho, voy a crear la función.
¿Y qué pasa?
Que la primera vez que se ha renderizado, el valor de search, search, es un stream vacío.
No, previous search, no, Batman, Guijacopalo, no fumes cosas.
Search es un stream vacío.
Y claro, le estamos diciendo, oye, memoriza esto de aquí la primera vez.
Como nunca, no hemos dicho que tiene que volver a generar la función nunca, pues lo que pasa es que el search se queda con el stream vacío.
Y por más que tú haces aquí, ves que no se está volviendo a generar esa función.
Por más que escribo, pues no se está generando la función.
Claro, le tenemos que decir, oye, es que en este caso estamos dependiendo de search.
De esta forma, cada vez que cambie el search del input, se va a estar generando una nueva función donde va a tener acceso al nuevo valor de search.
Esto es para que veáis justamente cómo funciona el useMemo.
¿Por qué? Es una cosa que hay que tener en cuenta muchas veces, de tener cuidado, porque podéis cometer errores como este, que se os olvide una dependencia y por lo tanto causar que vuestra UI esté rota, como hemos visto, ¿no?
En este caso necesitamos que tenga el search.
Y otra cosa es que hay veces que a lo mejor no es importante utilizarlo, a lo mejor no es interesante.
En este caso os estoy enseñando para que veáis, ¿no?
Puede ser interesante utilizarlo por esto, ¿no?
Por el useEffect, si tenéis un efecto que depende tanto del valor como de una función.
Vamos a darle una vuelta a esto porque esto todavía se puede mejorar, ¿vale?
¿Por qué?
Porque lo que me gustaría es poder intentar solo construir esta función una vez.
Porque he visto que obviamente si le dejo el search, cada vez que escribo aquí, fíjate que yo cada vez que escribo, se está volviendo a crear la función.
Y esto lo quiero evitar.
¿Cómo lo puedo hacer?
Bueno, vamos a hacer que solo se genere una vez, pero fíjate, vamos a darle una vuelta.
En lugar de depender este search del search que le viene por aquí, vamos a hacer que se le inyecte por parámetro.
Y esto vas a ver que es algo muy típico para poder generar las funciones una sola vez.
Así que aquí vamos a inyectarle el search, se lo vamos a hacer por parámetro.
En lugar de depender de este, vamos a depender del que se le pasa por parámetro.
Así creamos una vez la función y en el app.jsx, que estábamos utilizando aquí el getMovie, le podríamos pasar aquí el search que tenemos.
¿Qué es lo que vamos a conseguir con esto? Bueno, se lo voy a hacer con nombrado, que me gusta un poco más.
Que lo he hecho así.
¿Qué es lo que vamos a conseguir con esto?
Lo que vamos a conseguir es que como ahora depende del valor que le estamos inyectando por parámetro,
no tiene que depender del otro y podemos crear la función una sola vez.
Y ahora podemos ver a ver si esto funciona, si lo he actualizado todo.
Avengers, ¿vale?
No se está creando la función, como podéis ver.
Avengers, buscar.
Y ahora sí que funciona.
Fíjate la diferencia.
Hemos empezado generando, regenerando esta función cada vez que se renderizaba,
a terminar, a generar esta función solo la primera vez, solo la primera vez.
Y le hemos inyectado el search por parámetro.
Ya está.
Pim, pam.
Esto es simplemente como para optimizar el rendimiento de nuestra aplicación,
si sobre todo realmente tenemos un problema de rendimiento.
No empecéis a optimizar si no sabéis medir.
Si no sabéis medir, pues mejor aseguraos que realmente tenéis un problema.
¿Cómo identificamos problema de performance?
Mira, en ese caso, lo mejor que podéis hacer para ver si tenéis problema de performance,
esto lo vimos en una de las clases anteriores, es utilizar el profiler, ¿no?
En el profiler, de hecho, una cosa que está interesante aquí, que podríais ver,
es el que se está renderizando, que no se está renderizando y todo esto.
Esto lo podemos ver aquí.
A ver, voy a quitar para que veamos esto.
Vamos a poner que esto se cambie en el search.
Vale, lo ponemos aquí.
Y aquí, cada vez que escribáis Avengers, y le damos aquí,
vais a poder ver cuántas veces se ha renderizado,
qué es lo que ha hecho, todos los cambios que ha tenido.
El tiempo que le ha dedicado.
Una cosa que es interesante es que podáis ver,
claro, esto es una aplicación muy sencilla.
Normalmente, cuando tienes una aplicación mucho más tocha,
pues vas a poder ver con mucho más detalle, ¿no?
Entonces, de hecho, esto lo vamos a ver también en la siguiente clase.
Vamos a ver el tema del rendimiento con mucho más detalle, ¿vale?
Pero lo que podéis ver es cuánto tiempo ha tardado.
En este caso es que es una aplicación muy sencilla, ya os digo,
y es difícil que encontréis algún tipo de cambio.
Si tuviésemos muchos más elementos,
igual sí que podríamos encontrar algún tipo de problema.
También se puede ver análisis mediante PageSpeed Insights.
Son como dos cosas diferentes,
porque PageSpeed Insights sería como la big picture,
y esto sería más la small picture, ¿no?
Al detalle.
El profiler, esto es una extensión de React,
que se llama React Developer Tools,
y entonces en las herramientas de desarrollo se aparece.
Ya he comentado lo del UseMemo versus UseEffect,
son dos cosas diferentes, Manu.
No tienen nada que ver.
Es que no es un versus, porque no tienen nada que ver, ¿sabes?
O sea, no es un versus, no tiene sentido.
Porque el UseEffect es para ejecutar efectos
la primera vez que se renderiza el componente
y cada vez que sus dependencias cambien.
Y el UseMemo es para guardar un valor
o para recalcular un valor cada vez que esas dependencias cambien.
Sirven para dos cosas totalmente distintas.
Y es que no son intercambiables, ¿sabes?
No son intercambiables.
Entonces, ¿y cuándo usas UseCallback?
No os preocupéis, que ahí vamos, ¿vale?
Ahí vamos, ahí vamos.
Bueno, el tema es que ya hemos conseguido con el UseMemo,
ya hemos conseguido simplificar esto.
Pero, obviamente, os habréis dado cuenta que, ostras,
es un poco raro, ¿no?
Tener que utilizar el UseMemo,
crear aquí una función que devuelve una función.
Bueno, el tema es que existe otro custom hook muy especial
que te permite facilitar el uso del UseMemo con las funciones.
Y se utiliza, se llama UseCallback.
El UseCallback es lo mismo que el UseMemo,
pero pensado para funciones.
Pero ya ves que puedes utilizar el UseMemo,
porque es que el UseCallback, por debajo, utiliza el UseMemo.
Lo único que te permite el UseCallback es simplificar la sintaxis.
El UseCallback sería lo mismo que el UseMemo,
solo que hacemos UseCallback y ya no hace falta que le pasemos un callback,
sino que le pasamos directamente la función que queremos memorizar.
Y ya está.
Es exactamente lo mismo.
Por debajo, hace exactamente lo mismo.
No es especial, no hace algo extra.
Lo único que hace es una sintaxis azucarada para que sea mucho más fácil.
¿Vale?
Pero por debajo, el UseMemo utiliza...
O sea, el UseCallback utiliza por debajo el UseMemo,
solo que el UseCallback solo y exclusivamente está pensado
para, obviamente, las funciones.
¿Vale?
Así que esa es la única diferencia.
El UseCallback solo lo utilizarías para las funciones.
Pero, por lo demás, son totalmente equivalentes.
El UseCallback utiliza por debajo el UseMemo
exactamente como os acabo de enseñar.
Esto sería con el UseMemo y el UseCallback sería esto.
Una forma más sencilla de escribir exactamente lo mismo.
Por lo tanto, cuando alguien me dice
UseCallback versus UseMemo,
la respuesta es UseMemo para cualquier cosa,
UseCallback para funciones.
¿Vale?
Si es una función, por lo tanto,
siempre vais a querer priorizar el UseCallback.
Si es un valor, como hemos visto aquí abajo,
pues sería el UseMemo.
Ya.
Punto pelota.
¿Vale?
Esto espero que os haya quedado cristalino.
Cristalino.
Use...
¿Me traerás contes para controlar el estado?
Sí, eso lo veremos en la próxima clase.
Lo dice en la documentación.
UseCallback es igual...
Bueno, pues como lo dice la documentación,
pues la respuesta no tiene sentido.
Claro que tiene sentido, ¿no?
O sea, no tiene sentido.
UseEffect versus UseCallback.
O sea, pues ya lo tenéis, ¿no?
O sea, ese sería el UseMemo y el UseCallback.
De hecho, es muy interesante
porque ahora vamos a hacer el de Bounce.
Si volvemos al ReadMe, ¿vale?
Haz que la búsqueda se haga automáticamente al escribir.
Vale, vamos a hacer la búsqueda automáticamente al escribir.
Vas a ver que con todo lo que hemos hecho,
pues va a ser súper fácil, ¿no?
Vamos a hacer la búsqueda al escribir.
¿Cómo lo haríamos?
Bueno, podemos hacerlo de diferentes formas.
Pero aquí en el HandleChange podemos tener aquí
que el GetMovies, pues sea...
Vamos a poner aquí NewSearch,
Event.target.value.
Vamos a actualizar el estado
porque necesitamos que funcione también el botón todavía.
GetMovies, pues aquí le ponemos que el Search es el News.
O sea, cada vez que detecta un cambio en el Input,
también va a hacer la búsqueda, ¿vale?
Así que aquí, si estamos aquí en Avengers,
vamos a refrescar.
Matt...
¿Ves?
Mattrix.
Ya está.
Lo tenemos ahí, ¿no?
Quitamos.
Ya está haciendo la búsqueda cada vez que escribimos.
Tan fácil como en el HandleChange llamar al GetMovies.
Justamente, fíjate cómo de importante y qué interesante es
que hayamos utilizado en Custom Hook.
Porque si tú hubieras utilizado en el GetMovies,
hubieras hecho aquí el fetching de datos,
ahora te enfrentarías al hecho de,
vale, tengo que hacer que esto, replicar, no sé qué, o sacarlo.
Pero en este caso ya lo tenemos totalmente preparado.
Ya tenemos que en el HandleChange ponemos al GetMovies
con el nuevo valor y ya está.
Punto pelota.
Fácil y rápido, ¿no?
Pero, obviamente, esto tiene problemas.
Y es que en el ReadMe nos dice una cosa muy interesante.
Dice, haz que la búsqueda se haga automáticamente al escribir.
Vale, esto lo tengo.
Esto lo tengo.
Pero me dice, evita que se haga la búsqueda continuamente al escribir.
¿Por qué?
Porque, fíjate, voy a quitar aquí el useEffect este que no es útil.
Esto lo quitamos.
Vale, vale.
Fíjate que yo cuando pongo Avengers en la red,
fíjate todas las llamadas.
O sea, cada vez que he puesto A, AV, AB, AVEN, AVENG, AVENG, ¿sabes?
Cada vez que he hecho una búsqueda, ha hecho, ha disparado la API.
Y esto es un problema, uno, de rendimiento y dos, de race condition.
Y te voy a explicar esto.
¿Qué es lo que puede pasar?
De hecho, fíjate en este problema.
Fíjate lo que ha pasado aquí.
He puesto Avengers, pero los resultados no son los de Avengers.
¿Por qué pasa esto?
Esto pasa porque, como es una race condition, una race condition quiere decir que hay una condición de carrera.
en la que hay dos cosas o más que están en paralelo, pero tú no sabes cuál ha terminado antes.
¿Qué pasa?
Que seguramente una de las anteriores ha terminado más tarde de la última.
¿Por qué?
Porque a lo mejor Avengers estaba cacheada, pero he empezado a buscar AVENG.
A lo mejor AVENG ha terminado más tarde.
Y por lo tanto, aunque yo tengo aquí Avengers, fíjate que los resultados son los de AVENG.
Esto es un error muy típico, ¿vale?
Muy típico en millones de...
Entonces, ¿cómo podemos evitar esto?
Esto podemos evitarlo de muchas formas, pero lo mejor que podéis hacer es aprender a utilizar, a crear un debounce.
Un debounce sería, vamos a hacer que el usuario, mientras escribe, no vamos a hacer nada y vamos a esperar a que deje de escribir un tiempo, 300 milisegundos, 500 milisegundos,
para que la última llamada que ha hecho el usuario sea la que realmente vamos a disparar.
Entonces, ¿cómo sería un debounce?
Hay un montón de...
Tienes low dash, debounce, tienes un montón de pequeñas librerías.
Podrías utilizar un custom hook que ya se hubiera hecho, use the bounce...
Hay un montón.
Pero yo te voy a intentar explicar al nivel más bajo cómo hacerlo.
Obviamente, el día de mañana, pues mira, puedes utilizar un custom hook como este, ¿vale?
Fácil y rápido.
Pero yo te voy a intentar explicar una forma de que la podrías hacer para que entiendas como lo que funciona por debajo de RIA.
Para que aprendas RIA.
Para que aprendas RIA realmente.
Entonces, lo podríamos hacer con low dash.
Esto tienes un debounce por aquí, ves, una función debounce.
Y esto lo podríamos...
¿Cómo podríamos utilizar el use callback y un montón de cosas para que funcione?
A mí hay una que me encanta, que siempre la recomiendo.
Es una librería que se llama Just, es de Angus C, y también tiene un debounce.
Y además te recomiendo que le puedas echar un vistazo, porque fíjate, puedes ir al código y es muy fácil de entender.
Porque lo tienes, son 50 y pico líneas y no es muy difícil de entender.
Obviamente lo utilizan con un timeout, que haces un clear timeout.
Cada vez que llamas, tú haces un timeout.
¿Vale?
¿Cómo funciona el debounce por debajo?
Tú lo que haces es un timeout.
Dices, vale, 500 milisegundos.
Un timeout.
Si vuelvo a llamar, reinicio el timeout.
Reinicio el timeout y vuelvo a esperar otros 500 milisegundos.
Que no me llama nadie.
Cuando el timeout termina, ejecuto la función.
Que me llama otra vez, reinicio el timeout.
Es así todo el rato, ¿vale?
Entonces, para eso sirve.
Y lo que puedes hacer es cancelar el debounce.
Puedes hacer un montón de cosas.
De hecho, a veces puede ser buena idea cancelarlo, porque si te cambias de componente y tal.
Pero bueno, no vamos a aplicarnos un debounce desde cero.
Porque esto ya va a script, no es React.
Pero sí la parte de React sí que la vamos a ver desde cero, ¿vale?
¿Cómo vamos a utilizar esto?
Vamos a instalarlo.
Vamos a ver por aquí.
Vamos a utilizar el pnpm install just debounce sheet.
Exacto, ¿vale?
Vamos a utilizar la parte más mínima del debounce.
Y vamos a ver los problemas que nos vamos a encontrar a la hora de crear el debounce.
¿Por qué?
Porque vamos a ver la documentación.
¿Cómo nos dice que funciona el debounce?
Nos dice que tenemos que importar debounce.
Y para crear una función que hace esta magia de cada vez que la llamas esperar un tiempo.
Fíjate, nos dice, vale, debounce.
Aquí la función.
Y aquí el tiempo que espera.
Por ejemplo, si tú llamarías a la función fn1, debería cada vez que le llamas poner el console.log.
Pero como le dices que tiene que esperar 500 milisegundos, si tú empiezas a llamar fn1, fn1, fn1.
Hasta que no pasan 500 milisegundos de la última, entonces no se ejecuta.
Y solo se ejecuta la última vez.
Solo se ejecuta una vez.
Esto es justamente lo que queremos conseguir.
Luego, hay otras estrategias.
Por ejemplo, está el debounce en la que le puedes decir que se dispare el primero nada más empezar.
Esto es para darle como algo al usuario rápidamente.
Entonces, si le pasásemos aquí un true, el primero se ejecutaría inmediatamente y luego seguiría haciendo esta cola hasta que pasasen 500 milisegundos.
También lo podríamos cancelar y también podríamos utilizar el flush, el flush este, como para obligar a que se dispare.
Esto también lo puedes hacer, por ejemplo, si detectas que has escrito 10 palabras y todavía no estás buscando nada.
Pues también lo podrías hacer manualmente.
Nosotros vamos a hacer el primero, que es el más típico, el que tiene más sentido.
Y vamos a ver, ya os digo, los retos que nos vamos a encontrar.
Lo primero que hacemos es importar debounce de just debounce.
Entonces, ¿cuál es el que queremos hacer debounce?
De lo que queremos hacer debounce es justamente de este getMovies.
De este getMovies, no del handleChange.
Porque si lo hacemos del handleChange, lo que va a pasar es que visualmente el usuario no va a ver cómo está escribiendo en el input.
Nosotros sí que queremos que vea qué está escribiendo en el input.
Lo que queremos es evitar que estamos haciendo la búsqueda hasta que no sea necesario.
Así que este getMovies es realmente el que queremos hacer en debounce.
Y además solo lo queremos hacer de este getMovies.
Ni siquiera de este, porque este al hacer el submit, cuando le da el enter, obviamente va a querer buscarlo.
Así que vamos a crear aquí nuestro debounce set getMovies.
Y aquí podríamos hacer un debounce.
Vamos a hacerlo search.
Le pasamos search a esto.
Le decimos que tiene que esperar 500 milisegundos.
¿Y qué es lo que queremos que haga dentro?
Pues lo único que tenemos que hacer dentro.
Voy a poner un console.log para que veamos si funciona o no.
Search, search, y vamos a hacer getMovies y le pasamos el search.
Exactamente igual de como lo estábamos haciendo aquí.
Vale, aquí teníamos el debounce getMovies.
Este debounce set getMovies lo vamos a utilizar aquí.
Y aquí vamos a pasarle el new search así.
Y ya está.
Así de fácil.
Solo que no.
Solo que esto no funciona.
Esto no funciona.
Vais a ver por qué.
¿Por qué no funciona?
A ver si lo sé.
¿Es prueba técnica para mid?
Yo diría que es prueba técnica para juniors.
Bueno, mid.
¿Qué mid?
Bueno, ¿por qué creéis que esto no funciona?
¿Por qué esto no funciona?
O no funciona como esperáis.
Uy, ahora todos callados, ¿eh?
¿Eh?
Al principio, no sé qué, no sé cuánto.
No me malinterpretes.
React me parece una librería cojonera, pero entre los custom hooks, debounce y demás,
no me extraña que Svelte se coma la merienda.
No tiene nada de sentido lo que dices, Alfredo.
Porque es que el debounce, al final, tampoco automáticamente tienes debounce Svelte.
Y tiene sentido.
Y el tema de los custom hooks en Svelte, pues al final, el problema es que no puedes hacer
custom hooks.
O sea, a mí me encanta Svelte.
De hecho, me gusta más que React.
Pero este no es el problema.
O sea, hablar de custom hooks o el debounce.
Es como si me dijeses, React me parece una librería cojonuda, pero qué asco de Tailwind,
¿sabes?
Es que no tiene sentido.
Se reinicia en cada render.
Esa es buena, Geralt.
Porque está en el cuerpo del render.
Ah, muy bien, ¿eh?
Por el use movie, dicen por aquí.
¿Por qué no os tienes que enseñar todo?
Bueno, si queréis no os enseño tanto.
Podéis iros a ver vídeos de 5 minutos.
Aprende React en 3 minutos.
Y ya está.
Porque no está importado.
Sí que está importado.
Porque se fumó un peta.
No funciona porque es miércoles.
Esa es buena.
Está deteniendo la ejecución de la renderización.
Hostia.
No funciona porque estás esperando que no funcione.
Tienes que creer que va a funcionar para que funcione.
Por ahí eso se declara y no se ejecuta.
Bueno, tocaría usar un use call.
Lo dicen por aquí.
Las dependencias.
Render infinito.
Vale.
Dos horas y media para hacer esta prueba.
No estás contratado.
Hombre, a ver.
Esta prueba en Lucas yo la hubiera hecho mucho más rápido.
Lo que pasa es que me he parado bastante a explicaros todo.
O sea, no creo.
Creo que es obvio, ¿no?
Que no hubiéramos tardado tanto en hacer esta prueba.
Aprende React en 3 minutos.
Un vídeo al 1000 de los directos de Midu.
Sí, bueno.
Sí, luego...
Aprende React en 3 minutos.
15 minutos.
10 minutos.
¿Estás dudando del poder de Midu?
Sí.
Bueno, a ver.
Venga, os explico por qué.
Vais a ver que funciona raro.
Funciona, pero raro.
Funciona raro, ¿eh?
Mira, el tema es que ahora voy a empezar aquí.
Avengers...
Vale, le voy a hacer más bestia para que lo veas.
Vamos a poner dos segundos.
¿Vale?
Vamos a poner dos segundos.
Mira, ¿veis que sí que parece que funciona?
¡Ay, ay, ay, ay, ay!
Pero luego las ha hecho todas igual, ¿no?
Las ha hecho todas.
¿Por qué está pasando esto?
Porque si habéis estado atentos y atentas,
lo que está pasando es que este The Bounce Get Movies
se está creando en cada render.
En cada render ejecuto esto y, por lo tanto,
en cada render está...
Claro, no se está cancelando el anterior.
Estamos creando en cada render un nuevo The Bounce,
en realidad.
Entonces, es verdad, sí que está haciendo algo
porque está esperando dos segundos para que se ejecute
por primera vez, pero lo que está viendo es que son
funciones diferentes.
No se está dando cuenta, ¿ves?
En cada render ejecuto esto, cada render ejecuto esto.
Entonces, no se está dando cuenta que son la misma función.
Por suerte, como soy gente muy inteligente,
ya sabéis qué es lo que tenemos que hacer.
¿Qué es lo que tenemos que hacer?
Tenemos que asegurarnos que este The Bounce
que creamos aquí siempre sea el mismo.
Así que, para que esto funcione,
vamos a utilizar un UseCallback, ¿vale?
A ver, UseCallback.
Lo acertamos aquí.
Y le tenemos que pasar la función que crea el The Bounce.
Y aquí ya tenemos el UseCallback con el 1000.
Y le tenemos que pasar aquí, a ver, aquí,
las dependencias.
Que en este caso, no son necesarias las dependencias.
Porque como el GetMovies, no cambia el GetMovies.
Y el Search, que podríamos poner GetMovies, ¿eh?
Por si os quedáis más tranquilos.
Podemos poner GetMovies, pero ya hemos visto antes
que no cambia porque solo lo estábamos creando una vez.
Y aquí le pasaremos el Search.
O sea, que cada vez que cambia el GetMovies,
podemos volver a crear este debug.
Ahora, con este cambio, si volvemos aquí,
ponemos Avenger.
Fíjate, he puesto dos segundos, que es bastante bestia.
Vamos a ponerle menos.
300 milisegundos.
Lo interesante, vamos a ver, vamos a reiniciar.
Ponemos Avenger, ¿vale?
Mate, ahí tenemos un debounce.
Fíjate, solo ha hecho buscado Avengers y Matrix.
300 milisegundos suele ser una buena medida
porque, uno, no le añades mucho tiempo a la carga.
Y, dos, es lo que suele tardar,
un usuario suele tardar entre 100 y 250 milisegundos
entre escribir cada una de las teclas.
Así que, ahora aquí, podemos ir poniendo diferentes.
Panzer, ¿ves?
Y cuando terminas, entonces es cuando está buscado.
Y con esto, ya tenéis también un debounce, ¿vale?
Mi abuelo escribe lento.
Bueno, no pasa nada.
Puede haber, lo importante es tener algo más en general, ¿no?
Pero con esto, hemos creado la prueba técnica
de los sueños de mucha gente.
Porque, realmente, lo que estamos haciendo
es tener un debounce y está súper bien.
Bueno, amigos, muchas gracias a todos.