Cómo crear una aplicación de recetas con React, Prisma y GraphQL

Introducción
GraphQL ganó popularidad en términos de desarrollo front-end debido a las diversas ventajas que ofrece sobre las API REST. Sin embargo, configurar su propio servidor GraphQL es propenso a errores y complicado. Debido a esto, se han creado servicios administrados como Prisma para administrar su servidor GraphQL, lo que le permite concentrarse en el desarrollo de su aplicación.
En este tutorial, crearemos una aplicación de recetas completamente funcional utilizando React y Prisma para administrar GraphQL.
Prerrequisitos
- Conocimientos intermedios de Javascript y React
- Fundamentos de GraphQL
- Fundamentos de Docker
Paso 1: Instalación de dependencias
Instale el cliente Prisma CLI globalmente ejecutando el siguiente comando:
- npm install -g prisma
Usaremos create-react-app para iniciar nuestra aplicación React, así que ejecute el siguiente comando para instalarla globalmente:
- npm install -g create-react-app
Para utilizar Prisma de forma local, debe tener Docker instalado en su máquina. Si aún no tiene Docker, puede descargar Docker Community Edition.
Paso 2: Configuración de Prisma
Para utilizar la CLI de Prisma, necesitará tener una cuenta de Prisma. Puede crear una cuenta en el sitio web de Prisma y luego iniciar sesión en la CLI de Prisma ejecutando el siguiente comando:
- prisma login
Ahora que tenemos todas las dependencias necesarias, crea una carpeta para el proyecto y navega hacia la carpeta ejecutando los siguientes comandos:
- mkdir recipe-app-prisma-react
- cd recipe-app-prisma-react
Luego inicialice su servidor Prisma en la carpeta:
- prisma init
Aparecerá un mensaje con algunas opciones sobre el método que desea utilizar para configurar su servidor Prisma. Trabajaremos con el servidor localmente por ahora y luego lo implementaremos más tarde. Elija Create new database
que Prisma cree una base de datos localmente con Docker.
A continuación, se le solicitará que elija una base de datos. Para este tutorial, utilizaremos Postgres, así que elija PostgreSQL
:
A continuación, tenemos que elegir un lenguaje de programación para nuestro cliente prisma generado. Elija Prisma Javascript Client
:
Tendrás los siguientes archivos generados por Prisma en función de las opciones seleccionadas:
Paso 3: Implementación de Prisma
Ahora que tenemos configurado nuestro servidor Prisma, asegúrese de que Docker esté en ejecución. Luego, ejecute el siguiente comando para iniciar el servidor:
- docker-compose up -d
Docker Compose se utiliza para ejecutar varios contenedores como un único servicio. El comando anterior iniciará nuestro servidor Prisma y la base de datos Postgres. Dirígete a 127.0.0.1:4466
en tu navegador para ver el área de juegos de Prisma.
Si desea detener su servidor, ejecute docker-compose stop
.
A continuación, abra su datamodel.prisma
archivo y reemplace el contenido de demostración con lo siguiente:
type Recipe { id: ID! @unique createdAt: DateTime! updatedAt: DateTime! title: String! @unique ingredients: String! directions: String! published: Boolean! @default(value: "false")}
Luego ejecute el siguiente comando para implementar en un servidor de demostración:
- prisma deploy
Recibirá una respuesta que muestra los modelos creados y su punto final Prisma de la siguiente manera:
Para ver el servidor implementado, abra el panel de Prisma https://app.prisma.io/
y navegue hasta Servicios. En el panel, verá lo siguiente:
Para implementar en su servidor local, abra el prisma.yml
archivo y cambie el punto final a http://localhost:4466
, luego ejecuteprisma deploy
Paso 4: configuración de la aplicación React
Ahora que nuestro servidor Prisma está listo, podemos configurar nuestra aplicación React para consumir el punto final Prisma GraphQL.
En la carpeta del proyecto, ejecute el siguiente comando para iniciar nuestra aplicación cliente usando create-react-app
:
- create-react-app client
Para trabajar con GraphQL, necesitamos algunas dependencias. Navegue hasta la carpeta del cliente y ejecute los siguientes comandos para instalarlas:
- cd client
- npm install apollo-boost react-apollo graphql-tag graphql --save
Para la interfaz de usuario, utilizaremos Ant Design:
- npm install antd --save
Estructura de carpetas:
La estructura de carpetas de nuestra aplicación será la siguiente:
src├── components│ ├── App.js│ ├── App.test.js│ ├── RecipeCard│ │ ├── RecipeCard.js│ │ └── index.js│ └── modals│ ├── AddRecipeModal.js│ └── ViewRecipeModal.js├── containers│ └── AllRecipesContainer│ ├── AllRecipesContainer.js│ └── index.js├── graphql│ ├── mutations│ │ ├── AddNewRecipe.js│ │ └── UpdateRecipe.js│ └── queries│ ├── GetAllPublishedRecipes.js│ └── GetSingleRecipe.js├── index.js├── serviceWorker.js└── styles └── index.css
Paso 5: escribir el código
Índice.js
Aquí realizaremos la configuración de Apollo. Este será el archivo de entrada principal para nuestra aplicación:
import React from 'react';import ReactDOM from 'react-dom';import ApolloClient from 'apollo-boost';import { ApolloProvider } from 'react-apollo';import App from './components/App';// Pass your prisma endpoint to uriconst client = new ApolloClient({ uri: 'https://eu1.prisma.sh/XXXXXX'});ReactDOM.render( ApolloProvider client={client} App / /ApolloProvider, document.getElementById('root'));
Obtener todas las recetas publicadas.js
Consulta para obtener todas las recetas:
import { gql } from 'apollo-boost';export default gql`query GetAllPublishedRecipes { recipes(where: { published: true }) { id createdAt title ingredients directions published } }`;
ObtenerRecetaSingle.js
Consulta para obtener una receta por el ID de la receta:
import { gql } from 'apollo-boost';export default gql`query GetSingleRecipe($recipeId: ID!) { recipe(where: { id: $recipeId }) { id createdAt title directions ingredients published } }`;
AgregarNuevaReceta.js
La mutación para crear una nueva receta:
import { gql } from 'apollo-boost';export default gql`mutation AddRecipe( $directions: String! $title: String! $ingredients: String! $published: Boolean ) { createRecipe( data: { directions: $directions title: $title ingredients: $ingredients published: $published } ) { id } }`;
ActualizarReceta.js
La mutación para actualizar una receta:
import { gql } from 'apollo-boost';export default gql`mutation UpdateRecipe( $id: ID! $directions: String! $title: String! $ingredients: String! $published: Boolean ) { updateRecipe( where: { id: $id } data: { directions: $directions title: $title ingredients: $ingredients published: $published } ) { id } }`;
Contenedor de recetas AllRecipes.js
Aquí es donde CRUD
se basa nuestra lógica para las operaciones. El archivo es bastante grande, por lo que hemos incluido solo las partes cruciales. Puedes ver el resto del código en GitHub.
Para poder utilizar nuestras consultas y mutaciones, necesitamos importarlas y luego usar react-apollo's
graphql que nos permite crear una higher-order component
que pueda ejecutar consultas y actualizar de forma reactiva en función de los datos que tenemos en nuestra aplicación.
A continuación se muestra un ejemplo de cómo podemos obtener y mostrar todas las recetas publicadas:
import React, { Component } from 'react';import { graphql } from 'react-apollo';import { Card, Col, Row, Empty, Spin } from 'antd';// queriesimport GetAllPublishedRecipes from '../../graphql/queries/GetAllPublishedRecipes';class AllRecipesContainer extends Component { render() { const { loading, recipes } = this.props.data; return ( div {loading ? ( div className="spin-container" Spin / /div ) : recipes.length 0 ? ( Row gutter={16} {recipes.map(recipe = ( Col span={6} key={recipe.id} RecipeCard title={recipe.title} content={ Fragment Card type="inner" style={{ marginBottom: '15px' }} {`${recipe.ingredients.substring(0, 50)}.....`} /Card Card type="inner" {`${recipe.directions.substring(0, 50)}.....`} /Card /Fragment } handleOnClick={this._handleOnClick} handleOnEdit={this._handleOnEdit} handleOnDelete={this._handleOnDelete} {...recipe} / /Col ))} /Row ) : ( Empty / )} /div ); }}graphql(GetAllPublishedRecipes)(AllRecipesContainer);
La vista resultante se vería así:
Nota: No se incluirá el estilo de los componentes debido al tamaño del archivo. El código está disponible en el repositorio de GitHub.
Dado que necesitamos más de un potenciador en nuestro componente, usaremos compose para incorporar todos los potenciadores necesarios para el componente:
import React, { Component } from 'react';import { graphql, compose, withApollo } from 'react-apollo';// queriesimport GetAllPublishedRecipes from '../../graphql/queries/GetAllPublishedRecipes';import GetSingleRecipe from '../../graphql/queries/GetSingleRecipe';// mutationsimport UpdateRecipe from '../../graphql/mutations/UpdateRecipe';import AddNewRecipe from '../../graphql/mutations/AddNewRecipe';// other importsclass GetAllPublishedRecipes extends Component { // class logic}export default compose( graphql(UpdateRecipe, { name: 'updateRecipeMutation' }), graphql(AddNewRecipe, { name: 'addNewRecipeMutation' }), graphql(GetAllPublishedRecipes))(withApollo(AllRecipesContainer));
También necesitamos el withApollo
potenciador, que proporciona acceso directo a su ApolloClient
instancia. Esto será útil, ya que necesitamos realizar consultas puntuales para obtener datos para una receta.
Creando una receta
Después de capturar los datos del siguiente formulario:
Luego ejecutamos la siguiente handleSubmit
devolución de llamada, que ejecuta la addNewRecipeMutation
mutación:
class GetAllPublishedRecipes extends Component { //other logic _handleSubmit = event = { this.props .addNewRecipeMutation({ variables: { directions, title, ingredients, published }, refetchQueries: [ { query: GetAllPublishedRecipes } ] }) .then(res = { if (res.data.createRecipe.id) { this.setState( (prevState, nextProps) = ({ addModalOpen: false }), () = this.setState( (prevState, nextProps) = ({ notification: { notificationOpen: true, type: 'success', message: `recipe ${title} added successfully`, title: 'Success' } }), () = this._handleResetState() ) ); } }) .catch(e = { this.setState((prevState, nextProps) = ({ notification: { ...prevState.notification, notificationOpen: true, type: 'error', message: e.message, title: 'Error Occured' } })); }); };};
Editar una receta
Para editar una receta, reutilizamos el formulario que se utilizó para crear una nueva receta y luego pasamos los datos de la receta. Cuando un usuario hace clic en el ícono de edición, aparece el formulario con los datos precargados de la siguiente manera:
Luego ejecutamos un handleSubmit
controlador diferente para ejecutar la mutación de actualización de la siguiente manera:
class GetAllPublishedRecipes extends Component { // other logic _updateRecipe = ({ id, directions, ingredients, title, published, action }) = { this.props .updateRecipeMutation({ variables: { id, directions, title, ingredients, published: false }, refetchQueries: [ { query: GetAllPublishedRecipes } ] }) .then(res = { if (res.data.updateRecipe.id) { this.setState( (prevState, nextProps) = ({ isEditing: false }), () = this.setState( (prevState, nextProps) = ({ notification: { notificationOpen: true, type: 'success', message: `recipe ${title} ${action} successfully`, title: 'Success' } }), () = this._handleResetState() ) ); } }) .catch(e = { this.setState((prevState, nextProps) = ({ notification: { ...prevState.notification, notificationOpen: true, type: 'error', message: e.message, title: 'Error Occured' } })); }); };}
Eliminar una receta
En cuanto a la funcionalidad de eliminación, haremos lo mismo soft-delete
en la receta eliminada, lo que significa que cambiaremos el published
atributo a falso ya que al obtener los artículos filtramos para asegurarnos de obtener solo published
artículos.
Utilizaremos la misma función que antes y pasaremos publicado como falso, como se muestra en el siguiente ejemplo:
class GetAllPublishedRecipes extends Component { // other logic _handleOnDelete = ({ id, directions, ingredients, title }) = { // user confirmed delete prompt this._updateRecipe({ id, directions, ingredients, title, published: false, // soft delete the recipe action: 'deleted' }); };};
Conclusión:
En este tutorial, creaste una aplicación de recetas con React y GraphQL, usando Prisma para administrar tu servidor GraphQL. Prisma es un servicio confiable que te permite concentrarte en implementar tu lógica empresarial.
Puedes acceder al código en GitHub.
Deja una respuesta