This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Hicimos un GraphQL server. Además, teníamos aquí las type definitions, vimos cómo se hacía el esquema, cómo funcionaba esto del esquema en GraphQL, el tema de las queries, las mutaciones para añadir personas, editar números, qué eran los resolvers para resolver, y nos reímos un poco, ¿no? Los resolvedores, o como le queráis llamar, resolvedores, bueno, resolvers, le vamos a llamar en inglés, que básicamente lo que hacen es resolver la información de alguna forma.
Y aquí podíamos ver que no solo podíamos traernos información que teníamos de forma estática aquí, en una constante, sino que más adelante vimos que podíamos tirar, por ejemplo, hacer un fetch de una API externa, en este caso era de localhost porque estamos tirando de un JSON server, pero aquí podríamos conectar una base de datos o lo que sea, y de hecho, en la siguiente clase lo vamos a ver.
Veremos cómo conectar aquí un MongoDB, así que, bueno, si te interesa, que lo sepas, que la siguiente clase lo veremos. Y vimos lo que son las mutaciones, que no es solo convertir a personas en los X-Men, sino que es transformar o cambiar datos en nuestras fuentes de datos.
En este caso, pues, podríamos añadir una persona o editarle el número de teléfono. Eso eran las mutaciones en GraphQL. Y también podíamos ver cómo podíamos extraer información de una forma un poco especial.
Por ejemplo, la dirección, pues, era como un cálculo que podíamos hacer de root, que era el objeto de la persona, ¿no? Y aquí, pues, podríamos hacer cálculos, transformaciones, lo que fuese.
Esto era un poco lo que vimos, que iteramos un poquito y estuvo bastante bien. Y hoy lo que vamos a hacer es, más bien, cómo podemos consumir todo esto en el cliente.
En la clase de hoy vamos a ver cómo podemos conectar nuestro servidor de Apolo al cliente. Y en nuestro caso va a ser una aplicación de React.
Vamos a ir poco a poco, vamos a ver cómo podemos hacer peticiones de una forma bastante sencilla. Luego crearemos nuestra aplicación de React.
Vamos a ver cómo podemos conectarnos a este GraphQL Server desde la aplicación de React. Cómo es la mejor forma utilizando un cliente de GraphQL.
Y veremos qué cliente vamos a utilizar, por qué, qué ventajas tiene y todo esto. Así que, para empezar, vamos a ver cómo podemos, justamente, pues, eso, pedir cómo podríamos conectarnos a este GraphQL Server.
Si voy a mi terminal, yo aquí ya tengo levantado el servidor. Pero voy a cerrarlo otra vez para enseñaros un poco cómo lo he hecho, para que veáis que no me invento nada.
Primero, estoy levantando el JSON Server porque este JSON Server está simulando que tenemos una API. Esto lo hicimos, más que nada, para que nos sirviera de ejemplo de cómo podíamos resolver una query a través de una API externa.
No es importante porque esto es como una caja negra. No debería importarnos, ahora que estamos en cliente, cómo resuelve la información. Pero ya os digo que es para eso.
Y, por otro lado, por supuesto, deberíamos levantar el servidor. Que lo hacemos con un npm start. Que esto es lo que hace un npx.nodemon.index.js. Que esto lo que hará, pues, es reiniciar el servidor cada vez que detecte un cambio, ¿vale?
Así que, en el localhost 4000, si vamos, voy a abrir por aquí esto y vamos a poner localhost 4000. En localhost 4000, además, vimos cómo funcionaba el playground y todo esto.
Pero ya tenemos aquí nuestra API ya levantada. Ya estaría aquí funcionando. Así que voy a hacer esto un poco más grande para que lo veáis bien. ¿Ves? Esto sería cómo hacemos una query y esta sería la respuesta.
Entonces, la primera cosa que creo que es interesante que veáis o que veamos es que, en realidad, cuando tenemos un servidor de GraphQL, lo podemos utilizar de cualquier forma.
¿Qué quiere decir esto? De cualquier forma. Que no necesitamos una tecnología en concreto para poder extraer datos de nuestro servidor de GraphQL.
Aquí tenemos esta URL. Pues, en esta URL, para que veamos lo sencillo que sería, si vamos a Visual Studio Code, yo ahora tengo esta extensión que se llama Sander Client,
que básicamente es como un insomnio, es como un postman, es muy similar. Voy a darle a New Request.
Y lo que voy a hacer es intentar hacer una request a mi GraphQL Server para extraer la información de una forma sencilla.
O sea, sin ningún cliente ni nada.
Así que habría que hacer un post, porque ya vimos en la clase anterior que en GraphQL siempre acepta post, no acepta ningún otro.
Solo es un post y siempre tiene un solo endpoint desde el que se hacen todas y cada una de las queries.
Así que ya tenemos aquí el localhost 4000 y ahora le tenemos que decir la query que tenemos que hacer.
Así que nos vamos a body del tipo JSON y aquí vamos a crear un objeto que va a tener como propiedad query.
Y luego le tenemos que decir la query que queremos hacer.
Así que le decimos query y, por ejemplo, pues, all persons para extraer el name.
Cerramos aquí la query, ¿vale?
Y le voy a dar a send.
Y como puedes ver, solo con esto ya podríamos utilizar nuestro servidor de GraphQL.
O sea, esto simplemente, y ahora lo veremos, cómo se podría transformar en un fetch.
Muy fácilmente.
Pero ya ves que aquí, pues ya tendrías la información.
En lugar del name podríamos intentar sacar el font, ¿ves?
Y esto funciona correctamente.
No necesitamos nada más.
O sea, podemos hacer una petición directamente así y ya funcionaría.
Obviamente, hacer así las peticiones veremos que tiene algún tipo, no complejidad, porque complejidad no tiene ninguna,
pero sí que perdemos unas cuantas ventajas.
De hecho, vamos a iniciar aquí, en otra terminal, voy a iniciar con Vite, ¿vale?
Que, para el que no lo sepa, existe Create React App para crear aplicaciones de React.
Ya lo hemos visto a lo largo del FullStack Bootcamp.
Y, bueno, pues para ir viendo diferentes cosas, con Vite, ¿vale?
Que Vite es una alternativa a Create React App, pero es un poquito más que eso, porque es un empaquetador de aplicaciones,
igual que los Webpack.
Y tienes la posibilidad, en este caso vamos a decirle que nos crea un React GraphQL.
Este sería el nombre del proyecto.
Y le vamos a decir que utilice el template de React.
Así que nos va a crear una aplicación muy parecida a la que hace Create React App,
solo que lo hace un poquito más rápido, porque tiene menos dependencias, es un poquito más moderno.
Y, bueno, así pues veis cosas diferentes que también suele ser interesante.
Hacemos un NPM install de nuestro proyecto nuevo.
Vale, vais a ver que esto es un momentito.
Muchas gracias, Vulcanoc, por esa suscripción a Prime.
Dos meses que llevas ya.
Muchas gracias.
Vale, pues ha sido justo en la instalación.
Me ha encantado, ¿eh?
Que te suscribas justo cuando estás instalando.
Ahora que ya tengo esto, ya tengo todo preparado para inicializar el proyecto, ¿vale?
Así que un NPM run me dice cuáles son los comandos que puedo ejecutar.
Dev, build, serve.
Pues vamos a ponerle el dev.
NPM run dev.
Y con esto, en el puerto 3001, ya tendríamos nuestra aplicación de React.
Esto ya viene con un contenido general, ¿no?
Ya para utilizar, que tenga un contador y tal.
Vamos a editar rápidamente el contenido este.
Y vamos a empezar a utilizar nuestro servidor de GraphQL.
Vale, vámonos a nuestro app.g6.
El estado y todo esto.
Vamos a eliminarlo.
Vamos a poner aquí que sea GraphQL más React.
Vamos a quitar todo esto, que no necesitamos para nada.
Vamos a dejarlo por ahora así, ¿vale?
Lo dejamos por ahora así, con eso dando vueltas.
Vale, pues lo primero que podríamos hacer para conectar nuestro GraphQL server es justamente lo que acabamos de ver, ¿no?
Hacer una petición al servidor de GraphQL y ya está.
¿Cómo lo podríamos hacer?
Pues mira, creamos un useEffect.
Le ponemos aquí el callback del useEffect.
Podríamos hacer un fetch de la dirección.
En este caso es HTTP localhost porque lo tenemos en localhost.
Pero bueno, esto lo cambiaríamos si fuese ya en producción.
Y le pasamos una segunda opción, ¿no?
Que aquí tendríamos el method.
Ya hemos dicho que siempre tiene que ser el post.
Por otro lado, los headers, las cabeceras.
Tenemos que decir que el content type que vamos a utilizar es el application JSON.
Porque tienes que enviarle como query el JSON.
Y ¿qué más tendríamos?
Pues el body, ¿no?
El cuerpo de la petición que le vamos a mandar porque es de tipo post.
Y aquí tendríamos el JSON.stringify y le pasaríamos ya la query.
Y esto sí que lo podríamos hacer ya con un template string.
Podríamos poner aquí un template string y pondríamos la query.
Y lo mismo, ¿no?
All persons.
Aquí tendríamos el name.
Si no me he equivocado cerrando cosas, esto ahora ya estaría bien con el body.
Esto, el fetch, pues ya sabemos que es una promesa.
Hacemos un des.
Esto lo convertimos a JSON porque siempre GraphQL nos va a devolver un JSON.
Y el den, pues bueno, aquí podría guardarlo en el estado y mostrarlo.
Por ahora voy a poner un console.log porque tampoco es muy importante.
Vamos a poner res.data, ¿vale?
Porque siempre GraphQL nos devuelve la respuesta en data.
Es donde va a estar la información.
Con esto, básicamente, ya estaríamos conectándonos y podríamos llegar a pintar las cosas.
Vamos a ver si esto funciona.
Ahí está la aplicación.
Voy a mirar en la consola.
Se aparece la información.
¿Veis?
Aquí tenemos un objeto.
Y aquí tendríamos las tres personas.
O sea, ya estamos conectando con esto, ¿vale?
¿Por qué estoy haciendo esto?
Porque quiero que te quede muy claro que cualquier cliente que vayamos a utilizar,
al final, de forma última, lo que hace es algo muy similar a lo que estamos haciendo aquí,
de forma manual.
Estamos haciendo un fetch.
Al final es una petición a un endpoint donde le pasaríamos la query.
Aquí, pues ahora le hemos puesto solo name, pero ya le podríamos poner phone y address.
Guardaríamos los cambios.
Vale.
He puesto una bad request porque a lo mejor, no sé si ahora.
A lo mejor uno de los campos que he puesto no estaba bien escrito.
¿Vale?
Pero ves, ahora he puesto que quiero phone, pues ahora también me devuelve phone.
Y si me damos la network, pues ahí estaría correctamente la petición.
¿Ves?
Localhost aquí.
Y aquí en headers, pues tendríamos la query que he hecho y la respuesta.
Lo que quiero que te quede muy claro es que esto ya funcionaría.
Y de hecho, a ver, no es que esté mal, sino que perderíamos muchas ventajas que podríamos utilizar con los clientes que vamos a ver ahora.
¿Qué es esto de un cliente?
¿Vale?
¿Qué clientes y clientes?
¿Vale?
El tema es que hasta aquí funciona.
Podríamos tener aquí la respuesta, guardarlo en el estado.
Pero esto sería un trabajo ya muy manual.
Estaríamos constantemente guardando la información en el estado.
Y tendríamos, perderíamos algunas cualidades que nos dan los clientes, como por ejemplo aquí, para saber cuándo está cargando, teníamos que poner aquí un estado.
Set loading, que aquí fuese true, cuando tengo respuesta sea false.
Gestionar los errores.
Bueno, un montón de historias.
¿Vale?
Entonces, existen diferentes clientes que tienen muchas ventajas a la hora de trabajar con GraphQL en específico.
¿Vale?
Uno de ellos, y solo para que lo conozcas, aunque no lo vamos a utilizar hoy, es relay.dev.
Relay.dev es el cliente de GraphQL que está utilizando Facebook de forma oficial en sus productos.
Y está muy bien, sobre todo para productos muy, muy, muy, muy, muy grandes.
¿Vale?
Como puede ser Facebook.
Y bueno, aquí tenéis diferentes ejemplos que si vais viendo, pues va a ser muy similar a lo que vamos a ver hoy.
¿Vale?
Así que os debería más o menos sonar.
Además utiliza algunas funcionalidades de React bastante interesantes, como React Suspense.
Y bueno, tenía los fragments, que eso es una cosa que seguramente veremos más adelante.
Y bueno, buenas prácticas y tal.
Este sería el que utiliza.
Si te interesa realmente saberse el relay, que no vamos a verlo hoy, pero mira, aquí te dirá quién lo utiliza.
Pues bueno, Facebook es el más interesante.
Oculus también, pero bueno, Oculus también es de Facebook.
Si te interesa, yo lo que te recomendaría, y lo pasaré y lo dejaré en la descripción del vídeo, o lo paso en el chat también, es este vídeo.
Este vídeo de Facebook está muy bien y explica exactamente cómo estaban creando la nueva versión de Facebook, la que tienen ahora disponible.
Y explica cómo utilizan React, GraphQL y Relay.
Y entonces, pues explícale cada una, te da una visión de la infraestructura, cómo utilizan React, cómo lo conectan con Relay, cómo GraphQL le da la ventaja de rendimiento que necesitaban.
Bueno, pues si os interesa este vídeo, os lo recomiendo muchísimo, ¿vale?
Le podéis buscar como buildingthenewfacebook.com y ya, porque es muy famoso, así que le podéis echar un vistazo.
Creo que por aquí hablan de Relay, si no me equivoco, para el tema de los datos.
¿Veis? Ahí estaba el tema, ¿no? Cómo era el fetching y esto es Relay y cómo lo hacen.
Bueno, esta sería una opción, Relay, pero la opción más popular que no sea la que utiliza Facebook es, cómo no, Apolo, GraphQL.
Bueno, vamos a poner directamente el cliente de React, ¿vale?
Al final hay que tener en cuenta que Apolo Client, pues tendréis que tener, Apolo Client tendréis de diferentes, para React, Vanilla, un montón de sabores.
Nosotros vamos a utilizar, obviamente, el que es de React, ¿vale?
O sea, vamos a mirar este, el Apolo Client de React.
¿Qué es lo que nos da el Apolo Client de React?
Mira, aquí tenéis Angular, Vue, Svelte, Ember, Meteor, Web Components, o sea, hay un montón de clientes que ya están preparados.
Pero os dan un data fetching declarativo que va muy alineado con cómo funciona React.
Te dan unos custom hooks geniales.
Te dan unas developer tools donde puedes ir viendo cada una de las peticiones, la caché, lo que tienes.
Además, te permite hacer un, implementarlo en tu aplicación de forma incremental, poco a poco, que no hace falta que lo hagas todo de golpe.
Así que, y además que no hace falta, y esto es súper importante también que mucha gente lo confunde, no hace falta que el servidor de Apolo esté hecho con Apolo.
O sea, el servidor de GraphQL esté hecho con Apolo, ¿vale?
Funciona cualquier servidor de GraphQL.
Esto es importante.
El Apolo Client es compatible con cualquier servidor de GraphQL, esté hecho o no con Apolo.
¿Ok?
Así que el que vamos a ver es el Apolo Client.
Este es el que vamos a utilizar, el que vamos a ver en la clase de hoy,
y seguramente es uno de los más famosos, de los más fáciles de usar, quizás no,
porque hay alternativas que son un poquito más simples, pero bueno, podéis utilizar incluso React Query,
que es un poquito agnóstico a GraphQL, pero también está bastante bien.
Tampoco lo vamos a ver en el stack, pero quién sabe si lo veremos a lo mejor más adelante,
porque es realmente interesante y te da muchas de las ventajas que te da el Apolo Client.
Pero bueno, en esta clase, Apolo Client.
Vamos a ver cómo lo deberíamos utilizar.
Primero, en nuestra aplicación, en la de React GraphQL, lo que tenemos que instalar sería Apolo Client
y también GraphQL.
Vamos a ver, luego veremos para qué necesitamos lo de GraphQL,
pero básicamente es una dependencia que necesita el propio Apolo Client
cuando trabajemos con las queries y todo esto.
Vale, ya hemos instalado los paquetes.
Voy a volver a iniciar el servidor, por si acaso.
Y ahora vamos a configurar cómo sería la conexión con Apolo Client.
Nos vamos al punto de entrada de nuestra aplicación, que es en este caso main.jsx.
Esto depende de cada aplicación.
En nuestro caso es el main.jsx, porque ves que tenemos aquí el react.render.
Este sería el típico index.jsx.
Pues aquí lo tenemos.
Podemos importar ahora ya el Apolo Client.
¿Vale?
Y esto nos lo traemos de Apolo Client.
Otra cosa que vamos a necesitar seguro sería el GQL.
El GQL es GraphQL, esto lo vimos en la anterior clase,
y es la que nos va a permitir utilizar como un template string con las queries y todo esto.
Esto por ahora es lo que necesitaríamos.
¿Cómo iniciamos el cliente?
Pues nada, client igual new Apolo Client.
Y ahora hay que pasarle diferente información.
Las opciones serían, ¿con qué nos queremos linkar?
¿Con qué quiere este cliente que se tiene que conectar?
Pues vamos a crear un nuevo HTTP link,
porque en este caso vamos a ir a un servidor que tiene una IP.
Para crear esto tenemos que también importar HTTP link.
¿Vale?
Hay diferentes enlaces.
En este caso pues tendríamos un HTTP link,
porque ya tiene una ruta HTTP a la que nos queremos conectar.
Así que hacemos new HTTP link.
Y aquí le tenemos que decir cuál es la URI donde está este recurso.
O sea, cuál es la dirección.
En nuestro caso, HTTP localhost 4000.
Normalmente aquí esto suele venir a través de las variables de entorno.
¿Por qué?
Porque cuando estamos desarrollando pues será localhost,
pero cuando estéis en producción será una URL y tal.
Como en clases anteriores ya hemos visto temas de variables de entorno,
pues no vamos a incidir en ello.
Pero que sepa que sería así, de esta forma.
Vale.
Por ahora lo voy a dejar así.
Luego os explicaré una cosa porque nos dará un error,
pero por ahora lo vamos a dejar así.
Ya tendríamos como el cliente inicializado.
Con este cliente podemos hacer pues peticiones a nuestro servidor de GraphQL.
Vamos a ver cómo crearíamos una petición.
Vamos a hacer una query y utilizamos el GQL y ponemos aquí el template string.
Aquí en este template string podemos escribir la query como lo haríamos normalmente.
Pues query, all persons.
Y aquí pues sacar el name, el font, el address.
Y del address podemos sacar el street, el city.
Y creo que también tendríamos la id, ¿no?
Pues vamos a ponerla por aquí.
Es una query para recuperar todas las personas que teníamos
y todas las propiedades que tienen estas personas.
Vamos a ver si esto ahora funciona y tal.
Y ahora vamos a utilizar esta query.
Para utilizarla pues hacemos un client.query.
le pasamos como objeto, ¿vale?
Un objeto hay que pasarle la query, que es la query, ¿vale?
Como estos son nombres, son iguales, podemos hacerlo así.
Pero a query se le pasa un objeto que tiene la propiedad query.
Ya sé que es un poco raro.
Esto es como es el cliente de Apolo, lo que hay.
Pero es client.query.
Es para hacer una query le tienes que pasar un objeto que recibe query.
Ya ves que tiene otras propiedades que le podrías pasar.
Pero en este caso necesitamos query, que es seguro que es para hacer la query.
Así que query se le pasa un objeto con la propiedad query.
Y esto nos devuelve una promesa.
Así que hacemos un den.
Aquí tendríamos la respuesta.
Y vamos a hacer un console.log res.dita, ¿vale?
Vamos a empezar así.
Esto lo vamos a iterar porque esto no sería la forma más ideal de hacerlo.
Pero vamos incrementando, ¿vale?
Ya hemos inicializado nuestro cliente de Apolo.
Hemos escrito nuestra primera query.
Y estamos haciéndola.
Y vamos a ver si esto nos devuelve datos.
Vamos a nuestra aplicación.
Debite.
¿Vale?
Si refresco me voy a la consola.
Pam.
Pete.
Me dice que el Apolo Client necesita una propiedad caché en las opciones para que pueda funcionar.
¿Qué es esto?
Una de las ventajas que tiene y es súper importante el cliente de Apolo es que tiene una caché.
Una caché que cada vez que hace una petición pues guarda la caché de esa información para evitar no solo hacer más de una vez esa petición,
sino también para sincronizar los cambios que tú vayas haciendo en esa caché y así poderlo guardar ahí sin necesidad de volver a pedirlos al servidor.
Luego más adelante veremos un ejemplo de esto y lo verás clarísimo.
Pero por ahora te tiene que quedar claro que necesitamos una caché.
La caché más típica que puedes utilizar es en memoria.
Y en memoria al final es como una variable que hay, como una variable o un array o un objeto que hay en memoria que ahí se va guardando toda la información.
Se llama inmemory caché.
Y este inmemory caché hay que importarlo.
¿Vale?
Inmemory caché.
Esto ya viene del propio Apolo Client.
Este inmemory caché.
Pues ya lo utilizamos así y ya estaría.
Podríamos tener diferentes cachés.
Claro, ¿por qué?
Porque cada vez que cerremos el servidor y lo volvamos a levantar, se pierde la caché, porque como está en memoria.
Así que podría haber cachés de base de datos, en disco, hay un montón de tipos de caché.
Esta es la más típica y normalmente la que mejor funciona en muchos proyectos,
pero hay veces que quieres llevarlo a otro nivel o que sea una caché.
Imagínate, esto ya es un poquito más avanzado,
pero hay veces que tú el servidor lo quieres levantar en cuatro máquinas distintas a la vez.
Pues claro, si está en memoria, la memoria no es compartida entre las cuatro máquinas.
Por lo tanto, a lo mejor quieres que sea en una caché, en una base de datos, o puede ser Redis o lo que sea,
para justamente que se sincronice esa caché entre las cuatro máquinas.
Ya son casos más avanzados, pero un poco para que veas que hay ejemplos reales de por qué puede ser útil esto.
Vale, pues vamos a guardar aquí los cambios.
Esto no sé si lo había guardado o algo.
Ahora guardamos los cambios y vamos a ver.
Vale, voy a quitar el useEffect este que había puesto anteriormente,
¿vale? Para hacer la petición como a mano.
Lo vamos a eliminar y vamos a dejar solo esta petición que estoy haciendo por aquí.
Refresco y ya tengo aquí allPersonalRate.
Aquí tendría la información.
Aquí podemos ver lo que me está devolviendo ApoloClient.
Pues como le he dicho que me devuelva el address, pues tenemos city, street.
Tenemos este, el typeName, que básicamente nos dice el nombre del tipo.
Y como address, podríamos mirar en nuestro código, address, habíamos hecho que fuese un type.
¿Ves? El typeName es este address de aquí.
Así que este typeName, el de Person, también tenemos toda la información.
Pues ya está funcionando.
Ahora, ¿cuál es el problema de esto?
Hombre, que trabajar así con el cliente es un poco rollo.
Porque al final, si lo ves así, dices, a ver, pero ¿qué ventaja tiene esto?
Porque al final vas a tener que importar el ApoloClient.
Bueno, harías esto y este client tendrías que inyectarlo.
O sea, este client lo tenemos que pasar a la app y de la app, pues abajo, todo el rato y bla, bla, bla, bla.
Obviamente, como esto nos calaría bien, lo que se hace en estos casos, ya podemos quitar esta query porque esta query ya no la vamos a utilizar.
Lo que se utiliza en estos casos es un provider, ¿vale?
Esto lo vimos en la clase de Redux.
Y un provider lo que permite es encapsular, bueno, es envolver nuestra aplicación.
Vamos a ponerlo aquí, el provider, que sería ApoloProvider y le pasaríamos el client, ¿vale?
ApoloProvider.
Voy a quitar el strict mode porque, bueno, no es importante.
No estamos mirando eso.
Así, ApoloProvider, ¿vale?
Esto es un componente que también lo da el ApoloClient.
Y lo interesante de esto es que lo que hace es utilizar el contexto para que el cliente esté disponible en toda la aplicación o todos los componentes que estamos envolviendo.
En este caso, estamos envolviendo App, pues todos los componentes que estén dentro del subárbol de App tendrán la posibilidad de utilizar este client sin necesidad de estar importándolo manualmente y todo esto.
Así que voy a guardar por aquí los cambios y ya estaría.
¿Cómo funcionaría esto?
Vale, vamos a traer, me voy a traer esta query que habíamos hecho aquí.
Esto quedaría más o menos así, ¿vale?
Tenemos ApoloClient, Provider, todo esto así, perfecto.
Guardamos los cambios y nos vamos a la app.
Aquí vamos a realizar una consulta y vamos a ver cómo deberíamos utilizar este client, ¿vale?
Ya no se utilizaría el client directamente.
O sea, se dejaría utilizar el client como lo hemos hecho hasta ahora.
Lo que tenemos que hacer, bueno, voy a dejar por aquí la consulta, la query que queremos hacer, aunque luego lo refactorizaremos.
Esta query, bueno, necesitamos el GQL, eso seguro, así que GQL lo vamos a importar del ApoloClient y vamos a importar, y aquí es donde empieza la magia y lo interesante realmente de ApoloClient, un custom hook que se llama useQuery.
Este useQuery lo que nos va a permitir es llamar dentro de nuestro componente, vamos a poder hacer un const result, vamos a utilizar el useQuery y le vamos a decir la query que queremos hacer.
En este caso es esta query que ahora le vamos a llamar allPerson.
¿Por qué?
Porque esta query al final lo que hace es traerte todas las personas.
Pues useQuery, ¿qué query quieres usar?
Pues la de allPersons, ¿vale?
Y aquí tendríamos el resultado.
¿Qué resultado?
Pues vamos a verlo.
Vamos a hacer un console log de result para ver, uno, si funciona todo, y dos, cuál es el contrato o el tipo que tiene este objeto, a ver la información que nos proporciona.
¿Vale?
Así que vámonos a nuestra aplicación, voy a guardar, refresco.
Fíjate que está dos veces.
Esto también es súper importante y mucha gente a veces se vuelve loca, ¿vale?
Pero es que es normal, porque cuando yo refresco está dos veces, hay dos objetos, ¿vale?
Porque en una, la primera vez, no se está haciendo la petición, sino que nos está devolviendo información, por ejemplo, que se está cargando, o sea, que tiene el estado de loading a true.
Pero aquí en la primera todavía no tenemos los resultados, todavía no ha terminado la petición.
Pero al menos en results ya sabemos que está haciendo algo, o sea, que ya ha inicializado.
Y luego la segunda es cuando ya ha terminado, a veces con un error, a veces pues con la información, ¿no?
Puede ser un error, puede ser, en este caso, error, undefined.
Y data es donde sí que tenemos la información de la query.
Pero fíjate que la primera en data, pues lo tenemos undefined, pero el loading estaba true.
¿Qué significa esto?
Vale, pues que tenemos que reaccionar a los dos estados distintos.
En lugar de tener un estado ahí, un useState a mano, lo que está haciendo este result es que podemos recuperar, por un lado, data, y por otro lado, el loading, ¿vale?
Podríamos recuperar también el error, ¿vale?
Y como podéis ver, hay un montón de información aquí, o sea, data, tenéis el client para volver a utilizar el mismo client que hemos visto al principio, cosa que no os recomiendo, ¿vale?
Si podéis evitarlo, mejor.
Pero aparte del client, pues tendríais un fetch more, que sería un método que podéis volver a llamar para traeros más información, se suele utilizar para un tema de paginación, se pueden hacer un montón de cosas, ¿vale?
Pero lo importante ahora mismo sería data, error, y loading.
Esos sean los tres más importantes.
Y que si normalmente podéis enfocaros en esos tres y no tirar, cuanto menos tiréis de los otros, normalmente mejor.
Porque suelen ser, obviamente, suele ser más imperativo lo que se hace.
Imperativo es decirle lo que tienes que hacer, es menos declarativo y suele ser más complejo de mantener al final.
Ahora que tenemos data, error y loading, lo que podríamos decir es que si está cargando, pues lo que vamos a hacer es devolver, pues en lugar vamos a poner este div.
Bueno, de hecho, lo podríamos hacer aquí, mira.
Dentro, aquí dentro, podríamos hacer.
Si está loading, podríamos poner aquí que loading o cargando.
Bueno, loading, vamos a ponerlo en inglés, ¿vale?
Si tenemos un error, el error igual lo podríamos poner más a saco aquí.
If error, pues vamos a poner un span style con color red.
Y vamos a poner, pues el error.
Vamos a poner error, ¿vale?
Si hay un error, ya devolverá esto.
Si no hay un error, pues entrar aquí.
Teníamos loading, pues estaría cargando.
Y si no está cargando, pues lo que podríamos, podríamos hacerlo como ternaria, ¿no?
Podríamos hacer, si estoy cargando, haz esto.
Y si no, pues ya renderizas todo lo demás.
Y podríamos poner este graph, Google, no sé qué, no sé cuántos.
Y además podríamos, pues, hacer ver la data, ¿no?
Vamos a ver la data.
Si no está cargando, podríamos mirar.
Y aquí ya teníamos esto.
Y hacer otro más, ¿no?
Decirle data.
Y si tenemos data, pues, ¿qué podríamos poner aquí?
¿Vale?
Espérate, me dice que me la he liado aquí parda.
Que no le gusta.
La verdad es que cuando empiezas a concatenar, te puede volver un poco loco.
Lo que se puede hacer es sacarlo fuera, por ejemplo.
O sea, podremos poner aquí variables y ya está.
O poner método render o lo que queramos, ¿vale?
Pero en este caso, a ver, ¿qué podríamos hacer?
Ah, es que me extraña que...
Vale, eso es porque son dos.
Tenemos que utilizar un fragment, ¿vale?
Ahora sí, tendríamos esto aquí.
Y aquí podríamos poner data.
Y si tenemos data, pues ya data.map.
Y esto sería una persona.
Y a ver, lo podemos...
Por ahora lo podemos poner de cualquier forma.
Bueno, data.
Ojo, que es data.
Y como lo hemos visto antes, debería ser data.allpersons.
¿Vale?
Aquí debería ser allpersons.
Porque, si os acordáis, me da data, ¿veis?
Allpersons.
En una sola query, o sea, podríais hacer más de una...
Traer tanta información como queráis.
Aquí podríamos tener allpersons y más queries.
En este caso tenemos el allpersons.
Pues nada, allpersons.
Y por cada persona, pues a ver, podríamos poner person.name.
Y esto, pues vamos a hacer por ahora un join, de la coma, join, coma, así.
Solo para ver que esto funciona correctamente, ¿vale?
Y esto lo cerramos aquí.
Ahora luego lo refactorizamos y lo dejamos con componentes mejor visto.
Pero mira, fíjate que sale el loading.
Nada, un momentito.
No sé si se ve el frame, pero se ve el loading un momento.
Y luego aparecen aquí ya nuestras personitas, ¿vale?
Nuestras personas que, bueno, las que tenemos información y ya está.
Vamos a refactorizarlo ya.
Ahora que ya sabemos que esto está funcionando correctamente.
Podríamos crear un componente.
Le vamos a llamar persons.jsx, ¿vale?
Y a ver, vamos a poner persons, que aquí le pasamos las personas.
Y estas personas, pues vamos a renderizar un div.
Vamos a poner aquí persons.
Persons.map.
Y por cada persona, pues div key p.id, ¿vale?
Porque cada persona tiene su propia idea.
Deberíamos verlo fácilmente aquí cuando hacemos la petición.
¿Veis?
La idea.
Vale.
Vámonos aquí.
Tenemos la idea.
¿Qué más podríamos poner?
Bueno, p.name y el...
Vamos a dejarlo sencillo, p.phone.
¿Vale?
Al menos que se haga el nombre y el teléfono y ya está.
Esto serían las personas.
Aquí no estamos utilizando nada.
O sea, esto será solo para pintar.
Así que en lugar de hacer esto, ya aquí lo que podríamos hacer...
De hecho, esto puede ser interesante a veces porque, mira, persons.
Y aquí ahora será data all persons.
¿Vale?
Y podemos hacer esto.
Data.
No sé si funciona.
Ahora miraremos si funciona el optional chaining.
Pero esto lo que puede hacer, de esta forma, ya nos olvidamos un poco de cómo gestionarlo aquí.
Queda un poquito más limpio.
Y lo que haríamos...
Bueno, puedo quitar incluso esto porque tampoco es que el título ese sea muy importante.
¿Vale?
Pero vamos a hacer esto.
Vamos a hacerlo así.
¿Vale?
Más fácil.
Entonces, esto, si aquí devuelve null, por ejemplo, lo que podemos hacer aquí, por ahora, vamos a poner que persons...
Bueno, esto, persons, esta prop, le podría llegar que fuese null, ¿vale?
O sea, que esto podría ser null.
Podríamos hacer persons, if persons es igual a null, pues return null, por ejemplo.
¿Vale?
Y así, pues, que no renderice nada.
Y deberíamos no tener ningún problema con esto.
Vale.
Persons is not defined porque aquí estoy utilizando el componente, pero todavía no lo he importado.
Así que lo importamos.
Vamos a exportarlo también, que yo también export const.
Así que lo importamos así, from persons.
Venga.
A ver ahora.
Venga, ahora que no ha gustado.
React is not defined.
Vale.
Import React from React.
Claro, como no tengo el linter puesto, tampoco me dice muchas cosas.
Vale, ahora sí que lo tenemos, ¿vale?
Esto sería el nombre de la persona y este es el número de teléfono.
A ver, no es la gran cosa, pero al menos ya lo estamos separando, ¿vale?
Entonces, hasta aquí lo que quiero, sobre todo, que te fijes, ¿no?
Es como hemos hecho el tema de la query, que solo con una línea ya nos está diciendo,
si tiene información, el error y el loading.
Y esto gracias al cliente de Apollo, en este caso que estamos utilizando,
que si no lo tenías que hacer manualmente.
Si usases el fetch, toda esta gestión del error, del loading, estos estados,
lo tenías que hacer manualmente, sería un poco más complejo.
Vale.
Hasta aquí, bien.
Voy a leeros un momento y así bebo también a ver cómo estáis y me comentáis.
Ya hemos visto el tema de los clientes, hemos visto cómo puedo realizar consultas,
pero claro, las consultas que estamos haciendo hasta ahora son un poco de aquella manera, ¿no?
O sea, son consultas muy a saco.
Si no recuerdo mal, ¿ves?
Teníamos esta, que era la del find person.
Esto lo teníamos en el GraphQL Server, en el Playground,
y podíamos encontrar una persona, pero aquí le estábamos poniendo justamente ya la persona.
Teníamos aquí, si poníamos dapelu, creo que sí que existe, ¿no?
¿No? ¿Dapelu no existe?
A ver cómo es el nombre.
Dapelu.
Pues debería existir.
Ah, porque a lo mejor el find person este, como teníamos en JSON Server,
una parte, vamos a ver, esto de aquí.
Claro, como no habíamos cambiado todo, find person,
como que la información que había en un sitio no era exactamente la misma.
Vamos a mover esto, vamos a ver cómo es este David JSON.
Vamos a traérnoslo.
La información que hay en los dos sitios es distinta y eso nos puede confundir, ¿vale?
A ver ahora qué nos sale en el cliente.
Vale, la pelu.
Y ahora aquí.
Ahora sí que sale.
Vale, perfecto.
Vale, pues teníamos una query para buscar una persona.
Vamos a utilizar esto porque lo interesante de esto es aprender
cómo se le puede pasar una variable justamente a la query,
porque ahora hasta aquí lo estamos haciendo justamente con un string,
pero lo que nos interesa es ver cómo le podemos pasar una variable.
Así que vamos a, vámonos a persons, podríamos hacerlo en persons, creo que sí.
Vamos a hacerlo en persons.
Esto es el servidor, nos vamos al cliente y nos vamos a persons.
Luego lo refactorizaré y sacaré todo lo que son las queries y todo esto, ¿vale?
Pero vamos a crear aquí una constante que se llama findPerson, ¿vale?
Vamos a utilizar el GQL, este, de GraphQL, y aquí tendríamos básicamente nuestra query.
Nos la podemos copiar, que sería esta de aquí, pero ahora tenemos que cambiarle algo,
porque fíjate, claro, si yo quiero que esto sea una variable,
¿cómo podemos hacer, no?, de pasarle una variable.
Primero vamos a ponerle un nombre a esta query y le vamos a decir que esto es findPersonByName.
Y vamos a decirle que esta query recibe un parámetro, y aquí le ponemos el nameTo.
Y luego le vamos a decir el tipo, súper importante, ¿no?
El GraphQL todo es tipado, todo tiene tipos.
Le vamos a decir que el tipo es string y la exclamación, que es obligatoria.
Y esta variable, el nameToSearch, ahora lo podemos utilizar en la query.
En lugar de utilizar el string directamente, lo que vamos a poner aquí es nameToSearch.
De esta forma ahora es más dinámica esta query, sino que le vamos a pasar la variable a nosotros,
no es que sea un string, sino que desde fuera le podemos pasar esta información.
Tenemos el name, el phone, id, address, que creo que lo he escrito bien,
si no ya se quejará, city, y ya tendríamos esto, ¿no?
Para sacar toda la información de esta persona.
Aquí en persons vamos a ver otro tema interesante,
porque fíjate que en app hasta aquí lo que teníamos en este useQuery y tal,
este hook lo que hace es que en cuanto se renderiza,
lo que hace es hacer la petición, ¿no?
Lo que está haciendo es hacer la petición de primeras.
Pero yo ahora lo que me gustaría es hacer la petición cuando yo quiera,
no cuando le dé la gana, o sea, no cuando se renderice.
O sea, yo quiero controlar cuándo se hace la petición.
Para hacer eso existe otra cosa.
Ahora vamos a importar el GQL de Apollo Client
y vamos a utilizar un nuevo hook que se llama useLazyQuery, ¿vale?
Es como una query que es un poco vaga.
¿Por qué? Porque nosotros le vamos a decir cuándo se tiene que hacer.
Vale, Lazy básicamente es que va a esperar a que pase algo
y en este caso es cuando nosotros le digamos.
¿Cómo la utilizaríamos?
Pues ya aquí en persons, por ejemplo, bueno,
lo hemos puesto en persons, pero lo podríamos haber puesto en otro sitio.
No sé si tiene más sentido que lo ponga en otro sitio.
Igual la sacamos de aquí.
Vale, vamos a sacarlo de aquí.
Vamos a hacerlo en otro componente, ¿vale?
Vamos a hacerlo en findPerson.jsx, por ejemplo.
Vale, traigo todo esto.
Bueno, a ver, en realidad podría traerme todo, ya está.
¿Vale? Así dejo este como estaba.
Vamos a dejar que siga esto así.
Vale, esto no lo necesita.
Voy a crear un nuevo componente que es findPerson.
Importo React, export, const, findPerson.
Y ahora aquí empezamos nosotros.
Vamos a hacer primero el uso del LazyQuery.
¿Cómo utilizamos el LazyQuery?
Pues lo que tenemos que hacer aquí, voy a dejar eso así,
es utilizar el useLazyQuery y decirle la query que queremos utilizar,
que es findPerson.
Ya está.
No tiene mucho más.
Es exactamente lo mismo que hemos visto antes con el useQuery,
pero con useLazyQuery.
Y ahora lo interesante aquí es que si te fijas en app,
teníamos data, error y tal,
porque aquí teníamos directamente el resultado,
que es un objeto,
pero en el useLazyQuery esto es un array de dos posiciones,
donde la primera posición es la llamada,
cuando queremos activar la consulta,
cuando queremos hacer la query, ¿vale?
Así, por ejemplo, getPerson,
y luego tendríamos una segunda posición que sí que sería el resultado.
¿Qué podemos hacer para que todo esto funcione?
A ver, una cosa que podemos hacer,
al menos por ahora,
sería,
vale,
ahora estoy pensando por qué sería interesante hacerlo aquí dentro,
porque podríamos darle un clic y buscar a esa persona,
y que nos dé toda la información.
Entonces, ya solo tendríamos el name y el font,
y así, pues, podríamos sacarlo.
Bueno, pues vamos a volverlo,
a poner aquí.
Así lo hacemos aquí en un solo sitio,
y ya está, ¿vale?
Vamos, perdón, ¿eh?
Por el movimiento sexy del código,
pero bueno, al menos.
Así que movemos esto aquí,
y así le daremos clic.
Es que si no,
tendría que hacer un formulario y tal.
Entonces, lo que puede hacer
es que cuando le demos un clic a este div,
que busque esa persona,
y ya está, ¿no?
Así hago un clic.
Y cuando le demos clic a esta persona,
pues, lo que hacemos es hacer algo.
Ahora, por ahora,
ahora os enseñaré lo que hacemos,
porque, claro,
podríamos buscar directamente a la persona,
pero ya veremos que nos gustaría,
pues, controlar mejor
cómo se hace esta query,
dónde se busca el resultado,
y todo esto.
Podríamos tener, por ejemplo,
un estado.
Esto se podría hacer en muchas formas, ¿eh?
Vamos a probarlo primero así,
y luego le damos una vuelta.
Una sería utilizando un useEffect.
Podríamos tener un estado,
que sea person, setPerson,
guardarlo en el useState,
que esto al principio sea nul.
Luego, aquí al hacer un clic,
lo que podemos hacer sería llamar a este getPerson.
Vamos a crear una constante,
que podría ser showPerson, ¿vale?
Que le pasemos el name,
y a partir del name,
llamamos al getPerson.
GetPerson, que es para hacer la query,
tenemos que pasarle la información
de las variables que queremos que lleguen aquí.
Por lo tanto, se le pasa un objeto,
que le dice, vale,
las variables que tienen son un objeto,
y el nameToSearch sería el nombre
que le estamos pasando aquí como parámetro.
Así que pondríamos aquí el name.
¿De dónde llega todo esto?
Pues este showPerson lo llamaríamos así,
aquí, en el onClick.
Así que aquí en el onClick utilizaríamos el p.name,
¿vale?
Que es justamente el que tenemos aquí.
La p aquí sería the person.
Si queréis, pongo esto un poco aquí así.
Y en lugar de p, pues pongo person.
Y vamos a cambiar todos estos.
¿Vale?
Person, person, person.
¿Vale?
Revisamos otra vez.
Tenemos un div,
que cuando se hace un click,
va a ejecutar el método showPerson
con el person.name.
Lo hemos hecho con el name,
pero podríamos haberlo hecho con el id y tal.
Lo que pasa es que el GraphQL
ya tiene esta query así, y ya está.
ShowPerson recibe el name
que le estamos pasando por aquí,
y llamamos al getPerson.
Y con este getPerson, pues tendríamos aquí
las variables que le tienen que llegar
y en las variables, si miramos aquí,
tenemos el nameToSearch.
Entonces le decimos,
de las variables, el nameToSearch
es el que le estamos pasando por parámetro,
el name.
Y este es lo que haría hasta aquí
el showPerson.
¿Qué pasa con esto?
A ver, que ahora este getPerson
tendríamos aquí dentro de result,
tendríamos la información, ¿no?
Ahora tendríamos la información
que deberíamos mostrar.
Pero, claro, podríamos manejarlo
de diferentes formas esto, ¿no?
Ahora que tenemos aquí en el result,
pues podríamos directamente mirar
si en este result tienes la persona
que has buscado, pues mostrarle y ya está.
Pero, claro, cuando nos queramos controlar
de cerrarlo, ¿no?
De cerrar esa persona, pues esto
no lo podríamos hacer tan fácilmente.
Podríamos hacerlo en un montón de formas,
pero quizás lo mejor puede ser,
al menos para empezar,
sería tener este estado
Person y SetPerson
y básicamente tener un UseEffect.
Con el UseEffect lo que podríamos hacer
es mirar que si tenemos en result,
tenemos data,
pues utilizar este SetPerson
y guardar el resultData.FindPerson.
¿Por qué es tan FindPerson?
Porque justamente la query se llama,
bueno, así es este, ¿vale?
No llegará, es que le había puesto este,
es este.
No llegará aquí.
Esto es lo que decimos siempre
que GraphQL es predecible, ¿vale?
Porque yo sé ya directamente,
no tengo que mirar
qué es lo que me devuelve el servidor,
ni ver documentación, ni nada.
Porque yo, al saber que estoy haciendo
esta query con este nombre,
yo ya sé que me va a llegar
en result.data.FindPerson
y que FindPerson debería tener,
si lo encuentra,
tendría que tener la propiedad name,
font, id, un objeto address
que tiene la propiedad street y city, ¿vale?
Esto es lo que significa
que sea predecible.
Porque ya sé cómo va a ser el objeto,
básicamente.
Ahora, importante este useEffect,
que si lo dejamos así,
esto se puede volver loco,
es que dejemos aquí y pongamos
que este useEffect se tiene que ejecutar
cada vez que cambie este result, ¿vale?
De forma que cuando este result cambie,
pues haremos el setPerson con uno u otro.
Ahora que ya tenemos esto, ¿vale?
Si Persons es null, return null.
Bueno, pero antes de esto,
podríamos mirar que si tenemos la persona,
que es la que guardamos en este estado,
aquí en este setPerson,
cuando haga esto,
se guardará en este person,
y ya tendríamos,
si tenemos persona,
pues renderizar la persona.
Podríamos renderizar con un h2,
tendríamos person.name,
de nuevo, predecible,
porque ya sé todas las propiedades
que va a tener el objeto.
O sea,
es que me petaría directamente esta query.
Yo ya sé que todas estas propiedades
van a estar sí o sí.
Si no,
lo que tengo ya es un problema
de mi backend,
pero a nivel de cliente,
yo debería fiarme de que si la he encontrado,
o sea,
este if,
si esto ha funcionado
y entra este if,
todas estas propiedades las va a tener,
porque es como está definido mi esquema.
¿Ok?
Entonces,
bueno,
tendríamos el street,
podríamos,
bueno,
aparte del street,
podríamos poner aquí
person,
address,
punto city.
Podríamos ponerle el teléfono.
Y podríamos poner el botón
que os comentaba,
que era justamente para hacer
que el set person,
pues vuelva a ser null.
Y así habría una forma
de cerrar esto.
Por ejemplo,
close.
Pues algo así.
Vamos a ver si esto funciona,
que hemos hecho muchos cambios.
Vamos a quitar el formato person este.
Este sería el mismo component
que teníamos antes.
Vamos a ver.
Nos vamos a nuestra aplicación.
Bueno,
está apretando las cosas,
pero más que nada
porque no estoy importando cosillas.
que es el useState.
Vamos a ver si el useState.
Vale.
Vale.
Uy.
Can not read,
mira,
property city of undefined.
Pues mira,
justamente,
city of undefined.
No,
esto es que lo he escrito mal.
¿Ves?
Es predecible,
pero lo que no predice
es que yo lo escriba mal.
Y es que he puesto
person.address
y aquí lo he puesto con una S.
O sea que,
a ver,
predice hasta cierto punto.
Vale.
Ahora se supone que si doy click,
vamos a quitar esto,
si le doy click.
Vale.
Ahora no está haciendo nada.
Vamos a ver que a lo mejor
la he ligado.
Person name.
Vamos a ver si está haciendo
las peticiones.
Vale,
las peticiones sí que las está haciendo.
Vamos a ver.
Data.
Al último que le he dado
ha sido de apelo.
A ver,
vamos a darle.
De apelo.
No.
No.
No.
Ah,
claro,
ahí está funcionando la cache.
Vale,
le he dado asdolo 94.
Hasta aquí sí que está haciéndolo bien.
ID,
name,
no sé qué,
no sé cuánto.
Vale,
está así con el show person.
El result data,
find person.
Esto debería estar funcionando bien también.
Aquí ya tengo que hacer esto.
Find person.
Y vamos a poner aquí un console.log
un momento del person.
A ver qué está pasando.
Porque no me está entrando a este if.
O.
Sí,
no.
O sea,
no me está entrando.
Vamos a verlo.
Aquí es normal que sea null,
pero cuando le doy,
¿ves?
El último sí que me sale aquí.
Ahora sí que debería estar entrando.
¿No?
Porque aquí vemos este console.log.
If person.
Claro,
es que yo también.
Si no pongo el retor,
madre mía.
Yo me he puesto ahí súper contento
a escribir el JSX
como si hubiera mañana.
Y esto me pasa por no leer el chat.
Porque estoy seguro que en el chat estaréis,
Dios,
pero ¿qué tienes ahí?
Que no has puesto un retor,
que no sé qué.
¿Veis?
Ahora sí que funciona.
Vale,
ya está.
Ya decía yo.
Pero claro,
es que sin retor no funciona.
Vale,
pues entonces,
si encuentro a la persona,
devuelvo todo esto con este div,
con el person name,
no sé qué,
no sé cuánto.
Ahora sí que tengo esto del close.
Y entonces puedo entrar a cada uno,
uno de ellos y ya está.
Si miramos la network,
lo interesante de esto,
fíjate que ya no está entrando,
¿no?
Cada vez que yo le doy,
en lugar de estar haciendo peticiones,
pues no hace nada.
Si refresco,
voy a refrescar,
¿vale?
He refrescado y ahora le doy un clic.
Claro,
pues localhost,
pues es normal.
Ha hecho una petición donde ha buscado a Midudev
y ha sacado esta información.
Cierro,
le voy a dar a Pelu,
pues ha sacado esta información.
Hasdolo94,
saca esta información.
Pero si voy a Midudev otra vez,
pum,
no va a buscar la información,
¿vale?
Está utilizando la caché.
Cada vez que refresque la URL,
la página web,
pues esta caché se va a perder
porque está en memoria.
Podríamos utilizar localstorage,
en este caso,
en este caso,
para hacer esta,
este,
como ya hemos hecho en main,
y memory caché,
podríamos utilizar localstorage,
podríamos utilizar un montón de cosas
para intentar que persista.
Pero en este caso no tiene mucho sentido.
Ya os digo que hay otras opciones
con Apollo Client,
porque puedes tener clientes
donde tú quieras.
Esto es un cliente que sea en React,
pero podrías llegar a tener
un cliente de GraphQL,
en este caso un Apollo Client,
en otro servidor,
y es lo que os comentaba antes,
¿no?
Que a lo mejor quieres tenerlo
en base de datos y todo esto.
Vale,
pues aquí tendríamos este tema,
¿no?
Y el tema de la caché,
hay otro tema
que también puede ser interesante.
No sé si lo tengo activado.
Vale,
no lo tengo activado.
Esto normalmente,
voy a mirar esto como era,
a ver si aquí nos lo pone,
a ver,
DevTools,
esto.
A ver,
normalmente existe una extensión de Apollo,
que está súper bien,
que es Apollo,
esta,
mira,
el how to use,
no,
esta de aquí,
Apollo Client DevTools.
Esta es la que podéis ver.
Normalmente,
en muchas de las herramientas,
en Webpack,
en Creative Rackup,
creo que también,
no hace falta
que pongáis absolutamente,
que lo configuréis.
Le dais aquí
y ya os debería aparecer,
de gratis,
¿vale?
pero hay otras herramientas,
como por ejemplo,
a lo mejor,
Vite,
o si no lo veis,
que hay veces que hay que poner aquí este
Connect to DevTools
y ponerlo a True,
porque creo que lo que utiliza es el Node Environment
para ver si lo conecta o no lo conecta.
Entonces,
si veis que no lo conecta,
pues podéis hacerlo vosotros manualmente
o utilizar vosotros una variable de entorno aquí,
en el caso que lo queréis hacer,
¿vale?
Ver cuál sería
y utilizar la variable de entorno.
Por ahora vamos a ponerlo a True
para asegurarnos
que lo podamos ver
y vamos a ver si sale.
¿Vale?
Nos sale.
Raro es.
Voy a darlo a la vez por aquí.
Ahora sí que sale.
Bueno,
tengo que cerrar y volver a entrar.
Pero veis que ahora me aparece aquí Apolo,
es porque tengo la extensión
y aquí en Apolo podéis ver,
veis aquí ves ya las queries,
si le doy,
pues puedes ir viendo las queries activas
que se han realizado
la primera,
pues que no tiene nombre,
la de FindPersonByName.
Este es el nombre
que le hemos puesto aquí arriba.
También teníamos las mutaciones
y aquí puedes ver la caché.
Y en la caché
puedes ir viendo
qué es lo,
cómo se está montando un poco la caché.
¿Ves?
Aquí se ha estado haciendo
PersonTal,
PersonTal,
RoadQuery.
Aquí tendrías todas las queries,
¿vale?
Con las referencias y todo esto.
Y entonces,
conforme tú le vas dando,
pues podrás ir viendo
cómo se va montando,
qué es lo que hay justamente
en la caché.
¿Vale?
Ahí tendrías un poquito
de información
y ver y montar
cada vez que se hace una query
qué información se está añadiendo
a la caché
y por qué
nos está haciendo la query
o nos está haciendo
un fetch
o lo que sea.
Al final,
siempre podríais intentar
hacer un refetch,
que es lo que os decía antes.
Cuando tenéis aquí
este data error
o no sé qué,
pues hay otra,
por ejemplo,
refetch,
que es un método
que lo podrías llamar
para que obligarle
a que haga un fetch
otra vez
y cosas así.
Mutaciones,
mutaciones.
Vamos a crear
un nuevo componente,
le vamos a llamar
person form.
¿Vale?
¿Por qué?
Porque vamos a,
teníamos en nuestro servidor
una forma de crear usuarios.
No sé si lo tengo justamente
en el playground,
no sé si llegamos a crear
un usuario,
add person.
No sé si esto al final
lo conectamos.
Creo que no.
Vamos a ir un momento
aquí a GraphQL Server
porque como hicimos
el ejemplo
de conectar una API,
¿veis?
Que yo hice un fetch
aquí en el
all persons,
este hice un fetch.
En lugar de hacer esto,
¿ves?
Que lo hice desde el person
no sé qué,
no sé cuántos.
Lo que voy a hacer
es, nada,
tener el persons
y ya está.
Vamos a quitar esto
del fetch
porque es que esto
no lo estábamos utilizando
y más adelante
en la próxima clase
esto lo conectaremos
con un mongo de B,
lo haremos mucho mejor.
¿Vale?
Así que nada,
utilizamos,
vamos a quitar el ejemplo
que hicimos del fetch
y ya veremos
cómo hacemos asincronía
en condiciones.
Por ahora vamos a hacer
que utilice siempre
este estático
que tenemos aquí
y así pues nos aseguraremos
que no tenemos
información equivocada.
Teníamos una mutación
para añadir personas.
¿Vale?
En este caso
pues teníamos
el aborja 25
lo habíamos añadido.
A ver si lo añadimos
aquí y ves
pues ahora tenemos
el aborja.
Entonces vamos a ver
cómo podemos utilizar
esta mutación.
Vamos a copiarnos
esta query,
vamos a irnos por aquí.
Ah, una cosa importante
e interesante
que a lo mejor
alguna vez os preguntáis
oye,
¿cómo puedo utilizar
el tema de las variables
aquí?
Porque aquí
no me lo has explicado.
O sea,
aquí este findPersons
siempre me has puesto
aquí un string.
A ver,
si no recuerdo mal
esto no debería tener
mucha más historia
que exactamente
lo mismo que hemos hecho
esta query
que tenemos en el cliente,
esta que hemos hecho aquí,
en Persons,
sí,
esta,
la podríamos copiar,
deberíamos poder ir
al playground,
la podríamos pegar aquí
y ahora
este nameToSearch
que es una variable,
¿veis que aquí pone
query variables?
Pues aquí
deberíamos ser capaces
de pasarle
el nameToSearch,
¿ves?
Que además ha hecho
ya autocomplete
y decirle que me busque
pues el lapelo,
¿vale?
Y con esto
le da a la play
y aquí tendríamos
la información,
justamente.
Esta sería la forma
correcta de utilizar
variables a la hora
de hacer queries
en los playgrounds,
por si te lo estabas
preguntando,
que se puede hacer,
que no hay ningún problema.
Y más adelante
veremos cómo utilizar
los HTTP headers
en la siguiente clase
para el tema del token,
así que para que lo tengas
cristalino,
vamos,
no tengas ninguna duda.
Vale,
entonces,
tema mutaciones,
aquí tenemos la mutación esta,
me la voy a copiar
y nos vamos a nuestro cliente,
¿vale?
Que vamos a crear
este PersonForms,
Esto luego ya os digo
que lo vamos a
CreatePerson,
¿vale?
Esto lo vamos a refactorizar después.
Voy a copiar así
la mutación a saco,
pero voy a ponerle
un nombre a mutación
que sea CreatePerson
y para la persona
necesitamos un Name,
¿vale?
Que sea,
es justamente lo que vemos aquí,
pues lo ponemos aquí
como variables,
¿vale?
Que tienes un String,
necesita un Street,
que también es un String,
necesita una City,
que también es un String
y necesita un Font
que también es un String,
aunque el Font es opcional,
¿vale?
Ahora,
en AddPerson,
pues aquí tendríamos que utilizar
las variables
que hemos puesto arriba,
el Name,
el Font,
aquí el Street,
y aquí el City
y el Font,
¿vale?
Y con esto ya tendríamos.
Y aquí lo que se hacía en la mutación
era los campos
que queríamos devolver después,
¿vale?
En este caso teníamos
None,
Font,
a ver,
Id,
Address,
o sea,
todos,
básicamente,
¿no?
Sí,
todos.
Vale,
pues ahora que tenemos esto,
vamos a importar ya
tanto React
como Import
G,
ostras,
que he puesto,
he puesto algo muy raro
en el,
aquí,
aquí he puesto algo muy raro,
GQL,
¿vale?
Vale,
ya tenemos el Create Person,
ya teníamos la mutación
que queremos hacer,
vamos a ver cómo se haría la mutación.
Ya os digo que hay un hook
que se llama Use Mutation,
así que,
spoiler.
Vamos a hacer un Export
Const
de Person Form
que no le llega nada,
esto va a ser un componente
que,
a ver,
podríamos,
bueno,
lo voy a hacer,
pero aquí podríamos estar
haciendo pues cada una
de las cosas
que queremos hacer
para que tenga
un formulario,
Use State,
¿vale?
El Street,
porque vamos a tener
que hacer un formulario.
Podríamos utilizar el hook
que hicimos en su día,
que estuvo bastante bien,
pero bueno,
como son cuatro cosas,
vamos a hacerlo,
¿no?
Cuatro cosas eran,
¿no?
Un, dos, tres, cuatro.
Ok,
pues esas cuatro cosas.
Ahora,
ahora os enseñaré primero,
vamos a hacer un poco
lo que sería
el Handle Summit,
¿vale?
Esto lo tenéis que tener ya,
pero grabado,
¿no?
¿Cuántas veces hemos hecho esto ya?
Unas cuantas,
¿no?
¿Vale?
Vamos a dejarlo por ahora así
y vamos a,
bueno,
cuando termine el Handle Summit,
además,
pues vamos a hacer
que el formulario
se quede limpio,
Set Zone,
Set Street,
y el Set City,
¿vale?
Vamos a ver
qué tiene que renderizar
este componente.
Bueno,
pues este componente
tendríamos aquí
un div,
bueno,
Create New Person,
vamos a crear personas,
somos como dioses,
más o menos.
Cuando hacen un Summit,
un Handle Summit,
qué importante
el Prevent Default,
porque si no el Summit
funciona,
bueno,
los que funcionen correctamente,
pero no funciona bien,
¿vale?
A ver,
podríamos,
bueno,
vamos a hacerlo más fácil,
¿vale?
Vamos a poner el Input,
si no,
podría poner un Label
para cada uno,
pero sed buenos
y haced esas cosas,
¿vale?
Vamos a tener aquí
el Name
y cuando cambie este,
pues nada,
lo que vamos a hacer es,
podríamos hacer un Handle,
bueno,
me lo copio
y lo pego y ya.
Aquí tendríamos el Event,
¿vale?
El OnChange,
tendríamos el Event
y de este Event
vamos a hacer un SetName
del Event
.target.value,
¿vale?
Esto sería así
y ya esto
lo podríamos hacer
con cada uno de ellos,
¿vale?
Teníamos el Set,
este sería el nombre,
vamos a poner el Playholder
con el nombre,
con el Name
y ahora esto,
lo pegamos cuatro veces.
Tendríamos el Name,
tendríamos el Phone,
tendríamos el Street,
Street Fighter
y tendríamos el City.
Este sería el Phone,
esto sería Street,
esto sería City
y, hombre,
esto también lo podría haber cambiado antes.
Esto sería
SetFund,
SetStreet
y Set City.
La verdad es que
lo lleva a saber
si damos un custom hook o algo.
Si tenía uno por ahí
que lo hicimos.
Bueno,
AddPerson.
Venga.
Bueno,
a ver,
esto está bien,
este pedazo de componente
que hemos hecho aquí
en un momento
escribiendo como locos,
lo puedo añadir,
lo puedo añadir aquí mismo,
a ver si aparece al menos.
¿Vale?
¿Vale?
Apetado porque
PersonForm,
claro,
lo estoy utilizando
pero no estoy...
PersonForm,
From,
PersonForm,
¿Vale?
Importamos el PersonForm,
otra vez.
El UseState
que no estamos importándolo
y que estoy utilizando.
State
y ahora sí,
¿Vale?
Venga,
perfecto.
Y ahora sí que tenemos aquí
un formulario
maravilloso,
enorme.
Igual lo podríamos poner
dentro del header,
aunque no es muy correcto,
pero es que está estilado
y a lo mejor queda un pelín mejor
que esté dentro.
Bueno,
más o menos.
Ahí tendríamos,
¿No?
A ver,
este formulario ahora no hace nada
más allá de que tú escribes
y debería refrescarse,
pero no está haciendo la petición.
Para ello,
lo que tenemos que hacer
en el PersonForm
es utilizar el UseMotation.
Esto lo habíamos ya importado aquí.
¿Cómo haríamos
el UseMutation este?
Es muy similar al UseQuery,
¿Vale?
O sea,
no tiene mucha historia.
La única diferencia
con el UseQuery
es que cuando utilizamos
el UseMutation,
claro,
cuando tú haces
un UseMutation
tienes que decirle
la query o mutation
que quieres hacer,
en este caso es el CreatePerson
y aquí en la constante
de nuevo es un array
y aquí lo que tenemos que decirle
es un CreatePerson.
¿Por qué?
Porque el UseMutation,
quieras o no,
siempre es lazy.
Eres tú cuando le dices
que tiene que utilizarse,
¿Vale?
No puede hacerlo así
directamente.
En este caso,
lo que estamos diciendo
al UseMutation
es devuélveme un método
que yo llamaré
para que hagas la mutación.
Le llamamos CreatePerson
y le puedes poner el nombre
que tú quieras,
¿Vale?
Pero en este caso,
CreatePerson.
Lo vamos a hacer
en el HandleSubmit
y igual que hemos visto
con las variables de antes,
aquí lo mismo.
Teníamos las variables
y qué variables
tenemos que decir.
Pues el NOM,
el FAME,
el STREET
y el CITY.
¿Vale?
Estas son las variables
que son exactamente
las mismas que tenemos aquí.
NAME, FON, STREET, CITY.
Es que el FON
lo he puesto dos veces.
¿Vale?
Es que estaba dos veces.
Bueno, seguro
que lo habéis puesto en el chat,
pero no lo había visto.
NAME, FON, STREET, CITY.
Ya decía yo
que antes he contado cuatro
y me sonaba que había cinco.
NAME, FON, STREET, CITY.
Vale, pues eso sea la mutación.
Si ahora volvemos aquí
y decimos vamos a volver,
vamos a recuperar aquí
el, yo que sé,
vamos a buscar en el chat
a ver quién hay.
¿Quién hay en el chat?
Shell, mira,
STATEFUL.
Vamos a ver.
STATEFUL.
STATEFUL.
1, 2, 3, 2, 3,
y ta-da-da.
ADPERSON
y ya lo tendríamos, ¿no?
Si miramos en la NAME,
bueno, espérate,
vamos a ver la NAME,
DATA, ADPERSON.
Vale, ha añadido STATEFUL y tal.
Pero claro,
¿cuál es el problema?
Que aunque yo he añadido
a esta persona,
no me aparece aquí.
Esto es un poco rollo.
Si refresco,
si entramos a otra pestaña,
ves, sí que me aparece.
O sea,
es un poco raro, ¿no?
Lo que ha pasado
porque yo he añadido
a una persona,
he visto aquí
en el servidor
que me ha dicho
que lo ha añadido,
pero aquí en la lista de personas
no me ha aparecido
por arte de magia
que es lo que me hubiera gustado,
es lo que hubiera esperado.
Pero en cambio,
cuando he entrado a otra pestaña,
sí que está aquí,
STATEFUL, ¿vale?
O sea que sí,
bueno,
¿veis?
Además puedo entrar
y ahí tiene todos los detalles
que he escrito.
Entonces,
aquí estamos teniendo
un problema
y esto es un problema
que suele ocurrir
cuando queremos
que la UI
esté sincronizada
con lo que hay
en el servidor, ¿no?
Y hay diferentes opciones.
Las dos más básicas,
que son las que te voy a explicar ahora,
sería
ir preguntando,
¿no?
ir diciendo,
vale,
tienes información nueva,
bueno,
tienes información nueva,
no,
haz una petición
para traer la información nueva.
Para ello,
aquí en este Use Query,
este All Persons,
lo que podríamos hacer
es un Poll Interval,
que le vamos a decir
un tiempo
en el que
cada X tiempo,
en este caso
milisegundos,
voy a decirle
que cada dos mil milisegundos,
que son dos segundos,
pues que vuelva a preguntar
para volver a hacer la query
para recuperarla,
¿no?
Y si hay algún cambio,
pues lo reflejará en la UI.
Si guardamos estos cambios
y volvemos a nuestra
petición aquí,
bueno,
esto no se va a refrescar,
me parece ya.
Vamos a probar aquí,
a ver si aquí sí que funciona.
Vamos a crear uno,
ta, ta, ta, ta,
Add Person.
¿Veis?
Pues ha ocurrido.
Claro,
no es que ha ocurrido
dos segundos después,
porque como esto está ocurriendo
cada dos segundos,
pues a lo mejor ha ocurrido
después de medio segundo.
Pero claro,
esto tiene un problema.
Esto puede ser interesante
hasta cierto punto
para algunas,
pero fíjate lo que ocurre aquí,
¿no?
Lo que está pasando
cada dos segundos.
Cada dos segundos
está haciendo una petición.
Esto a veces puede tener sentido,
¿vale?
O sea,
hay veces que esto puede tener sentido,
especialmente en cosas
en las que esta petición
tiene muy poco coste
y necesitas que cada segundo,
cada dos segundos,
pues mirar la disponibilidad
de una habitación,
¿no?
Imagínate que es Airbnb
y tienes que ir chequeando
si la habitación
está disponible todavía
para evitar
que se haga algún tipo de,
pues eso,
que intenten reservar la habitación
y ya no está disponible.
Pues bueno,
puede ser que hicieran algo así.
Aunque ya os digo,
la forma más avanzada
es hacerlo con suscripciones,
que es un poco más complejo,
pero es un poco más seguro.
Esta sería una forma,
¿vale?
Esta sería una,
que sería el tema
de hacer un polling,
que es cada dos segundos
o el tiempo que tú le digas,
en este caso le hemos dicho dos segundos,
le podríamos poner cinco horas,
o sea,
da igual.
Obviamente que cinco horas
no tendría mucho sentido,
pero bueno,
esta sería una.
¿El problema que tiene esto?
Pues que está haciendo más fetch
de seguramente lo necesario,
¿no?
Sin necesidad,
lo que está ocurriendo aquí
es que está,
está como haciendo
refetching constantemente,
¿no?
Sin,
a lo mejor,
ser necesario.
Otra estrategia
podría ser la contraria.
En lugar de decirle a esta query
que queremos que no pare
de hacer este tipo de petición
cada dos segundos,
lo que podríamos hacer,
voy a exportar esta query de aquí,
esta query all persons,
lo que podríamos hacer es,
donde estábamos mutando,
¿no?
Donde estábamos creando esto,
cuando hacemos la mutación,
le podemos pasar más parámetros aquí.
Y le podríamos decir,
mira,
hay una opción
que es refetch queries.
Y tú le puedes decir
que cuando haga la mutación,
le puedes decir,
vale,
todas las queries que quiero
de las que hagas refetch,
o sea,
que sería más bajo demanda.
Cuando yo hago la mutación,
quiero que me hagas un refetch
de la query
y aquí le sería all persons,
¿vale?
Que la tendríamos que importar,
que me la ha importado automáticamente,
¿ves?
De la app.
¿Por qué?
Porque la he exportado yo aquí.
¿Ves?
Que he hecho un export,
la importo aquí,
y le digo,
vale,
quiero que cuando hagas esta mutación,
me hagas un refetch
de esta query en concreto.
A ver,
esto está bastante mejor
porque al menos
lo que vamos a conseguir con esto,
a ver,
voy a refrescar por aquí.
Ahora se supone que yo
si creo aquí esto,
pa, pa, pa, pa, pa, pa, pa, pa, pa, pa, pa, pa.
¿Veis?
Ahora me ha aparecido automáticamente,
pero fíjate que ha hecho más,
ha hecho dos queries.
Una,
la de la mutación
y otra para volver a recuperar
esa información
que viene de la base de datos.
¿Vale?
Esta sería una forma
que no está mal
y la verdad es que para este tipo de cosas
que es añadir datos una vez
pues puede tener sentido
puede ser una forma bastante ideal
porque así evitamos tener que estar
preguntando todo el rato
es bastante mágico en el sentido que
está genial que la UI responde
además hemos ya cacheado esto
porque si la próxima vez necesitamos
hacer este tipo de query ya no sería necesario
porque nos hemos traído esta información
y ya estaría
así que estas serían las dos formas más sencillas
ya os digo que existe otra que sería con
suscripciones que no sé
si veremos pero me lo miraré
a ver pero bueno que sepas
que funcionaría de esta
forma vale
otras cosas obviamente esto de tener
aquí las queries esto está prohibidísimo vale
tenéis diferentes formas
de hacer esto hay gente que le gusta hacerla
de una forma de otra hay gente que le
gusta estructurar esto
como una forma que se llamaría
screaming architecture vale
una arquitectura que grita vale
esto es una forma esto es muy interesante
que mucha gente me pregunta cómo hago
el tema de las carpetas y todo esto
entonces
hay diferentes formas de estructurar
carpetas y depende de cómo de grande
sea tu proyecto pues puede ser más interesante
una u otra
una sería la de screaming architecture
que para proyectos pequeños
o que no cambian mucho puede estar
bastante bien
qué significa screaming architecture
es una arquitectura que grita
por qué porque tus carpetas
te están indicando qué arquitectura
estás siguiendo por ejemplo si yo pongo aquí
graphql pues esto está gritando
que estoy utilizando graphql y aquí dentro
pues podríamos tener queries
por ejemplo y podríamos tener
mutations
esto sería una forma de hacerlo
que no significa que esté mal ni nada
sino que simplemente tienes que tener en cuenta
que claro si un día cambias graphql pues
a lo mejor el tener que hacer todos estos cambios
sería bastante grande
pero aquí tendrías todas las queries
y las podrías tener y ya está
no habría ningún problema
otra forma de hacer esto
en lugar de hacer graphql sería más bien
hacerlo por contexto de tu negocio
en este caso estábamos haciendo
un listing telefónico con personas y tal
lo que podríamos hacer
en lugar de utilizar graphql
lo que podríamos tener sería el contexto
personas o persons
y dentro de persons
como es un concepto de tu negocio
dentro de persons
ya tendrías sí archivos
que podrías queries
o graphql queries
graphql queries
por ejemplo
y graphql mutations
la diferencia aunque es útil
es importante
especialmente cuando tu proyecto crece
porque cuando tu proyecto crece
cuando ya en la raíz tienes
tu arquitectura gritando
es diferente
que si tú tienes el contexto
que esto no debería cambiar nunca jamás
en la vida para tu proyecto
y dentro de tu
de esta carpeta
tú tengas ahí separados
graphql
puedes tener un montón de cosas
esto también
creo que en redax
se le llama dax
¿vale?
a este tipo de
de estilo de poner por contexto
las cosillas
la que prefiráis
yo no creo que haya una peor que otra
ni que una sea mil veces mejor
normalmente
esta de poner el nombre
de tu arquitectura
o de las cosas que utilizas
en tu arquitectura
funciona bien en proyectos pequeños
o que no cambia mucho
y esta suele funcionar mejor
en proyectos grandes
¿vale?
o que cambian bastante
o que tienes
cada dos por tres
que añadir nuevas cosas
porque si no esta
no suele crecer muy bien
porque entonces tienes aquí
redax
o ya directamente tienes
por ejemplo
reducers
no sé qué
en cambio la otra
pues lo tienes
más contenido en un sitio
que al final puede ir cambiando
de una forma más sencilla
y puedes agrupar
aquí podríamos poner
custom hooks también
lo que sea
si queréis lo podemos mirar
vamos a hacer la segunda
que quizás es la más rara
en la que mucha gente
bueno más rara
no sé
a mí sé que mucha gente
no hace esta
y hace más la otra
pero bueno
no tiene mucho misterio
el tema
por ejemplo
las mutaciones
¿esta será una mutación?
pues nada
nos la traemos
la cortamos de aquí
y la pondríamos aquí
¿vale?
y la exportamos
esto por un lado
y aquí pues importamos
¿cómo se llamaba esto?
create person
pues create person
bueno
de hecho
esto sería la primera
esta sería la primera cosa
que podríamos hacer
pero podríamos hacer más cosas
¿eh?
¿por qué?
y ahora
ahora lo enseñaré también
que es donde está la gracia
también de
de la polo client
lo ideal
para
para mí
si estábamos hablando
de tener una buena
buena
separación
de hacer las cosas
porque muchas
muchas veces la gente
me pregunta más
por las carpetas
como si las carpetas
fueran algo mágico
pero lo ideal
en un mundo ideal
de cómo separar
realmente esto
es que
este componente
no supiera
que utiliza polo client
¿vale?
o sea que
todo esto que vemos aquí
en realidad
lo tuviésemos
en un custom hook
a ver
lo podríamos
lo podríamos ver
vamos a ver
esto
vamos a quitarlo aquí
esto sea use mutation
bueno
mientras separamos este
por ejemplo
este de all persons
que este lo pondríamos aquí
queries
ahora en el
perform
este all persons
vamos a ponerlo aquí
persons
de queries
¿vale?
y esto ya lo dejaremos así
pues por ejemplo
estas queries
que teníamos aquí
¿vale?
esto no estamos utilizando
ya esto
este use query
que estamos haciendo aquí
al final
lo que podríamos hacer
que esto lo hemos visto
en la clase anterior
tendríamos el use
use persons
por ejemplo
¿no?
y aparte
a partir de use persons
al final
todo esto que teníamos aquí
lo podríamos sacar
y hacer así
con result
devolver el result
¿vale?
loading persons
no sé qué
entonces en persons
tendríamos aquí
un custom hook
o le podríamos poner
use persons
como queráis
use persons
lo que prefiráis
podría ser custom hooks
¿por qué?
porque al final
puedes tener más de uno
¿vale?
pero bueno
vamos a ponerle custom hooks
pondríamos aquí
custom hooks
un export de custom hooks
y aquí
en lugar
¿ves?
ya no teníamos nada
de use query
ya no teníamos
nada de use effect
no sé qué
no sé cuánto
deberíamos tener
el use persons
from
persons
custom hooks
y entonces
este
este app
por ejemplo
ahora
que esto debería ser
lo mismo
loading
error
pero hasta
sería
the use persons
lo que estamos
consiguiendo aquí
es que este componente
no sabe
de dónde viene
la información
¿vale?
o sea
lo que estamos
consiguiendo
básicamente
es eso
es
que el día
de mañana
bueno
vamos a ver
si esto funciona
vale
parece que
sí que funcionaba
no
apetado
espérate
gql is not defined
es que como no tengo
ves
como no tengo
el inter
no se me queja
cuando
no estoy
por los client
vale
esto también
por los client
custom hooks
claro
yo voy importando
aquí cosas
como si
no pasase nada
¿no?
como si me lo
fuese a hacer
todo gratis
vale
espérate
all persons
is not defined
que este
all persons
viene de
punto barra
graph query
vale
vale
ya lo tendríamos
cuál es la gracia
de todo esto
la gracia de todo esto
es que tus componentes
de react
no saben
de dónde le viene
la información
una cosa
que tienes que tener
bastante cuidado
en este tipo
de
de patrón
¿no?
de
estamos utilizando
un custom hook
pero podría ser
un montón de cosas
sería
que
lo que sea
que devuelve
este custom hook
tiene que ser
un contrato
que puedas cumplir
pese a que el día
de mañana
tú
en lugar de
de utilizar
apollo client
utilices fetch
por ejemplo
o sea
lo interesante
es que
este componente
yo
si ahora
por lo que fuese
digo
ya no quiero utilizar
apollo client
vale
pues en lugar
de utilizar
apollo client
voy a hacer
un use effect
que era lo que hicimos
al principio
¿no?
con el fetch
no sé qué
no sé cuánto
y al final
lo que tengo que conseguir
es que este
retón
siempre devuelva
data
loading
y error
independientemente
si utilizo
el apollo client
o no
eso
aunque no es
la mejor
arquitectura
del mundo
porque yo creo
que habría que llevarlo
a una arquitectura
hexagonal
y al menos
la parte esta
de la lógica
de negocio
separarla mejor
al menos
sería un primer paso
en lugar de tener
todo esto
dentro de tus componentes
esta es una de las gracias
de los custom hooks
y en este caso
creo que puede
tener bastante sentido
entonces
no es tanto
el separar
en carpetas
porque al final
si en
este app
dentro
lo que tienes
es la llamada
el apollo client
o por ejemplo
otro mal
o yo considero
que no está bien
sería hacer esto
use
graphql
persons
este tipo de cosas
no tiene sentido
¿vale?
porque si tú
le estás indicando
cuál es la implementación
que tiene este custom hook
pues al final
es que no estás
haciendo nada
¿vale?
esto lo veo muchas veces
que la gente hace
use fetch
o no sé qué
la gracia
de los custom hooks
justamente
es que te pueda permitir
esto de
tapar
la implementación
que tiene ese custom hook
por si el día de mañana
cambias como lo hace
mientras devuelva lo mismo
todo debería funcionar
exactamente igual
pero bueno
esto como luego me decís
que no
hacen este tipo de contenidos
de no sé qué
pues ahí lo tenéis
¿vale?
que si no al final
me echa de bronca
bueno
pues esto sería una
buena forma de
tener una buena estructura
con componentes de React
a ver
no lo voy a hacer con todos
¿vale?
no lo he hecho
con todos
pero bueno
si os queréis entender
lo mismo se podría hacer
con el use mutation
y de hecho
en un mismo custom hook
o podríais tener
use persons
o podríais tener
más de un custom hook
use add persons
o lo que sea
¿no?
o podéis tener
un solo custom hook
para todos
como veáis
eso depende
de un montón de cosas
¿ok?
vale
entonces
hasta aquí bien
¿vale?
os he enseñado un poco
esto del custom hook
creo que esto estaba funcionando
si entramos
pues perfecto
todo funcionando bien
hay una cosa
que se nos ha quedado
un poco en el tintero
¿vale?
aunque parecía
que todo funcionaba bien
aquí en el
create new person
si yo me pongo aquí
y le doy a add person
fíjate que aquí
me mete un pete
name más bio unique
¿cómo?
ah vale
o sea
había puesto
el mismo nombre
que he añadido antes
el de
asd
asd
bueno
en fin
pero bueno
que el error
habéis visto
que no lo estamos
controlando
de ninguna forma
o sea
yo me pongo ahí
a escribir
como un loco
y no hay ningún
no vemos ningún tipo
de error ni nada
se pueden
una de las cosas
que también tiene
el cliente de
de apolo
que es muy interesante
es el hecho
del manejo de errores
¿vale?
igual que podemos hacer
lo del refetch
y todo esto
aquí
aparte del refetch
es que hay un montón
de cosas
¿veis?
aquí hay un montón
de cosas
que le podéis pasar
y bueno
casi todas son una maravilla
pero hay una
que es realmente útil
que es la de
on error
lo que podemos hacer
con el on error
pues podríamos pasarle
al person form este
esto como queramos hacerlo
pero bueno
le podríamos pasar
un set error
o notify error
vamos a ponerle
notify error
¿vale?
notify error
pues esto
cuando tengamos aquí
un error
pues vamos a notificar
el error
esto aquí
este error
si lo miráis
veréis que tiene
una estructura de datos
a ver si queréis
lo podríamos poner
hacer el console log
y tal
pero la estructura
de datos es
graphql errors
de hecho veis que ya me
hace autocomplete
graphql errors
esto es un array
bueno
por ahora vamos a coger
tomar el primero
y mostrarlo
¿de dónde aparece
este notify error?
bueno
esto lo podemos hacer
en el app.js
esto se lo pasamos aquí
por ejemplo
tendríamos aquí
un estado
que sea
error message
set error message
error message
use state
esto le pasamos null
y aquí
pues podríamos tener
el
notify
error
con el message
y que aquí
bueno
set error message
con el message
que le pasamos
este notify error
es el que le vamos a pasar
por props
al person form
¿vale?
así que el person form
tenemos notify error
notify error
podríamos
hacer que desaparezca
el error
después de un rato
¿no?
o sea
le hacemos
set error message
lo pasamos a null
después de
5 segundos
¿vale?
así que este
método
notify error
cuando haya un error
aquí en la mutación
pues lo llamaremos
con este error
de aquí
ya le vamos a lab.js
y aquí lo que podemos hacer
pues podríamos tener
también un componente
que sea notify
notify
o notify
así ya secas
error message
con el error message
¿vale?
esto lo he puesto dentro
pero debería ir aquí
y este componente
vamos a crearlo por aquí
notify.js
¿vale?
pues export const
notify
error message
si no tenemos error message
pues nada
devolvemos null
y si no
pues lo que hacemos
es un div style
bueno
alguien
antes me ha dicho
que los estilos
son con objetos
y tiene toda la razón
en react
son objetos
no es en string
antes lo había hecho
rápidamente
porque no le había
dado mucha importancia
pero bueno
position fixed
vamos a ponerle
un poco de enmero
estos son comas
en lugar de puntos y coma
yo también
vale
with
100%
no sé si esto
cómo se verá
no tengo ni idea
pero bueno
lo dejamos así
y ya está
el notify
me lo importo
from
notify
¿vale?
y
vale
espérate
use state
no le he importado
aquí
vale
ahora sí que lo tenemos
add person
papapá
bueno
apetado
porque react
es notify
vale
es que tenía que haber importado
que react
a ver
esto de tener que importar
react
from react
es porque estamos
utilizando vite
¿vale?
si no utilizamos vite
con query backup
creo que ya no es necesaria
vale
pero veis
ahora
name must be unique
o sea ya estamos gestionando
el error
y bueno
dentro de
después de unos segundos
desaparece
podría
a ver
eso podéis ponerlo
como queráis
a lo mejor lo podemos haber puesto
en el formulario mismo
pero bueno
solo para que veamos
cómo lo podríamos
gestionar
vamos a hacer rápidamente
otra
para que veamos
el tema de cómo se sincroniza
el tema de la caché
¿vale?
y es el hecho
de
teníamos otra
que era
editar el número de teléfono
veis que tenemos aquí
edit number
le pasamos el name
le pasamos el font
y podríamos editar
el número de teléfono
de una persona
vamos a hacerlo
porque esto
lo que deberíamos ver
es cómo se actualiza
la caché
sin que nosotros
hagamos nada
vamos a ver si
se hace magia
el Apollo Client
por nosotros
como esperamos
persons
mutation
vamos a crear aquí
export const
le vamos a llamar
edit number
gql
y aquí le pasamos
nuestra mutación
vamos a copiarnos
esta mismo
mutation
le vamos a poner
un nombre a mutation
edit number
¿qué parámetros necesitamos?
necesitamos el name
así que
el name
y necesitamos el font
y este
es obligatorio
edit number
pues
del name
que le tenemos
como parámetros
y del font
y ahora aquí
pues podríamos recuperar
el name
el font
address
vale
vamos a recuperarlo todo
y aquí hay un tema
que es interesante
por ahora vamos a recuperarlo todo
nombre
teléfono
la dirección
la id
todo
vale
lo dejamos aquí
y lo que podríamos hacer
es crear otro componente
con el
podríamos copiarnos
del person form
más o menos
vale
y le vamos a llamar
font form
font form.jsx
vamos a copiarnos
le damos font form
no hace falta ya
el notify error
pero vamos a dejar
tanto el name
como el font
esto lo quitamos
el name y el font
esto lo quitamos
esto en lugar de
esto ahora lo
lo hacemos desde cero
esto lo vamos a llamar
change
change font
y vamos a poner
edit font number
y le quitamos todo esto
es que es muy parecido
entonces para qué
vamos a reinventar
la rueda
este create
person
no es lo que vamos a hacer
en lugar de hacer
el create person
lo que vamos a utilizar
es el edit number
este old person
no lo necesitamos
el use mutation
sí
así que
font form
vale
qué es lo que queremos hacer
queremos utilizar
el use mutation
pero con el edit number
y esto lo que nos devuelve aquí
es la mutación
change number
vale
change number
cuando llamamos
el change number
cuando se haga el submit
de este formulario
así que
lo llamamos aquí
y las variables
que le tenemos que pasar
es name
y font
esto de street city
es de lo de antes
no lo necesitamos
vale
voy a ver si se me ha olvidado
alguna cosa
no la vaya a liar parda
set font
set name
vale
vale vale
handle submit
no sé qué
vale
ahora lo que estoy pensando
es donde deberíamos
deberíamos
añadir el font form
a ver
bueno
podríamos poner en cualquier sitio
venga
aquí mismo
lo habíamos puesto
debajo de la persona
vamos a poner aquí
el font form
y ya está
lo voy a poner encima
para que lo veamos
un poco más claro
vale
ahora seguro
que se me ha olvidado
que se me ha olvidado ahora
it's not defined
porque lo tengo que importar
lo he exportado
pues lo importamos de aquí
font form
from
font form
en un momento
una de formularios
una de historias
que hemos hecho aquí
vale
ahora tengo este formulario
edit font number
vale
y lo que voy a hacer
es editar el número de teléfono
de una persona
por ejemplo
de
hay
entrado a midudev
pues
de midudev
vale
no me deja
copiarlo
vale
midudev
y le vamos a poner el teléfono
688999999
change font
pum
vale
fíjate lo que ha pasado
porque me aparece allá
la información
correcta
correcta
o sea
le he cambiado
el número de teléfono
aquí en el edit font number
le he cambiado el número de teléfono
a midudev
y me ha salido
directamente aquí
la información
correcta
o sea
está haciendo magia
vamos a probarlo otra vez
yo voy a da pelu
vale
da pelu
venga
voy a da pelu
y le digo
688
6541253
654125353
vale
change font
mira
y le ha cambiado otra vez el nombre
le ha puesto
el número de teléfono correcto
magia
vale
que es lo que está pasando aquí
y que es lo que está
está haciendo todo esto
vale
y como lo está cambiando
y como sabe que está cambiando
tiene que cambiar eso
lo que está ocurriendo aquí
es que
cuando tú haces una mutación
es lo que os he comentado
en la clase
cuando tú haces una mutación
vale
en esta mutación
yo estoy haciendo la mutación
de cambiar el número de teléfono
que es esta de aquí
que pasa
que la persona
a la que estoy cambiando
el número de teléfono
tiene una idea
y lo que está haciendo
la polo client es
ostras
tú le estás haciendo
una mutación
a este
a esta persona
que tiene esta idea
de aquí
pues yo voy a mirar
en mi caché
y al mirar en su caché
lo que ha visto
vale
lo que ha visto
es que esta persona
con esta idea
dice
ostras
pues yo esta persona
con esta idea
a ver si ahora
se ve esto un poco más grande
esta persona
con esta idea
pues la tengo en la caché
pues lo que voy a hacer
es cambiar
esa información
que tengo en la caché
la voy a cambiar
de forma
que ahora voy a guardar
con la nueva información
que me estás diciendo
y ahora aquí
en el all persons
podríamos ver
cómo tenemos
la información esa
que nos interesa
la persona de mi dudez
vale
o sea
lo que hemos conseguido
es que
bueno
lo que ha conseguido
lo ha conseguido realmente
a ver si tenemos aquí
la persona de mi dudez
pero veis
tenemos aquí la persona
y la tenemos con este teléfono
cuando tiene esta persona
y tiene esta idea
lo que ha conseguido básicamente
es tener la información
toda guardada
porque además
fíjate
que yo cada vez
que la voy creando
pues él va guardando
aquí toda la información
y cuando
una vez que le devuelve
la mutación
con la información
dice
ostras
pues ahí está
en cambio
¿qué pasa?
vamos a ver una cosa
yo cuando hago la mutación
edito el número de teléfono
y fíjate que yo recupero
el nombre
el teléfono
la dirección
y la idea
vamos a hacer
que solo me devuelva
por ejemplo
el nombre
¿vale?
cuando yo hago la mutación
recordad
que cuando tú haces una mutación
aparte de pasarle
los parámetros
para hacer la mutación
lo que le puedes decir
es
el resultado de vuelta
y en las mutaciones
en GraphQL
normalmente
bueno, normalmente no
lo que te suele devolver
es
las propiedades
del propio objeto
que está mutando
por lo tanto
yo podría recuperar
de la persona
que le estoy cambiando
el número de teléfono
podría recuperar
su nombre
el teléfono
la dirección
y todo esto
vamos a recuperar ahora
solo el nombre
¿vale?
por poner un ejemplo
por ver qué pasa
vamos a ver qué pasa
voy a refrescar
y tenemos aquí
pues voy a poner
MiduDev
y ahora le pongo
un 234
y cambio el teléfono
¿qué ha pasado?
¿qué ha pachado?
¿qué ha pachado?
no, ¿qué ha pachado?
fíjate
que ahora no me lo ha cambiado
pero Midu
¿qué has hecho?
te lo has cargado
se acaba de funcionar
bueno, vamos a probar
con Dapelu
igual es el Dapelu
Dapelu
¿vale?
le voy a cambiar el número
56789
cambiar
no cambia
¿y ahora qué?
¿lo he roto?
¿qué pasa?
lo que pasa
es que
si tú quieres que ocurra
este enlace
lo que tienes que hacer
es devolverle
justamente aquí la ID
cuando estás mutando
ese objeto
le tienes que decir
vale
si tú lo que quieres
es que yo lo sincronice
cuando termine la mutación
tienes que devolverme
la ID
del objeto
que has mutado
para que Apolo
sea capaz
de hacer
de hacer ese enlace
de decir
ah, vale
que es que
lo que ha cambiado
lo puedo enlazar
pero claro
si yo ahora
le paso la ID
tampoco sería capaz
de hacer exactamente
la sincronización
porque tampoco
le estoy diciendo
cuál es el valor nuevo
o sea que también
debería decirle
cuál es el teléfono
¿vale?
o sea
que si queremos
que ocurra
esa sincronización
y que actualice
la información
con lo que
queremos que esté
en la UI
tendríamos que pasar
aquí todos los campos
que queremos
que se sincronicen
¿vale?
así que es necesaria
la ID
y el campo
que queremos
que se sincronice
si no
no ocurre
como hemos podido ver
de hecho ahora
si ponemos
new dev
y le ponemos
9333
¿vale?
ahora sí que pasa
así que esto
es súper
súper importante
que lo tengas
en caso
en cuenta
¿no?
porque
muchas veces
esto
la gente
pues dice
hostia
pero porque no me funciona
la sincronización
yo pensaba
este es el problema
entonces
ahora que sabes esto
Renato Mendoza
hace una muy buena pregunta
que dice
¿pero Apolo Client
reemplaza Redux?
sí y no
sí
en el sentido
de que
si tú utilizas
mucho GraphQL
cuando hagas una mutación
sobre objetos
que tienes en el esquema
tienes ya un estado global
lo que acabamos de conseguir
es un estado global
que nos funciona
en todos los sitios
nos funciona en todos los sitios
gratis
además
sabes
no tienes que preocuparte
tú
de hacer absolutamente
nada
por lo tanto
si de alguna forma
es una ventaja
de que esto
es como un estado global
que ya no tienes que hacer nada
¿vale?
pero
es cierto
que cosas que no estén
dentro de GraphQL
pues todavía necesitarás
un estado global
o si son cosas de la UI
que no tienes mutaciones
pero
te puede quitar
mucho trabajo
que tengas de Redux
¿vale?
muchas cosas que hagas con Redux
igual
ya no las necesitas
porque te va a hacer
automáticamente
un estado global
con este tipo de cosas
pero hay cosas
que a lo mejor
sí que es necesario
que lo sigas haciendo
otra cosa importante
si os acordáis
cuando hacemos mutaciones
claro
si yo aquí pongo
asda
o sea
bueno
voy a poner
no lo encuentro
¿vale?
vamos a editar
el número de teléfono
de una persona
que no existe
y yo le cambio el teléfono
pues no pasa nada
y si inspecciono
le miro la consola
¿vale?
y intento aquí
pues cambiar el número de teléfono
de no lo encuentro
y digo
change phone
ni siquiera peta
o sea
no hay ningún problema
¿por qué pasa esto?
porque GraphQL
considera que esto
es una operación válida
importante
¿por qué considera
que es una operación válida?
porque
tú si intentas cambiar
el número de teléfono
de null
pues
lo que ocurrirá
es que no lo cambia
y ya está
pero no es un error
dice
bueno
no lo he encontrado
pues no lo
no hago nada
si queréis solucionar esto
y queréis controlar
este tipo de problemas
entre comillas
podríamos ir al phone for
y aquí
como hemos dicho anteriormente
era un array
pero porque tiene
un segundo
una segunda posición
que sería el resultado
o los resultados
¿vale?
en este caso
en este caso
el result
el resultado
nos podría decir
si está devolviendo
algún tipo de información
así que
cuando
estamos aquí
podríamos hacer
un useEffect
¿no?
useEffect
de nuevo
¿vale?
y lo nuevo
si tenemos
resultado
la data
result.data
que siempre es igual
result.data
punto
miramos como llaman
la mutación
pues EditNumber
¿no?
pues EditNumber
si esto es igual a nul
porque no ha hecho nada
entonces podríamos hacer
podríamos utilizar
el NotifyError
que teníamos antes
este NotifyError
¿vale?
NotifyError
ponemos aquí
el NotifyError
y podríamos decir
vale
si está
la propiedad de data
en resultado
y además
EditNumber
es nul
significa
pues que
no hemos encontrado
PersonOfTown
y podríais controlar
el error
de mil formas diferentes
¿eh?
como te la gana
podemos hacer un error
y poner PersonNotFound
también aquí
por si lo queréis ver
también la consola
o lo que sea
pero con esto
al menos
ahora
cuando busquéis
no lo encuentro
pues ChangeFound
¿veis?
PersonNotFound
y PersonNotFound
pero es lo que está ocurriendo
¿vale?
podríais poner aquí
personas que no encontráis
bueno esto no sé
porque se ha vuelto loco
pero que ese es el tema
¿vale?
ah y esto es porque
creo que es el timeout
ese que he puesto antes
que a lo mejor no
ah bueno claro
es que esto se
se está quedando aquí
porque este UseEffect
que he puesto aquí
este tiene
esto no
esto lo he puesto aquí
y esto no es así
esto debería ser aquí
con el Result.data
que si no se pone en infinito
¿vale?
tenerlo en cuenta
no lo encuentro
vale
ChangeFound de esto
ahora sí
PersonNotFound
y ahora sí que no
entraría en un bucle infinito
que antes estaba entrando
y me podría petar
el ordenador y todo
entonces
esto es súper importante
no sólo el hecho
de controlar los errores
porque ya veis
que si intentáis editar
una persona
que no lo encuentra
pues se lo va a comer
con patatas fritas
¿vale?
entonces hay que
hay que controlarlo
y que tengáis en cuenta
que cuando hacéis una mutación
si sois capaces
de recuperar la ID
y los nuevos datos
pues eso
con la ID
será capaz
de sincronizar la caché
mágicamente
y de esta forma
la interfaz
se actualizará
con esos datos nuevos
y es lo más potente
justamente que tiene
que sea
ridículo
no
eso
es o menos
la misma
que sea
lo más potente
entonces
mucho
mejor
y
también
entonces
lo más
útil
que sea
tú
o menos
una
la wind
que sea
ahí
la
que sea
como
o
vaya