Comprender GraphQl del lado del cliente con Apollo-Client en aplicaciones React
Publicado: 2022-03-10Según State of JavaScript 2019, al 38,7 % de los desarrolladores les gustaría usar GraphQL, mientras que al 50,8 % de los desarrolladores les gustaría aprender GraphQL.
Al ser un lenguaje de consulta, GraphQL simplifica el flujo de trabajo de creación de una aplicación cliente. Elimina la complejidad de administrar puntos finales de API en aplicaciones del lado del cliente porque expone un único punto final HTTP para obtener los datos necesarios. Por lo tanto, elimina la obtención excesiva y la obtención insuficiente de datos, como en el caso de REST.
Pero GraphQL es solo un lenguaje de consulta. Para usarlo fácilmente, necesitamos una plataforma que haga el trabajo pesado por nosotros. Una de esas plataformas es Apolo.
La plataforma Apollo es una implementación de GraphQL que transfiere datos entre la nube (el servidor) a la interfaz de usuario de su aplicación. Cuando usa Apollo Client, toda la lógica para recuperar datos, rastrear, cargar y actualizar la interfaz de usuario está encapsulada por el useQuery
(como en el caso de React). Por lo tanto, la obtención de datos es declarativa. También tiene almacenamiento en caché de configuración cero. Con solo configurar Apollo Client en su aplicación, obtiene un caché inteligente listo para usar, sin necesidad de configuración adicional.
Apollo Client también es interoperable con otros marcos, como Angular, Vue.js y React.
Nota : este tutorial beneficiará a aquellos que han trabajado con RESTful u otras formas de API en el pasado en el lado del cliente y quieren ver si vale la pena probar GraphQL. Esto significa que debería haber trabajado con una API antes; solo entonces podrá comprender cuán beneficioso podría ser GraphQL para usted. Si bien cubriremos algunos conceptos básicos de GraphQL y Apollo Client, un buen conocimiento de JavaScript y React Hooks será útil.
Conceptos básicos de GraphQL
Este artículo no es una introducción completa a GraphQL, pero definiremos algunas convenciones antes de continuar.
¿Qué es GraphQL?
GraphQL es una especificación que describe un lenguaje de consulta declarativo que sus clientes pueden usar para solicitar a una API los datos exactos que desean. Esto se logra mediante la creación de un esquema de tipo sólido para su API, con la máxima flexibilidad. También garantiza que la API resuelva los datos y que las consultas de los clientes se validen con un esquema. Esta definición significa que GraphQL contiene algunas especificaciones que lo convierten en un lenguaje de consulta declarativo, con una API tipificada estáticamente (construida alrededor de Typescript) y que hace posible que el cliente aproveche esos sistemas de tipos para solicitar a la API los datos exactos que desea. .
Entonces, si creamos algunos tipos con algunos campos, entonces, desde el lado del cliente, podríamos decir: "Danos estos datos con estos campos exactos". Luego, la API responderá con esa forma exacta, como si estuviéramos usando un sistema de tipos en un lenguaje fuertemente tipado. Puede obtener más información en mi artículo de TypeScript.
Veamos algunas convenciones de GraphQl que nos ayudarán a medida que continuamos.
Los basicos
- Operaciones
En GraphQL, cada acción realizada se denomina operación. Hay algunas operaciones, a saber:- Consulta
Esta operación tiene que ver con la obtención de datos del servidor. También podría llamarlo una búsqueda de solo lectura. - Mutación
Esta operación implica crear, actualizar y eliminar datos de un servidor. Popularmente se denomina operación CUD (crear, actualizar y eliminar). - Suscripciones
Esta operación en GraphQL consiste en enviar datos desde un servidor a sus clientes cuando ocurren eventos específicos. Suelen implementarse con WebSockets.
- Consulta
En este artículo, nos ocuparemos únicamente de las operaciones de consulta y mutación.
- Nombres de operaciones
Hay nombres únicos para las operaciones de consulta y mutación del lado del cliente. - Variables y argumentos
Las operaciones pueden definir argumentos, muy parecido a una función en la mayoría de los lenguajes de programación. Esas variables luego se pueden pasar a llamadas de consulta o mutación dentro de la operación como argumentos. Se espera que las variables se proporcionen en tiempo de ejecución durante la ejecución de una operación de su cliente. - alias
Esta es una convención en GraphQL del lado del cliente que implica cambiar el nombre de los campos detallados o imprecisos con nombres de campo simples y legibles para la interfaz de usuario. El alias es necesario en casos de uso en los que no desea tener nombres de campo en conflicto.
¿Qué es GraphQL del lado del cliente?
Cuando un ingeniero front-end crea componentes de interfaz de usuario utilizando cualquier marco, como Vue.js o (en nuestro caso) React, esos componentes se modelan y diseñan a partir de un determinado patrón en el cliente para adaptarse a los datos que se obtendrán del servidor.
Uno de los problemas más comunes con las API RESTful es la obtención excesiva y la obtención insuficiente. Esto sucede porque la única forma en que un cliente puede descargar datos es accediendo a puntos finales que devuelven estructuras de datos fijas . La sobreexplotación en este contexto significa que un cliente descarga más información de la que requiere la aplicación.
En GraphQL, por otro lado, simplemente enviaría una sola consulta al servidor de GraphQL que incluye los datos requeridos. Luego, el servidor respondería con un objeto JSON de los datos exactos que ha solicitado; por lo tanto, no se extrae demasiado. Sebastian Eschweiler explica las diferencias entre las API RESTful y GraphQL.
GraphQL del lado del cliente es una infraestructura del lado del cliente que interactúa con los datos de un servidor GraphQL para realizar las siguientes funciones:
- Gestiona los datos mediante el envío de consultas y la mutación de datos sin que tengas que crear solicitudes HTTP por tu cuenta. Puede dedicar menos tiempo a la instalación de datos y más tiempo a la creación de la aplicación real.
- Gestiona la complejidad de un caché por ti. Por lo tanto, puede almacenar y recuperar los datos obtenidos del servidor, sin la interferencia de terceros, y evitar fácilmente la recuperación de recursos duplicados. Por lo tanto, identifica cuándo dos recursos son iguales, lo cual es excelente para una aplicación compleja.
- Mantiene su interfaz de usuario coherente con la interfaz de usuario optimista, una convención que simula los resultados de una mutación (es decir, los datos creados) y actualiza la interfaz de usuario incluso antes de recibir una respuesta del servidor. Una vez que se recibe la respuesta del servidor, el resultado optimista se descarta y se reemplaza con el resultado real.
Para obtener más información sobre GraphQL del lado del cliente, dedique una hora con el cocreador de GraphQL y otras personas interesantes en GraphQL Radio.
¿Qué es el cliente Apollo?
Apollo Client es un cliente GraphQL interoperable, ultraflexible e impulsado por la comunidad para JavaScript y plataformas nativas. Sus características impresionantes incluyen una sólida herramienta de administración de estado (Apollo Link), un sistema de almacenamiento en caché de configuración cero, un enfoque declarativo para obtener datos, paginación fácil de implementar y la interfaz de usuario optimista para su aplicación del lado del cliente.
Apollo Client almacena no solo el estado de los datos obtenidos del servidor, sino también el estado que ha creado localmente en su cliente; por lo tanto, administra el estado tanto de los datos API como de los datos locales.
También es importante tener en cuenta que puede usar Apollo Client junto con otras herramientas de administración de estado, como Redux, sin conflicto. Además, es posible migrar su gestión de estado de, por ejemplo, Redux a Apollo Client (que está más allá del alcance de este artículo). En última instancia, el objetivo principal de Apollo Client es permitir que los ingenieros consulten datos en una API sin problemas.
Características del cliente Apollo
Apollo Client se ha ganado a tantos ingenieros y empresas debido a sus características extremadamente útiles que hacen que la creación de aplicaciones modernas y robustas sea muy sencilla. Las siguientes características vienen integradas:
- almacenamiento en caché
Apollo Client admite el almacenamiento en caché sobre la marcha. - IU optimista
Apollo Client tiene un excelente soporte para la interfaz de usuario optimista. Implica mostrar temporalmente el estado final de una operación (mutación) mientras la operación está en curso. Una vez completada la operación, los datos reales reemplazan a los datos optimistas. - Paginación
Apollo Client tiene una funcionalidad integrada que facilita la implementación de la paginación en su aplicación. Se ocupa de la mayoría de los dolores de cabeza técnicos de obtener una lista de datos, ya sea en parches o de una sola vez, utilizando la funciónfetchMore
, que viene con eluseQuery
.
En este artículo, veremos una selección de estas características.
Basta de teoría. Abróchese el cinturón de seguridad y tome una taza de café para acompañar sus panqueques, mientras nos ensuciamos las manos.
Construyendo nuestra aplicación web
Este proyecto está inspirado en Scott Moss.
Construiremos una aplicación web simple para una tienda de mascotas, cuyas características incluyen:
- ir a buscar a nuestras mascotas desde el lado del servidor;
- crear una mascota (lo que implica crear el nombre, el tipo de mascota y la imagen);
- utilizando la interfaz de usuario optimista;
- usando la paginación para segmentar nuestros datos.
Para comenzar, clone el repositorio, asegurándose de que la rama starter
sea la que ha clonado.
Empezando
- Instale la extensión Apollo Client Developer Tools para Chrome.
- Con la interfaz de línea de comandos (CLI), navegue hasta el directorio del repositorio clonado y ejecute el comando para obtener todas las dependencias:
npm install
. - Ejecute el comando
npm run app
para iniciar la aplicación. - Mientras aún está en la carpeta raíz, ejecute el comando
npm run server
. Esto iniciará nuestro servidor back-end para nosotros, que usaremos a medida que avancemos.
La aplicación debería abrirse en un puerto configurado. El mío es https://localhost:1234/
; lo tuyo es probablemente otra cosa.
Si todo funcionó bien, su aplicación debería verse así:
Notarás que no tenemos mascotas para mostrar. Eso es porque aún no hemos creado esa funcionalidad.
Si ha instalado correctamente las herramientas de desarrollo de Apollo Client, abra las herramientas de desarrollo y haga clic en el icono de la bandeja. Verás "Apolo" y algo como esto:
Al igual que las herramientas de desarrollo de Redux y React, utilizaremos las herramientas de desarrollo de Apollo Client para escribir y probar nuestras consultas y mutaciones. La extensión viene con GraphQL Playground.
Ir a buscar mascotas
Agreguemos la funcionalidad que busca mascotas. Vaya a client/src/client.js
. Estaremos escribiendo Apollo Client, vinculándolo a una API, exportándolo como un cliente predeterminado y escribiendo una nueva consulta.
Copie el siguiente código y péguelo en client.js
:
import { ApolloClient } from 'apollo-client' import { InMemoryCache } from 'apollo-cache-inmemory' import { HttpLink } from 'apollo-link-http' const link = new HttpLink({ uri: 'https://localhost:4000/' }) const cache = new InMemoryCache() const client = new ApolloClient({ link, cache }) export default client
Aquí hay una explicación de lo que está sucediendo arriba:
-
ApolloClient
Esta será la función que envuelve nuestra aplicación y, por lo tanto, interactúa con HTTP, almacena en caché los datos y actualiza la interfaz de usuario. -
InMemoryCache
Este es el almacén de datos normalizados en Apollo Client que ayuda a manipular el caché en nuestra aplicación. -
HttpLink
Esta es una interfaz de red estándar para modificar el flujo de control de las solicitudes de GraphQL y obtener resultados de GraphQL. Actúa como middleware, obteniendo resultados del servidor GraphQL cada vez que se activa el enlace. Además, es un buen sustituto de otras opciones, comoAxios
ywindow.fetch
. - Declaramos una variable de enlace que se asigna a una instancia de
HttpLink
. Toma una propiedaduri
y un valor para nuestro servidor, que eshttps://localhost:4000/
. - Lo siguiente es una variable de caché que contiene la nueva instancia de
InMemoryCache
. - La variable de cliente también toma una instancia de
ApolloClient
y envuelve ellink
y elcache
. - Por último, exportamos el
client
para poder usarlo en toda la aplicación.
Antes de que podamos ver esto en acción, debemos asegurarnos de que toda nuestra aplicación esté expuesta a Apollo y que nuestra aplicación pueda recibir datos obtenidos del servidor y que pueda mutar esos datos.
Para lograr esto, vayamos a client/src/index.js
:
import React from 'react' import ReactDOM from 'react-dom' import { BrowserRouter } from 'react-router-dom' import { ApolloProvider } from '@apollo/react-hooks' import App from './components/App' import client from './client' import './index.css' const Root = () => ( <BrowserRouter>
<ApolloProvider client={client}> <App /> </ApolloProvider>
</BrowserRouter> ); ReactDOM.render(<Root />, document.getElementById('app')) if (module.hot) { module.hot.accept() }
Como notará en el código resaltado, envolvimos el componente de la App
en ApolloProvider
y pasamos el cliente como accesorio al client
. ApolloProvider
es similar a Context.Provider
de React. Envuelve su aplicación React y coloca al cliente en contexto, lo que le permite acceder a él desde cualquier parte de su árbol de componentes.
Para obtener nuestras mascotas del servidor, debemos escribir consultas que soliciten los campos exactos que queremos. Dirígete a client/src/pages/Pets.js
y copia y pega el siguiente código en él:
import React, {useState} from 'react' import gql from 'graphql-tag' import { useQuery, useMutation } from '@apollo/react-hooks' import PetsList from '../components/PetsList' import NewPetModal from '../components/NewPetModal' import Loader from '../components/Loader'
const GET_PETS = gql` query getPets { pets { id name type img } } `;
export default function Pets () { const [modal, setModal] = useState(false)
const { loading, error, data } = useQuery(GET_PETS); if (loading) return <Loader />; if (error) return <p>An error occured!</p>;
const onSubmit = input => { setModal(false) } if (modal) { return <NewPetModal onSubmit={onSubmit} onCancel={() => setModal(false)} /> } return ( <div className="page pets-page"> <section> <div className="row betwee-xs middle-xs"> <div className="col-xs-10"> <h1>Pets</h1> </div> <div className="col-xs-2"> <button onClick={() => setModal(true)}>new pet</button> </div> </div> </section> <section>
<PetsList pets={data.pets}/>
</section> </div> ) }
Con unos pocos bits de código, podemos obtener las mascotas del servidor.
¿Qué es gql?
Es importante tener en cuenta que las operaciones en GraphQL son generalmente objetos JSON escritos con graphql-tag
y con acentos graves.
Las etiquetas gql
son etiquetas literales de plantillas de JavaScript que analizan las cadenas de consulta de GraphQL en GraphQL AST (árbol de sintaxis abstracta).
- operaciones de consulta
Para recuperar nuestras mascotas del servidor, debemos realizar una operación de consulta.- Debido a que estamos realizando una operación de
query
, necesitamos especificar eltype
de operación antes de nombrarla. - El nombre de nuestra consulta es
GET_PETS
. Es una convención de nomenclatura de GraphQL usar camelCase para nombres de campo. - El nombre de nuestros campos es
pets
. Por lo tanto, especificamos los campos exactos que necesitamos del servidor(id, name, type, img)
. -
useQuery
es un enlace de React que es la base para ejecutar consultas en una aplicación Apollo. Para realizar una operación de consulta en nuestro componente React, llamamos aluseQuery
, que inicialmente se importó desde@apollo/react-hooks
. Luego, le pasamos una cadena de consulta de GraphQL, que esGET_PETS
en nuestro caso.
- Debido a que estamos realizando una operación de
- Cuando nuestro componente se procesa,
useQuery
devuelve una respuesta de objeto de Apollo Client que contiene propiedades de carga, error y datos. Por lo tanto, se desestructuran para que podamos usarlos para representar la interfaz de usuario. -
useQuery
es increíble. No tenemos que incluirasync-await
. Ya está atendido en segundo plano. Bastante genial, ¿no?-
loading
Esta propiedad nos ayuda a manejar el estado de carga de la aplicación. En nuestro caso, devolvemos un componenteLoader
mientras se carga nuestra aplicación. De forma predeterminada, la carga esfalse
. -
error
Por si acaso, usamos esta propiedad para manejar cualquier error que pueda ocurrir. -
data
Esto contiene nuestros datos reales del servidor. - Por último, en nuestro componente
PetsList
, pasamos los accesorios depets
, condata.pets
como valor de objeto.
-
En este punto, hemos consultado con éxito nuestro servidor.
Para iniciar nuestra aplicación, ejecutemos el siguiente comando:
- Inicie la aplicación cliente. Ejecute el comando
npm run app
en su CLI. - Inicie el servidor. Ejecute el comando
npm run server
en otra CLI.
Si todo salió bien, deberías ver esto:
Datos mutantes
Mutar datos o crear datos en Apollo Client es casi lo mismo que consultar datos, con cambios muy leves.
Todavía en client/src/pages/Pets.js
, copiemos y peguemos el código resaltado:
.... const GET_PETS = gql` query getPets { pets { id name type img } } `;
const NEW_PETS = gql` mutation CreateAPet($newPet: NewPetInput!) { addPet(input: $newPet) { id name type img } } `;
const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS);
const [createPet, newPet] = useMutation(NEW_PETS);
const onSubmit = input => { setModal(false)
createPet({ variables: { newPet: input } }); } if (loading || newPet.loading) return <Loader />; if (error || newPet.error) return <p>An error occured</p>;
if (modal) { return <NewPetModal onSubmit={onSubmit} onCancel={() => setModal(false)} /> } return ( <div className="page pets-page"> <section> <div className="row betwee-xs middle-xs"> <div className="col-xs-10"> <h1>Pets</h1> </div> <div className="col-xs-2"> <button onClick={() => setModal(true)}>new pet</button> </div> </div> </section> <section> <PetsList pets={data.pets}/> </section> </div> ) } export default Pets
Para crear una mutación, seguiríamos los siguientes pasos.
1. mutation
Para crear, actualizar o eliminar, debemos realizar la operación de mutation
. La operación de mutation
tiene un nombre CreateAPet
, con un argumento. Este argumento tiene una variable $newPet
, con un tipo de NewPetInput
. El !
significa que se requiere la operación; por lo tanto, GraphQL no ejecutará la operación a menos que pasemos una variable newPet
cuyo tipo sea NewPetInput
.
2. addPet
La función addPet
, que está dentro de la operación de mutation
, toma un argumento de input
y se establece en nuestra variable $newPet
. Los conjuntos de campos especificados en nuestra función addPet
deben ser iguales a los conjuntos de campos de nuestra consulta. Los conjuntos de campos en nuestra operación son:
-
id
-
name
-
type
-
img
3. useMutation
El useMutation
React es la API principal para ejecutar mutaciones en una aplicación Apollo. Cuando necesitamos mutar datos, llamamos a useMutation
en un componente React y le pasamos una cadena GraphQL (en nuestro caso, NEW_PETS
).
Cuando nuestro componente representa useMutation
, devuelve una tupla (es decir, un conjunto ordenado de datos que constituye un registro) en una matriz que incluye:
- una función de
mutate
que podemos llamar en cualquier momento para ejecutar la mutación; - un objeto con campos que representan el estado actual de la ejecución de la mutación.
Al gancho useMutation
se le pasa una cadena de mutación de GraphQL (que es NEW_PETS
en nuestro caso). Desestructuramos la tupla, que es la función ( createPet
) que mutará los datos y el campo del objeto ( newPets
).
4. createPet
En nuestra función onSubmit
, poco después del estado setModal
, definimos nuestro createPet
. Esta función toma una variable
con una propiedad de objeto de un valor establecido en { newPet: input }
. La input
representa los diversos campos de entrada en nuestro formulario (como nombre, tipo, etc.).
Con eso hecho, el resultado debería verse así:
Si observa el GIF de cerca, notará que nuestra mascota creada no aparece instantáneamente, solo cuando se actualiza la página. Sin embargo, se ha actualizado en el servidor.
La gran pregunta es, ¿por qué nuestra mascota no se actualiza al instante? Averigüémoslo en la siguiente sección.
Almacenamiento en caché en el cliente Apollo
La razón por la que nuestra aplicación no se actualiza automáticamente es que nuestros datos recién creados no coinciden con los datos de caché en Apollo Client. Por lo tanto, existe un conflicto en cuanto a qué es exactamente lo que debe actualizarse desde el caché.
En pocas palabras, si realizamos una mutación que actualiza o elimina varias entradas (un nodo), entonces somos responsables de actualizar cualquier consulta que haga referencia a ese nodo, de modo que modifique nuestros datos almacenados en caché para que coincidan con las modificaciones que hace una mutación en nuestro respaldo. datos finales .
Mantener el caché sincronizado
Hay algunas formas de mantener nuestro caché sincronizado cada vez que realizamos una operación de mutación.
La primera es recuperando las consultas coincidentes después de una mutación, utilizando la propiedad del objeto refetchQueries
(la forma más sencilla).
Nota: si tuviéramos que usar este método, tomaría una propiedad de objeto en nuestra función createPet
llamada refetchQueries
, y contendría una matriz de objetos con un valor de la consulta: refetchQueries: [{ query: GET_PETS }]
.
Debido a que nuestro enfoque en esta sección no es solo actualizar nuestras mascotas creadas en la interfaz de usuario, sino manipular el caché, no usaremos este método.
El segundo enfoque es utilizar la función de update
. En Apollo Client, hay una función auxiliar de update
que ayuda a modificar los datos de la memoria caché, para que se sincronice con las modificaciones que realiza una mutación en nuestros datos de back-end. Usando esta función, podemos leer y escribir en el caché.
Actualización del caché
Copie el siguiente código resaltado y péguelo en client/src/pages/Pets.js
:
...... const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS);
const [createPet, newPet] = useMutation(NEW_PETS, { update(cache, { data: { addPet } }) { const data = cache.readQuery({ query: GET_PETS }); cache.writeQuery({ query: GET_PETS, data: { pets: [addPet, ...data.pets] }, }); }, } );
.....
La función de update
recibe dos argumentos:
- El primer argumento es el caché de Apollo Client.
- El segundo es la respuesta de mutación exacta del servidor. Desestructuramos la propiedad
data
y la establecemos en nuestra mutación (addPet
).
A continuación, para actualizar la función, debemos verificar qué consulta debe actualizarse (en nuestro caso, la consulta GET_PETS
) y leer el caché.
En segundo lugar, debemos escribir en la query
que se leyó, para que sepa que estamos a punto de actualizarla. Lo hacemos pasando un objeto que contiene una propiedad de objeto de query
, con el valor establecido en nuestra operación de query
( GET_PETS
), y una propiedad data
cuyo valor es un objeto pet
y que tiene una matriz de la mutación addPet
y una copia de la datos de la mascota.
Si siguió estos pasos cuidadosamente, debería ver que sus mascotas se actualizan automáticamente a medida que las crea. Echemos un vistazo a los cambios:
IU optimista
Mucha gente es fanática de los cargadores y los spinners. No hay nada de malo en usar un cargador; hay casos de uso perfectos donde un cargador es la mejor opción. He escrito sobre cargadores versus spinners y sus mejores casos de uso.
De hecho, los cargadores y los spinners juegan un papel importante en el diseño de UI y UX, pero la llegada de Optimistic UI ha acaparado la atención.
¿Qué es la interfaz de usuario optimista?
La interfaz de usuario optimista es una convención que simula los resultados de una mutación (datos creados) y actualiza la interfaz de usuario antes de recibir una respuesta del servidor. Una vez que se recibe la respuesta del servidor, el resultado optimista se descarta y se reemplaza con el resultado real.
Al final, una interfaz de usuario optimista no es más que una forma de administrar el rendimiento percibido y evitar estados de carga.
Apollo Client tiene una forma muy interesante de integrar la interfaz de usuario optimista. Nos da un enlace simple que nos permite escribir en el caché local después de la mutación. ¡Vamos a ver cómo funciona!
Paso 1
Dirígete a client/src/client.js
y agrega solo el código resaltado.
import { ApolloClient } from 'apollo-client' import { InMemoryCache } from 'apollo-cache-inmemory' import { HttpLink } from 'apollo-link-http'
import { setContext } from 'apollo-link-context' import { ApolloLink } from 'apollo-link' const http = new HttpLink({ uri: "https://localhost:4000/" }); const delay = setContext( request => new Promise((success, fail) => { setTimeout(() => { success() }, 800) }) ) const link = ApolloLink.from([ delay, http ])
const cache = new InMemoryCache() const client = new ApolloClient({ link, cache }) export default client
El primer paso implica lo siguiente:
- Importamos
setContext
desdeapollo-link-context
. La funciónsetContext
toma una función de devolución de llamada y devuelve una promesa cuyosetTimeout
se establece en800ms
para crear un retraso cuando se realiza una operación de mutación. - El método
ApolloLink.from
asegura que la actividad de la red que representa el enlace (nuestra API) deHTTP
se retrase.
Paso 2
El siguiente paso es usar el gancho de IU optimista. Vuelva a client/src/pages/Pets.js
y agregue solo el código resaltado a continuación.
..... const Pets = () => { const [modal, setModal] = useState(false) const { loading, error, data } = useQuery(GET_PETS); const [createPet, newPet] = useMutation(NEW_PETS, { update(cache, { data: { addPet } }) { const data = cache.readQuery({ query: GET_PETS }); cache.writeQuery({ query: GET_PETS, data: { pets: [addPet, ...data.pets] }, }); }, } ); const onSubmit = input => { setModal(false) createPet({ variables: { newPet: input },
optimisticResponse: { __typename: 'Mutation', addPet: { __typename: 'Pet', id: Math.floor(Math.random() * 10000 + ''), name: input.name, type: input.type, img: 'https://via.placeholder.com/200' } }
}); } .....
El objeto optimisticResponse
se usa si queremos que la interfaz de usuario se actualice inmediatamente cuando creamos una mascota, en lugar de esperar la respuesta del servidor.
Los fragmentos de código anteriores incluyen lo siguiente:
- Apollo inyecta
__typename
en la consulta para obtener eltype
de las entidades consultadas. Apollo Client utiliza esos tipos para crear la propiedadid
(que es un símbolo) con fines de almacenamiento en caché enapollo-cache
. Entonces,__typename
es una propiedad válida de la respuesta a la consulta. - La mutación se establece como el
__typename
deoptimisticResponse
. - Tal como se definió anteriormente, el nombre de nuestra mutación es
addPet
y el__typename
esPet
. - Los siguientes son los campos de nuestra mutación que queremos que actualice la respuesta optimista:
-
id
Debido a que no sabemos cuál será la ID del servidor, creamos una usandoMath.floor
. -
name
Este valor se establece eninput.name
. -
type
El valor del tipo esinput.type
. -
img
Ahora, debido a que nuestro servidor genera imágenes para nosotros, usamos un marcador de posición para imitar nuestra imagen del servidor.
-
Este fue de hecho un viaje largo. Si llegaste al final, no dudes en tomarte un descanso de tu silla con tu taza de café.
Echemos un vistazo a nuestro resultado. El repositorio de soporte para este proyecto está en GitHub. Clonar y experimentar con él.
Conclusión
Las increíbles funciones de Apollo Client, como la interfaz de usuario optimista y la paginación, hacen que la creación de aplicaciones del lado del cliente sea una realidad.
Si bien Apollo Client funciona muy bien con otros marcos, como Vue.js y Angular, los desarrolladores de React tienen Apollo Client Hooks, por lo que no pueden evitar disfrutar de la creación de una gran aplicación.
En este artículo, solo hemos arañado la superficie. Dominar Apollo Client exige una práctica constante. Entonces, continúe y clone el repositorio, agregue paginación y juegue con las otras funciones que ofrece.
Comparta sus comentarios y experiencia en la sección de comentarios a continuación. También podemos discutir su progreso en Twitter. ¡Salud!
Referencias
- “GraphQL del lado del cliente en React”, Scott Moss, maestro de interfaz
- “Documentación”, Cliente Apollo
- “La interfaz de usuario optimista con React”, Patryk Andrzejewski
- "Verdaderas mentiras de las interfaces de usuario optimistas", Smashing Magazine