El tercero de tres artículos centrados en la construcción Fullstack React y GraphQL con el Apollo GraphQL Client.
- Configuración de un servidor NoSQL Couchbase (Parte 1)
- Creación de una API Express-GraphQL (Parte 2)
- Crear un cliente Apollo GraphQL en React (Parte 3)
- Código fuente final
Creación de la aplicación React con un cliente Apollo GraphQL
En este segmento del tutorial, te ayudaré a conectar las partes relacionadas con el uso de Apollo GraphQL. He incluido la mayor parte de la aplicación React que necesitarás en un repositorio de GitHub. Este código pre-hecho que clonamos en nuestro proyecto será un proyecto React que fue construido con Create Rect App y tiene enrutamiento, navegación, menús, comportamiento responsivo, estado y contexto siendo gestionados así como algunas utilidades y otros componentes para soportar una arquitectura básica de la app. Quería asegurarme de que sólo teníamos que preocuparnos de configurar el cliente Apollo GraphQL, pero quería hacerlo en el contexto de una aplicación en funcionamiento.
Clonar una aplicación React existente
Nuestro frontend React desacoplado será un hermano del frontend servidor couchbase-gql Esta es una idea básica de cómo será nuestra estructura de directorios:
|
1 2 3 4 5 |
rabia-con-couchbase │ └───couchbase-gql-servidor │ └───reaccionar-apollo-cliente |
Vamos a clonar el punto de partida de nuestro proyecto React ejecutando el siguiente comando git desde la raíz (rage-with-couchbase ) en nuestro terminal:
|
1 |
git clonar https://github.com/httpJunkie/reaccionar-apollo-cliente.git && cd reaccionar-apollo-cliente && rm -rf .git |
En el comando anterior, hemos eliminado el .git ya que no queremos tomar el historial git existente del proyecto que clonamos en nuestro proyecto. Tendrás que inicializar git por tu cuenta y hacer commits periódicamente si quieres. Es recomendable para que no pierdas tu trabajo.
Ahora tenemos una aplicación React funcionando añadida a nuestro proyecto con enrutamiento básico. Hay algunos componentes y utilidades que existen en el proyecto React pero que aún no están conectados. Antes de llegar a ellos, vamos a ejecutar la aplicación React por sí sola sólo para asegurarnos de que todo funciona sin errores:
|
1 |
npm instale && npm iniciar |
Abra la consola (⌘ Cmd + ⌥ Opción + I en Mac) (Ctrl + ↑ Mayús + J en PC)
Asegúrese de que al hacer clic de ida y vuelta de Inicio a Aerolíneas no se genera ningún error y que no hay errores o advertencias importantes. Lo que vemos en esta vista previa es la ruta de Aerolíneas, es la ruta a la que añadiremos nuestra función maestro-detalle. Es como si alguien más ya se hubiera encargado de todo el estilo y el diseño básico, nuestro trabajo será conectar la función airline-list.jsx y detalles-de-la-línea-aérea.jsx en lugar del texto actual en cada lado de la página. Por suerte, nuestro equipo de diseño se ha asegurado de que todo el trabajo de maquetación y CSS esté completo.
Antes de hacer cambios en la aplicación React, vamos a entender algunos de los archivos que tenemos en nuestro proyecto que aún no están en juego con nuestra ruta de la aerolínea.
Nuestros activos
Hay 6 archivos con los que queremos familiarizarnos y que están a la espera de que los utilicemos.
- hoc/withApolloProvider.js
- partial/airline-list.jsx
- partial/detalles-de-la-línea-aérea.jsx
- utility/pagination.jsx
- utilidad/paginación.scss
- routes/airline-gql.js
Una convención que estamos utilizando con respecto a la estructura de directorios es que los componentes en el directorio "rutas"son componentes de React que se resuelven para formar una ruta específica y los archivos dentro del directorio "parcial" son componentes que no son una vista cargada por una ruta, sino una vista parcial o un componente que potencialmente podría ser reutilizado en nuestra aplicación. Esta es una convención que yo uso, no algo que React nos obligue a hacer.
withApolloProvider - Estoy usando un componente de orden superior para facilitar la lectura. Sólo tienes que entender que esto es similar a la importación de la ApolloProvider en un componente padre. Esto puede no ser la mejor práctica, pero me gusta que mantiene mi código ordenado.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
importar Reaccione de reaccionar importar { ApolloProvider, Caché en memoria, ApolloClient } de @apollo/client; const withApolloProvider = (WrappedComponent, graphqlEndpoint) => { const apolloClient = nuevo ApolloClient({ uri: graphqlEndpoint, caché: nuevo Caché en memoria() }) devolver (atrezzo) => ( <ApolloProvider cliente={apolloClient}> <WrappedComponent {...atrezzo} wrappedBy={"withApolloProvider"} /> </ApolloProvider> ) } exportar por defecto withApolloProvider |
Tenemos airline-list.jsx y un detalles-de-la-línea-aérea.jsxestos dos componentes se cargarán uno al lado del otro en nuestro aerolíneas.jsx componente. La lista mostrará simplemente cada compañía aérea y utiliza paginación.jsx para asegurarnos de no tener una larga lista recorriendo la parte izquierda de la página.
Por último, tenemos el airline-gql.js que es simplemente nuestro Consulta GraphQL para todas las líneas aéreas del Reino Unido. Me gusta separar mis consultas en otro archivo para fines de organización, no es necesario, pero limpia el aerolíneas.jsx archivo.
Cómo funciona nuestra página principal
En nuestro proyecto, tenemos una relación de componentes maestro-detalle (airline-list.jsx && detalles-de-la-línea-aérea.jsx), en el /líneas aéreas ruta. Esta ruta resuelve a un componente de vista llamado: aerolíneas.jsxque utiliza las capacidades de React Router para hacer coincidir no sólo la ruta sino también un parámetro URI adicional (airlineId) que podemos añadir al final de la ruta para ser específicos. Cuando no se especifica airlineId El parámetro URI está presente en la URL:
http://localhost:3000/airlines
Sólo mostrará una lista de compañías aéreas en la parte izquierda. Además, aparecerá un enlace en la parte derecha de la página con el siguiente texto: "Seleccione una compañía aérea".
Al seleccionar una aerolínea del menú se cargarán los detalles en la parte derecha de la página. Una vez hecho clic, actualizaremos la URL con el id adecuado utilizando un componente proporcionado por React Router:
http://localhost:3000/airlines/1355
Aquí haremos coincidir el ID 1355 con la aerolínea correcta ya en memoria en los datos de nuestra aplicación React y mostrar su información apropiada de la aerolínea "British Airways".
Añadir dependencias para nuestro cliente Apollo GraphQL
Necesitamos tres paquetes: @apollo/react-hooks, apollo-boosty graphqlen el proyecto, así que cd en el react-apollo-client y ejecute el programa npm instalar para los paquetes que necesitamos para GraphQL y Apollo:
|
1 |
npm instale @apollo/cliente graphql |
Si desea familiarizarse con Apollo y GraphQL, la página Documentación GraphQL para consultases un lugar ideal para empezar, véase también: Documentación GraphQL sobre la realización de consultas en Apollo y React.
Creación de la página maestra-detalle
En aerolíneas.jsx es donde haremos la mayor parte de nuestro trabajo. Vamos a empezar por añadir algunas importaciones:
|
1 2 |
importar { useQuery } de @apollo/client importar { airlineGql } de './airline-gql' |
Debajo del import { airlineGql } tenemos que importar withApolloProviderun componente de orden superior.
|
1 |
importar withApolloProvider de '../hoc/conProveedorApollo' |
Esto envuelve nuestro componente con un Apollo Provider. He utilizado este método en lugar de envolver toda nuestra aplicación con un ApollloProvider. Un intento de hacer el código que estoy compartiendo un poco menos complejo. Vamos a actualizar el aerolíneas.jsx exportación del archivo.
La línea que dice:
exportar Aerolíneas por defecto
debería cambiarse por:
|
1 2 |
const WrappedComponent = withApolloProvider(Líneas aéreas, http://localhost:4000/graphql) exportar por defecto WrappedComponent |
Nuestro primer argumento para el HOC es un componente React Líneas aéreas (este componente). Por lo tanto, cuando nuestra aplicación se renderiza, el componente <Airlines /> se envolverá con nuestro ApolloProvider. Un proveedor en React es una función de la API Context. Context proporciona datos a través del árbol de componentes en nuestra aplicación React sin tener que pasar datos hacia abajo a través de props manualmente. En nuestro caso, el <Airlines /> se envolverá con nuestro proveedor, lo que le dará acceso a los datos proporcionados por el código del cliente Apollo definido en el componente withApolloProvider componente de orden superior.
Nuestras importaciones finales son los dos componentes que ya he construido para usted (airline-list.jsx y detalles-de-la-línea-aérea.jsx):
|
1 2 |
importar AirlineList de '../parcial/lista de líneas aéreas' importar Detalles de la línea aérea de '../parcial/detalles-de-la-línea-aérea' |
Una vez importados estos dos archivos podemos añadir su sintaxis de componentes a nuestra rejilla flexbox (simple-flexbox que hemos creado y que nos ayuda a dividir fácilmente nuestra página por un porcentaje:
|
1 2 3 4 5 6 7 8 |
<Fila horizontal="espaciado"> <Columna flexGrow={1} estilo={{ minWidth: 280px, anchura: '65%' }}> <AirlineList líneas aéreas={líneas aéreas} /> </Columna> <Columna flexGrow={1} estilo={{ anchura: '45%' }}> <Detalles de la línea aérea aerolínea={aerolínea} /> </Columna> </Fila> |
Con todo esto en su sitio, sólo tenemos que ocuparnos de nuestros datos. useQuery devuelve un objeto del cliente Apollo GraphQL con cargando, errory datos que podemos utilizar. También tenemos que coincidir en la ruta de nuestra ruta (de la URL). Acceder a eso es fácil con React Router: (match.params).
Traigamos React Router's match mediante la desestructuración de los Líneas aéreas Componente::
|
1 |
const Líneas aéreas = ({ match }) => { |
A continuación, añadiremos lo siguiente al nivel superior de nuestro Líneas aéreas Componente:
|
1 2 3 4 5 6 7 8 |
const airlineId = Número(match.parámetros.id) const { cargando, error, datos } = useQuery(airlineGql) si (cargando) devolver <p>Cargando...</p> if (error) return <p>Error :( <span style="{{color:" 'red'}}>{error.message}</s>pan> )</p> const líneas aéreas = datos.compañías aéreasUK const aerolínea = match.parámetros.id ? líneas aéreas.encontrar(a => a.id === airlineId) : null |
¿Qué acabamos de hacer?
- Establecer
airlineIdsi elmatch.params.iddevuelve un número y noindefinido(¿tenemos un ID en nuestra ruta?/líneas aéreas/1355o no/líneas aéreas/?). - Utilizando la cadena de consulta GraphQL exportada en nuestro
airlineGqlarchivo. Recuerda que devuelve cosas, así que las estamos desestructurando aquí también. - Devuelve "cargando" hasta que los datos hayan terminado de cargarse
- Devuelve "Error" en el caso de que nuestro servidor GraphQL no esté funcionando o tenga un error, etc...
- Captura los datos de todas las aerolíneas devueltas por nuestra consulta en una variable local llamada
líneas aéreas - Si
match.params.idcontiene un número significa que nuestra ruta contiene un ID, en este caso capturamos los datos para esa aerolínea específica en una variable local llamadaaerolíneade lo contrario almacenamos un valor nulo en esa variable.
En match funcionará debido a la forma en que configuramos nuestra ruta en el App.js página:
|
1 2 3 |
<Ruta exacto ruta={["/líneas aéreas/:id", "/líneas aéreas/"]} render={(atrezzo) => <Líneas aéreas {...atrezzo} />} /> |
Esta ruta en efecto dice: Busca una ruta con el nombre /líneas aéreas/ y todo lo que venga después estará disponible utilizando el match.params.id sintaxis.
Si ejecutamos nuestro proyecto ahora mismo y nuestro GraphQL Server no se está ejecutando, obtendremos un error.
"Error :( Error de red: No se ha podido recuperar )"
Así que tenemos que iniciar ese servidor antes de ejecutar nuestra aplicación React para probar nuestra página maestra-detalle.
Ejecutar nuestra aplicación Full Stack
Para ejecutar nuestro proyecto fullstack React y GraphQL, primero tendremos que añadir un paquete más:
|
1 |
npm instale cors |
Nuestra aplicación está alojada en un dominio (localhost:3000). Hace peticiones a una API en otro dominio (localhost:4000). Sin CORS, la política del mismo origen del navegador bloqueará la solicitud.
CORS permite a nuestra API decirle al navegador que está bien que nuestra aplicación web le haga peticiones. Lo hace mediante el envío de cabeceras HTTP. Necesitamos usar CORS en nuestro servidor Express-GraphQL. Sólo tienes que añadir el siguiente código para reemplazar las siete primeras líneas existentes.
|
1 2 3 4 5 6 7 8 9 |
const express = requiere(exprés) const cors = requiere(cors) const graphqlHTTP = requiere(express-graphql) const { construirEsquema } = requiere(graphql) const couchbase = requiere(couchbase) const aplicación = express() aplicación.utilice(cors()) |
Para familiarizarse con CORS de principio a fin, consulte un artículo titulado: "Cómo habilitar CORS para Express-GraphQL y Apollo Server”
En este punto, sólo tenemos que asegurarnos de que nuestra instancia de Couchbase Server está en funcionamiento.
Desde el directorio del servidor ejecute el comando node para iniciar el servidor Express-GraphQL:
|
1 |
nodo servidor |
A continuación, desde el directorio del cliente vamos a ejecutar el comando para iniciar nuestro cliente React:
|
1 |
npm iniciar |
La aplicación React se conecta a la API Express-GraphQL, que a su vez consulta la base de datos Couchbase para recuperar los datos de la Aerolínea, y ahora deberíamos tener una app funcionando si la visitamos: localhost:3000
Uso de Postinstall y Concurrently
Ahora que todo está funcionando, vamos a actualizar el proyecto para ejecutar ambos proyectos con un comando npm.
Necesitamos inicializar un proyecto npm en nuestro directorio raíz. Tanto el servidor como el cliente tienen sus propios directorios de proyecto. Le damos al directorio raíz su propio paquete.json con una sola dependencia.
Cambia de directorio a la raíz y ejecuta:
|
1 |
npm init -y && npm instale simultáneamente --guardar-dev |
Esto inicializará npm y aceptará todos los valores predeterminados (de lo contrario, elimine el archivo -y ) e instalar el paquete que necesitamos para ejecutar simultáneamente ambos proyectos con un solo comando.
Vamos a crear dos scripts denominados cliente y servidor para ejecutar cada proyecto individualmente y luego un iniciar para ejecutar el cliente y el servidor simultáneamente.
También utilizaremos postinstalación para ejecutar cada proyecto npm instalar de forma independiente cuando el npm instalar está completo. postinstalación forma parte de scripts npm por defecto. Todos estos cambios que realizamos a continuación permitirán que alguien clone su repositorio, ejecute npm install && npm start que iniciará las tres instalaciones y, a continuación, ejecutará simultáneamente cada proyecto.
Sustituya el paquete.json que se acaba de añadir con los siguientes scripts:
|
1 2 3 4 5 6 |
"scripts": { "cliente": "cd react-apollo-client && npm start", "servidor": "cd couchbase-gql-server && node server", "inicio": "concurrently --kill-others \"npm run server\" \"npm run client"", "postinstalación": "(cd couchbase-gql-server && npm install); (cd react-apollo-client && npm install);" }, |
Hemos inicializado npm en la raíz de nuestro proyecto, configurado dos scripts para cliente y servidor que podemos ejecutar simultáneamente con npm iniciar. Además, cuando alguien clona nuestro repositorio, ahora puede ejecutar: npm install && npm start e instalará todos los paquetes de los tres proyectos y después los pondrá en marcha, siempre y cuando tengan Couchbase Server funcionando, todo funcionará.
Eliminar usuario y contraseña del archivo del servidor
Un toque final es mover el nombre de usuario y la contraseña de nuestras credenciales de conexión a Couchbase a una carpeta .env . Esto asegurará que no enviemos credenciales sensibles a GitHub para que el mundo las vea.
Cambie los directorios a couchbase-gql-server/ e instalar dotenv:
|
1 |
npm instale dotenv --guardar-dev |
A continuación, importe dotenv y utilizar la desestructuración de objetos para acceder a las variables que hemos configurado en nuestro .env file:
|
1 2 |
requiere(dotenv).config() const { cbUser, cbPass } = proceso.env |
Actualiza el código donde utilizamos el nombre de usuario y la contraseña:
|
1 2 3 |
const grupo = nuevo couchbase.Grupo(couchbase://localhost, { nombre de usuario: cbUser, contraseña: cbPass }) |
Crear un archivo en nuestro servidor couchbase-gql directorio denominado .env con nuestras credenciales de Couchbase Server:
|
1 2 |
cbUser=Administrador cbPass=contraseña |
También tenemos que actualizar los directorios del servidor .gitignore archivo. Hay un bloque de ignorados etiquetado #miscmodifiquemos ese bloque de ignorados y añadamos .env a él. Recuerde que este archivo no se sube a git como parte del control de nuestro curso.
|
1 2 3 4 5 6 7 |
# misc Almacén DS .env .env.local .env.desarrollo.local .env.test.local .env.producción.local |
Vamos a ejecutar nuestro proyecto desde la raíz utilizando npm iniciar para asegurarse de que todo sigue funcionando.
Resumen del proyecto
Hemos montado un proyecto fullstack React y GraphQL. Utilizando SDK de Couchbase Node y Apollo GraphQL client & server, aprovechamos nuestro conocimiento de JavaScript para construir una aplicación fullstack. Espero que este tutorial te ayude a dominar el JavaScript fullstack.
Estoy disponible en Twitter @httpJunkieno dudes en ponerte en contacto conmigo, ¡mi DM está siempre abierto! Echa un vistazo a los siguientes enlaces para obtener más información sobre la construcción con Apollo y React.
El código final de este proyecto se puede encontrar en GitHub en:
github.com/httpJunkie/rage-with-couchbase-final

