Come costruire un’API GraphQL?

Cos'è la copertura GraphQL

Negli ultimi anni GraphQL è diventato una scelta popolare per la creazione di API complesse. Questo perché elimina alcune delle limitazioni delle API REST tradizionali e rende le API più flessibili ed efficienti.

In questo articolo parleremo di GraphQL, dei suoi vantaggi e svantaggi, della terminologia chiave di GraphQL e confronteremo le API GraphQL con le API REST. Inoltre, vi insegneremo a costruire la vostra API GraphQL su Back4app e a connettervi da un frontend Next.js.

Introduzione a GraphQL

GraphQL è un linguaggio di interrogazione e un runtime lato server per lo sviluppo di interfacce di programmazione delle applicazioni (API). Con GraphQL, i clienti possono specificare esattamente i dati di cui hanno bisogno dall’API, invece di affidarsi al backend per fornire un insieme fisso di dati.

GraphQL è un approccio moderno ed efficiente per costruire API veloci e flessibili. Ha un sistema di tipi incorporato e si basa su uno schema fortemente tipizzato che definisce i dati disponibili attraverso l’API. Supporta aggiornamenti e sottoscrizioni in tempo reale e consente agli sviluppatori di recuperare dati da più fonti. Inoltre, facilita l’evoluzione delle API dando agli sviluppatori la possibilità di deprecare i campi senza impattare le query o le mutazioni esistenti.

GraphQL può essere utilizzato fin dall’inizio di un progetto o integrato in un’API esistente. Alcune aziende lo combinano anche con REST e poi migrano passo dopo passo.

È stato sviluppato internamente da Facebook nel 2012 e successivamente reso open source nel 2015. GraphQL ha guadagnato popolarità con l’aumento delle applicazioni a pagina singola (SPA) e delle applicazioni mobili. Da quando è stato rilasciato, è stato adottato da molti giganti tecnologici come GitHub, Airbnb, Pinterest e Shopify.

GraphQL vs REST

GraphQL e REST sono due approcci popolari per la creazione di API web.

REST (Representational State Transfer) è uno stile architettonico del software che descrive la struttura del web. È stato introdotto nel 2000 ed è stato lo standard de facto per la costruzione di API web per oltre un decennio. Utilizza metodi HTTP come GET, POST, PUT, PATCH e DELETE per manipolare le risorse. Ogni risorsa è ospitata nel suo endpoint (si veda l’immagine sottostante) e ogni volta che si richiede una risorsa viene restituito l’intero “set di dati”.

Questa architettura ha introdotto due problemi. Il primo è l’under-fetching (ottenere pochi dati) e l’over-fetching (ottenere troppi dati). Inoltre, le API REST non consentono di sottoscrivere le modifiche ai dati.

È qui che entra in gioco GraphQL. GraphQL ha un unico endpoint e ci permette di interrogare i dati da più fonti di dati con un’unica richiesta. Ci permette di definire esattamente i dati di cui abbiamo bisogno. Inoltre, GraphQL ci permette di sottoscrivere le modifiche ai dati senza eseguire il polling sul server. Rende la nostra API più prevedibile e autodocumentata.

Alla fine, la scelta tra GraphQL e REST dipenderà dai requisiti specifici del vostro progetto. Anche se GraphQL è ottimo, potrebbe introdurre troppa complessità per progetti semplici.

API REST vs API GraphQL

Termini comuni di GraphQL

Vediamo alcuni dei termini più comuni che si possono incontrare quando si lavora con GraphQL.

Tipo

GraphQL ha un sistema di tipi ed è fortemente tipizzato. Dispone di alcuni tipi scalari integrati, come Int, Float, String e Boolean, ma consente anche di definire tipi personalizzati.

Un tipo personalizzato può essere definito in questo modo:

type User {
    username: String!
    password: String!
    friends: [User!]
}

Schema

Uno schema è una descrizione dei dati disponibili attraverso un’API GraphQL. Include i tipi di oggetti, i loro campi e i tipi di dati associati, le relazioni, le query, le mutazioni e altro ancora. Uno schema viene solitamente definito utilizzando lo Schema Definition Language (SDL).

Un esempio di schema

Risolutore

Un resolver è una funzione che recupera i dati di un particolare campo in una query GraphQL. Le funzioni resolver sono responsabili del recupero dei dati da un’origine dati e della loro restituzione nel formato previsto.

Interrogazione

Una query è una richiesta di sola lettura di dati da un’API GraphQL. Si può pensare alle query come alle richieste GET delle API REST.

Esempio:

query GetUser {
    user(id: "Wfx8o2AZrE") {
        id
        username
        fullName
    }
}

Questa query restituisce l’elenco di tutti gli utenti.

Mutazione

Una mutazione è una richiesta di manipolazione dei dati in un’API GraphQL. Si può pensare alle mutazioni come alle richieste POST/PUT/PATCH/DELETE delle API REST. Le mutazioni possono anche definire quali dati vengono restituiti.

Esempio:

mutation CreateAuthor {
  createAuthor(input: {fields: {firstName: "William", lastName: "Shakespeare"}}) {
    author {
      id
      createdAt
    }
  }
}

Questa mutazione crea un nuovo autore e restituisce l’id e il createdAt dell’autore.

Abbonamento

Una sottoscrizione è una richiesta di aggiornamenti in tempo reale da un’API GraphQL. Le sottoscrizioni consentono ai client di ricevere gli aggiornamenti non appena sono disponibili, senza interrogare il server.

Esempio:

subscription OnPostCreate($postID: ID!) {
  userAdded(postID: $postID) {
    id
    user
    content
  }
}

Questa sottoscrizione viene richiamata quando viene creato un nuovo post.

Come funziona GraphQL?

Per implementare un’API GraphQL è necessario eseguire i seguenti passaggi:

  1. Descrivere i dati utilizzando uno schema
  2. Collegare i resolver alle fonti di dati
  3. Scrivere query e mutazioni
  4. Ottenere risultati prevedibili

Utilizzando Back4app o un servizio simile, la maggior parte di questo lavoro sarà eliminato. Mentre si creano i modelli di database, Back4app genera automaticamente lo schema GraphQL e la documentazione. Per saperne di più, si veda la parte pratica del tutorial.

Quali sono i vantaggi di GraphQL?

GraphQL è facile da imparare, gli utenti possono aggregare dati da più fonti ed è un linguaggio moderno per le vostre API.

Schema

L’API GraphQL si basa su uno schema fortemente tipizzato. Ciò consente di rilevare errori di tipo e bug in fase di compilazione piuttosto che in fase di esecuzione. Inoltre, le API GraphQL sono introspettive, il che significa che possono fornire informazioni su se stesse senza fare affidamento su alcuna documentazione esterna.

Recupero dati flessibile ed efficiente

Le API GraphQL sono estremamente flessibili perché consentono ai clienti di specificare esattamente ciò di cui hanno bisogno. Questo risolve il problema dell’under-fetching e dell’over-fetching e riduce il numero di richieste API. Un minor numero di richieste API si traduce in migliori prestazioni.

Aggiornamenti API

Con GraphQL, è possibile integrare senza problemi nuovi campi e tipi senza influenzare le query correnti. I campi deprecati e obsoleti possono anche essere nascosti dagli strumenti. Le API GraphQL forniscono alle applicazioni un accesso costante a nuove funzionalità e incoraggiano lo sviluppo di codice server più pulito e sostenibile.

Un’unica fonte di verità

Uno schema GraphQL stabilisce un’unica fonte di verità in un’applicazione GraphQL. Offre a un’organizzazione un modo semplice per gestire l’intera API.

Estensioni GraphQL

GraphQL è supportato da un’enorme comunità di sviluppatori GraphQL e viene fornito con molte estensioni open-source. Le estensioni semplificano alcune attività comuni dell’API, come la paginazione, il caching, il monitoraggio delle prestazioni e così via.

Quali sono gli svantaggi di GraphQL?

Complessità

GraphQL sposta gran parte del lavoro di una query di dati sul lato server, rendendo i backend più complessi. Inoltre, il linguaggio di query e le definizioni dello schema potrebbero richiedere una maggiore pianificazione e manutenzione iniziale.

Curva di apprendimento

GraphQL ha una curva di apprendimento più ripida rispetto a REST. Inoltre, gli sviluppatori GraphQL sono solitamente più costosi e difficili da trovare rispetto agli sviluppatori REST.

Mancanza di standardizzazione

Una delle principali critiche a GraphQL è la mancanza di standardizzazione nella sua implementazione. Le API REST hanno un insieme consolidato di principi e best practice, mentre la documentazione di GraphQL fornisce solo alcuni suggerimenti generali su come implementare le cose. Questo può portare a incoerenze e confusione nel modo in cui le API GraphQL vengono progettate e utilizzate.

Sicurezza

L’aspetto positivo di GraphQL è che i client possono richiedere esattamente ciò di cui hanno bisogno, ma d’altra parte questo potrebbe essere un potenziale rischio per la sicurezza. È importante convalidare e sanificare correttamente l’input dell’utente per evitare che vengano eseguite query dannose.

Come costruire un’API GraphQL?

Questa sezione dell’articolo illustra come creare un’API GraphQL con Back4app e collegarsi ad essa da un frontend Next.js.

Prerequisiti

  • Esperienza con JavaScript ES6
  • Esperienza con React e Next.js
  • Conoscenza di base di GraphQL

Che cos’è Back4app?

Back4app è un’eccezionale soluzione Backend as a Service (BaaS) che opera sulla base di un software open-source. La piattaforma offre un’ampia gamma di funzionalità che consentono agli utenti di sviluppare applicazioni web e mobili in modo più semplice e rapido. Consente alle aziende di concentrarsi sulla logica aziendale senza doversi preoccupare del backend o dell’infrastruttura sottostante.

Back4app è dotato di una dashboard facile da usare e ricca di funzioni e di un’interfaccia a riga di comando (CLI). Fornisce inoltre kit di sviluppo software (SDK) per vari strumenti popolari come Node.js, Flutter, React Native, Android, Angular, iOS e altri ancora.

Back4app segue un modello di prezzi semplice che può soddisfare le esigenze di qualsiasi applicazione. Offre anche un piano gratuito (senza carta di credito), ottimo per i test e i prototipi.

Volete saperne di più su Back4app? Perché usare Back4app?

Introduzione al progetto

Costruiremo una semplice applicazione web TODO. L’applicazione sarà composta da due parti: il backend e il frontend. Il backend sarà alimentato da un’API GraphQL e distribuito su Back4app. Il frontend, invece, sarà scritto in TypeScript utilizzando il framework Next.js. Per collegare il frontend al backend utilizzeremo il client Apollo.

L’applicazione finale avrà il seguente aspetto:

Anteprima del progetto back4app-graphql

Backend

Creare l’applicazione Back4app

Per procedere con i passaggi seguenti, è necessario disporre di un account Back4app. Se ne avete già uno, accedete. Altrimenti, non esitate a registrarvi per un account gratuito.

Per utilizzare Back4app, il primo passo è creare un’app. Una volta effettuato l’accesso alla propria dashboard, sarà possibile visualizzare un elenco delle app correnti. Per creare una nuova app, cliccare su “Crea una nuova app”.

Creazione di app Back4app

Poiché stiamo costruendo un’API GraphQL, scegliere l’opzione “Backend as a Service” e specificare un nome unico per l’applicazione. Inoltre, scegliere “NoSQL” come tipo di database.

Attendete pazientemente che Back4app configuri tutto ciò che è necessario per la vostra applicazione, compresi il database, il livello applicativo, la scalabilità, i backup e la sicurezza.

Una volta completata la configurazione, si verrà indirizzati alla dashboard dell’applicazione.

Creata l'app Back4app

Definire i modelli di database

Poiché stiamo costruendo una semplice applicazione TODO, avremo bisogno di un solo modello di database.

Per iniziare, accedere alla dashboard di Back4app e individuare l’opzione “Database” nella barra laterale. Da qui, scegliere “Crea una classe” e assegnarle il nome “Attività”. Assicuratevi di selezionare “Lettura e scrittura pubbliche abilitate” e quindi fate clic su “Crea classe e aggiungi colonne”.

Back4app definisce il modello

Includere le colonne successive:

+-----------+------------------+---------------+----------+
| Data type | Name             | Default value | Required |
+-----------+------------------+---------------+----------+
| String    | name             | <leave blank> | yes      |
+-----------+------------------+---------------+----------+
| String    | description      | <leave blank> | no       |
+-----------+------------------+---------------+----------+
| Boolean   | isDone           | false         | no       |
+-----------+------------------+---------------+----------+

Dopo aver creato il modello di database, si noterà che quattro colonne del database sono state aggiunte automaticamente:

  1. objectId è la chiave primaria dell’oggetto
  2. updatedAt è il timestamp dell’ultimo aggiornamento
  3. createdAt è il timestamp della creazione
  4. ACL definisce l'”Elenco di controllo degli accessi”.

Teneteli a mente, perché ci serviranno più avanti nel corso del tutorial, quando lavoreremo sulle query GraphQL e sulle mutazioni.

Per familiarizzare con la dashboard di Back4app, provate ad aggiungere due task di esempio, ad es:

+-----------------+----------------------------------------+--------+
| name            | description                            | isDone |
+-----------------+----------------------------------------+--------+
| GraphQL backend | Create a GraphQL backend via Back4app. | false  |
+-----------------+----------------------------------------+--------+
| Learn GraphQL   | Learn the basics of GraphQL.           | true   |
+-----------------+----------------------------------------+--------+

Console API GraphQL

GraphQL API Console ci permette di testare le query e le mutazioni GraphQL prima di implementarle nel codice. Per accedere alla console, selezionare “API” nella barra laterale e poi “Console > GraphQL”.

Console GraphQL di Back4app

La console è estremamente facile da usare. Sul lato sinistro, possiamo inserire le nostre query e mutazioni personalizzate e i risultati vengono visualizzati sulla destra.

Per verificare se tutto funziona, eseguire la seguente query:

query CheckHealth {
    health
}

Si dovrebbe ottenere la seguente risposta JSON:

{
  "data": {
    "health": true
  }
}

Uno degli aspetti positivi di Back4app è che si basa su Parse. Quando abbiamo creato il nostro modello di database, Parse ha configurato automaticamente GraphQL per noi. Questo include la generazione di uno schema GraphQL, di documenti e così via.

Proviamo a elencare le attività e i loro dettagli dal database:

query GetTasks {
  tasks {
    count
    edges {
      node {
        id
        name
        description
        isDone
      }
    }
  }
}

Dovreste ottenere una risposta simile:

{
  "data": {
    "tasks": {
      "count": 2,
      "edges": [
        {
          "node": {
            "id": "VGFzazpXQkJzSkRtV2xU",
            "name": "GraphQL backend",
            "description": "Create a GraphQL backend via Back4app.",
            "isDone": false
          }
        },
        {
          "node": {
            "id": "VGFzazpnM2lhNzdwUXBp",
            "name": "Learn GraphQL",
            "description": "Learn the basics of GraphQL.",
            "isDone": true
          }
        }
      ]
    }
  }
}

L’ottenimento di un oggetto specifico, la creazione di oggetti, il loro aggiornamento e così via avvengono in modo analogo. Non mi dilungherò troppo in dettagli, dato che spiegherò queste query e mutazioni più avanti nel tutorial. Inoltre, la documentazione di Back4app tratta bene questi argomenti:

  1. Creare un oggetto
  2. Ottenere un oggetto
  3. Trovare gli oggetti
  4. Aggiornamento di un oggetto
  5. Eliminazione di un oggetto
  6. Autenticazione

Questo è tutto per la parte del backend. Nella prossima sezione inizieremo a lavorare sul frontend.

Frontend

Creare la prossima applicazione

Il modo più semplice per avviare un progetto Next.js è usare l’utility create-next-app. Aprite il vostro terminale ed eseguite il seguente comando:

$ yarn create next-app

√ What is your project named? ... back4app-graphql
√ Would you like to use TypeScript with this project? ... No
√ Would you like to use ESLint with this project? ... Yes
√ Would you like to use the `src/` directory with this project? ... No
√ Would you like to use the experimental `app/` directory with this project? ... No
√ What import alias would you like configured? ... @/*

Successfully created a Next.js app.

Quindi, eseguire il server di sviluppo:

$ yarn dev

Navigate su http://localhost:3000 e dovreste vedere la pagina di destinazione predefinita di Next.js.

Successiva Pagina di atterraggio predefinita JS

ChakraUI

Per accelerare e semplificare il processo di costruzione dell’UI/UX utilizzeremo ChakraUI. Chakra UI è una libreria di componenti semplice, modulare e accessibile che offre tutto ciò che serve per costruire le applicazioni React.

In caso di problemi, consultare ChakraUI: Come iniziare con Next.js.

Per installarlo, eseguire:

yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion

Quindi, spostarsi in _pages/app.tsx e avvolgere l’applicazione con ChakraProvider in questo modo:

// pages/_app.tsx

import "../styles/globals.css";
import type {AppProps} from "next/app";
import {ChakraProvider} from "@chakra-ui/react";

export const theme = extendTheme({});

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ChakraProvider theme={theme}>
      <Component {...pageProps} />
    </ChakraProvider>
  );
}

export default MyApp;

Non dimenticate di importare il ChakraProvider:

import {ChakraProvider} from "@chakra-ui/provider";

Per evitare lampi di colore casuali, assicurarsi di caricare lo script della modalità colore prima del contenuto. Per farlo, si può utilizzare _document.js in questo modo:

// pages/_document.tsx

import {ColorModeScript} from "@chakra-ui/react";
import { Html, Head, Main, NextScript } from "next/document";
import {theme} from "@/pages/_app";

export default function Document() {
  return (
    <Html lang='en'>
      <Head />
      <body>
        <ColorModeScript initialColorMode={theme.config.initialColorMode} />
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

Bene, avete installato ChakraUI con successo.

Interfaccia utente

Procediamo con la creazione dell’interfaccia utente. La nostra applicazione web avrà le due pagine seguenti:

  1. / visualizza l’elenco dei compiti
  2. crea/ visualizza il modulo per la creazione dei compiti

Iniziate sostituendo pages/index.tsx con il seguente contenuto:

// pages/index.tsx

import type {NextPage} from "next";
import {
    Button, Card, CardBody, Container,
    Heading, HStack, Stack, Text, VStack
} from "@chakra-ui/react";
import Link from "next/link";

let data = {
  "tasks": {
    "count": 2,
    "edges": [
      {
        "node": {
          "id": "VGFzazpXQkJzSkRtV2xU",
          "name": "GraphQL backend",
          "description": "Create a GraphQL backend via Back4app.",
          "isDone": false
        }
      },
      {
        "node": {
          "id": "VGFzazpnM2lhNzdwUXBp",
          "name": "Learn GraphQL",
          "description": "Learn the basics of GraphQL.",
          "isDone": true
        }
      }
    ]
  }
};

const ListPage: NextPage = () => {

  const handleMarkAsDone = async (id: string, isDone: boolean) => {
    console.log("TODO: mark task as done and refetch");
  };

  const handleDelete = async (id: string) => {
    console.log("TODO: delete task and refetch");
  };

  return (
    <>
      <Container maxWidth="container.lg">
        <HStack w="fill" justifyContent="space-between" mt={8} mb={4}>
          <Heading as="h1" size="lg">back4app-graphql</Heading>
          <Link href="/create">
            <Button size="sm" colorScheme="blue">
              Create task
            </Button>
          </Link>
        </HStack>
        <VStack spacing={4}>
          {data.tasks.edges.map((edge) => {
            let task = edge.node;
            return (
              <Card key={task.id} w="100%">
                <CardBody>
                  <Stack direction="column">
                    <Heading as="h2" size="md">
                      {task.isDone ? "✔️" : "❌"}{" "}
                      {task.name}
                    </Heading>
                    <Text>
                      {task.description}
                    </Text>
                    <Stack direction="row" pt={2}>
                      <Button size="sm" colorScheme="blue" onClick={() => handleMarkAsDone(task.id, task.isDone)}>
                        Toggle done
                      </Button>
                      <Button size="sm" colorScheme="red" onClick={() => handleDelete(task.id)}>
                        Delete
                      </Button>
                    </Stack>
                  </Stack>
                </CardBody>
              </Card>
            );
          })}
        </VStack>
      </Container>
    </>
  );
};

export default ListPage;
  1. Per progettare l’interfaccia utente abbiamo utilizzato ChakraUI.
  2. I compiti sono attualmente caricati dall’array statico denominato dati.
  3. In seguito utilizzeremo handleMarkAsDone() e handleDelete() per inviare richieste API GraphQL.

Quindi, creare un file create.tsx nella cartella pages con i seguenti contenuti:

// pages/create.tsx

import type {NextPage} from "next";
import {
  Button, Card, CardBody, CardHeader, Container, FormControl,
  FormLabel, Heading, HStack, Input, Stack, Switch, Text
} from "@chakra-ui/react";
import Link from "next/link";
import {useState} from "react";
import {useRouter} from "next/router";

const CreatePage: NextPage = () => {
  const router = useRouter();

  const [name, setName] = useState("");
  const [description, setDescription] = useState("");
  const [isDone, setIsDone] = useState(false);

  const [formError, setFormError] = useState("");

  const handleSubmit = (event) => {
    event.preventDefault();

    if (!name || !description) {
      setFormError("Please enter the title and the description.");
      return;
    }

    console.log("TODO: call the GraphQL API and redirect");
  };

  return (
    <>
      <Container maxWidth="container.lg">
        <HStack w="fill" justifyContent="space-between" mt={8} mb={4}>
          <Heading as="h1" size="lg">back4app-graphql</Heading>
          <Link href="/">
            <Button size="sm" colorScheme="blue">
              View list
            </Button>
          </Link>
        </HStack>
        <Card>
          <CardHeader>
            <Stack direction="column">
              <Heading as="h2" size="md">Create task</Heading>
              <Text>
                Fill out the form and press &quot;Create&quot; to create a new task.
              </Text>
            </Stack>
          </CardHeader>
          <CardBody>
            <form onSubmit={handleSubmit}>
              <Stack direction="column">
                {formError && <Text color="red.500" fontWeight="bold">{formError}</Text>}
                <FormControl>
                  <FormLabel>Name</FormLabel>
                  <Input type="text" value={name} onChange={(event) => setName(event.target.value)}/>
                </FormControl>
                <FormControl>
                  <FormLabel>Description</FormLabel>
                  <Input type="text" value={description} onChange={(event) => setDescription(event.target.value)}/>
                </FormControl>
                <FormControl display="flex" alignItems="center">
                  <FormLabel mb="0">
                    Is done?
                  </FormLabel>
                  <Switch isChecked={isDone} onChange={() => setIsDone(!isDone)}/>
                </FormControl>
                <Button size="sm" colorScheme="blue" type="submit">Create task</Button>
              </Stack>
            </form>
          </CardBody>
        </Card>
      </Container>
    </>
  );
};

export default CreatePage;
  1. Anche in questo caso abbiamo utilizzato i componenti di ChakraUI per creare l’interfaccia utente.
  2. Abbiamo creato un modulo controllato da React per la creazione di attività.
  3. La funzione handleSubmit() sarà utilizzata in seguito per inviare una richiesta API.

Rilanciare il server web e visitare l’applicazione web all’indirizzo http://localhost:3000. Si dovrebbero vedere i due task codificati. Quindi, fare clic su “Crea attività” per visualizzare il modulo di creazione dell’attività.

Back4app GraphQL Crea attività

Cliente GraphQL

Per connettersi a un’API GraphQL dal frontend è necessario installare un client GraphQL. Suggerisco di scegliere il client Apollo, in quanto è facile da configurare, non è un’opzione e non richiede molto boilerplate.

Iniziare installando @apollo/client e graphql:

$ yarn add @apollo/client graphql

Per inizializzare il client è necessario fornire le credenziali API di Back4app. Il modo più semplice per ottenere le credenziali è navigare nella GraphQL Console e prendere nota delle intestazioni.

Credenziali GraphQL di Back4app

Poiché non si vuole esporre le chiavi API nel codice sorgente, creare un file .env.local nella radice del progetto con i seguenti contenuti:

# .env.local

NEXT_PUBLIC_PARSE_APPLICATION_ID=<YOUR_PARSE_APP_ID>
NEXT_PUBLIC_PARSE_MASTER_KEY=<YOUR_PARSE_MASTER_KEY>
NEXT_PUBLIC_PARSE_CLIENT_KEY=<YOUR_PARSE_CLIENT_KEY>

Quindi, navigare in pages/_app.tsx e inizializzare il client Apollo, quindi avvolgere l’applicazione con ApolloProvider in questo modo:

// pages/_app.tsx

// ...
import {ApolloClient, ApolloProvider, InMemoryCache} from "@apollo/client";

const client = new ApolloClient({
  uri: "https://parseapi.back4app.com/graphql",
  headers: {
    "X-Parse-Application-Id": process.env.NEXT_PUBLIC_PARSE_APPLICATION_ID,
    "X-Parse-Master-Key": process.env.NEXT_PUBLIC_PARSE_MASTER_KEY,
    "X-Parse-Client-Key": process.env.NEXT_PUBLIC_PARSE_CLIENT_KEY,
  },
  cache: new InMemoryCache(),
});

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ChakraProvider theme={theme}>
      <ApolloProvider client={client}>
        <Component {...pageProps} />
      </ApolloProvider>
    </ChakraProvider>
  );
}

Attendere che il frontend venga ricompilato, quindi visitare l’applicazione web e verificare la presenza di eventuali errori nella console. Nessun errore significa che la connessione è avvenuta con successo.

Query e mutazioni GraphQL

L’ultima cosa da fare è definire le query e le mutazioni GraphQL e poi richiamarle dal codice React.

Per abilitare l’assistenza al codice GraphQL nel vostro IDE, visitate la Console GraphQL di Back4app, selezionate “Schema” nella barra laterale e scaricatelo come SDL. Creare quindi un nuovo file chiamato schema.graphql nella radice del progetto e incollare il contenuto dell’SDL.

Per prima cosa, navigare in pages/index.tsx e aggiungere le seguenti query dopo le importazioni:

// pages/index.tsx

const GET_TASKS = gql`
  query GetTasks {
    tasks {
      count
      edges {
        node {
          id
          name
          description
          isDone
        }
      }
    }
  }
`;

const UPDATE_TASK = gql`
  mutation UpdateTask($id: ID!, $isDone: Boolean!) {
    updateTask(input: { id: $id, fields: { isDone: $isDone } }) {
      task {
        isDone
        updatedAt
      }
    }
  }
`;

const DELETE_TASK = gql`
  mutation DeleteTask($id: ID!) {
    deleteTask(input: { id: $id }) {
      task {
        id
      }
    }
  }
`;

Queste tre query si spiegano da sole. La prima restituisce un elenco di tutti i task, la seconda aggiorna la proprietà isDone di un task specifico e la terza cancella un task specifico.

Quindi, modificare la parte superiore di ListPage in questo modo:

// pages_index.tsx

// ...

const ListPage: NextPage = () => {

  const {loading, error, data, refetch} = useQuery(GET_TASKS);
  const [deleteTask] = useMutation(DELETE_TASK);
  const [updateTask] = useMutation(UPDATE_TASK);

const handleMarkAsDone = async (id: string, isDone: boolean) => {
    try {
      const updateTaskResponse = await updateTask({
        variables: {id: id, isDone: !isDone}
      });
      console.debug(updateTaskResponse);
      refetch();
    } catch (error) {
      console.error(error);
    }
  };

  const handleDelete = async (id: string) => {
    try {
      const deleteTaskResponse = await deleteTask({
        variables: {id: id},
      });
      console.debug(deleteTaskResponse);
      refetch();
    } catch (error) {
      console.error(error);
    }
  };

  if (error) return <p>Oops, something went wrong.</p>;
  if (loading) return <Spinner/>;

  // ...
};

export default ListPage;
  1. Abbiamo usato useQuery() per eseguire la query GET_TASKS e memorizzare il risultato.
  2. Abbiamo usato useMutation() per definire le mutazioni GraphQL.
  3. Abbiamo aggiornato handleMarkAsDone() e handleDelete() per utilizzare i ganci di mutazione.

Procedendo, modificare pages/create.tsx in modo analogo:

const CREATE_TASK = gql`
  mutation CreateTask($name: String!, $description: String, $isDone: Boolean!) {
    createTask(
      input: {
        fields: { name: $name, description: $description, isDone: $isDone }
      }
    ) {
      task {
        id
      }
    }
  }
`;

const CreatePage: NextPage = () => {

  // ...

  const [createTask] = useMutation(CREATE_TASK);

  const handleSubmit = (event) => {
    event.preventDefault();

    if (!name || !description) {
      setFormError("Please enter the title and the description.");
      return;
    }

    createTask({
      variables: {name: name, description: description, isDone: isDone}
    }).then(response => {
      router.push("/");
    });
  };

  // ...
};

export default CreatePage;

Non dimenticatevi dell’importazione:

import {gql, useMutation, useQuery} from "@apollo/client";

Ottimo, è tutto!

Riavviare il server di sviluppo e visitare l’applicazione web. Verificare se i task sono caricati dal database, provare a creare un nuovo task, contrassegnarlo come eseguito ed eliminarlo.

Conclusione

In conclusione, GraphQL è una buona scelta per la costruzione di API complesse, grazie alle sue capacità di interrogazione flessibile e al recupero efficiente dei dati. Sebbene abbia molti vantaggi rispetto alle tradizionali API REST, ci sono alcuni svantaggi da considerare quando si inizia un progetto.

In questo articolo abbiamo discusso i vantaggi e gli svantaggi di GraphQL, l’abbiamo confrontato con le API REST e abbiamo introdotto alcuni termini chiave di GraphQL. Ora dovreste essere in grado di creare la vostra semplice API GraphQL su Back4app e di connettervi ad essa da un frontend JavaScript.

È possibile prelevare il codice sorgente finale dalla repo di GitHub.

FAQ

Che cos’è GraphQL?

GraphQL è un linguaggio di interrogazione e un runtime lato server per sviluppare API potenti e flessibili.

Quali sono le principali differenze tra REST e GraphQL?

REST è un approccio standardizzato e semplice per costruire servizi web, mentre GraphQL offre capacità di interrogazione più flessibili ed elimina il recupero insufficiente o eccessivo dei dati.

Quali sono i termini comunemente usati in GraphQL?

– Schema è una descrizione dei dati disponibili tramite un’API GraphQL.
– Resolver è una funzione che recupera i dati per un determinato campo in una query GraphQL.
– Query è una richiesta in sola lettura di dati da un’API GraphQL.
– Mutation è una richiesta per modificare i dati in un’API GraphQL.
– Subscription è una richiesta per aggiornamenti in tempo reale da un’API GraphQL.

Come costruire un’API GraphQL?

1. Crea un account gratuito su Back4app.
2. Progetta i modelli di database.
3. Scrivi le query e le mutation tramite la Console API GraphQL di Back4app.
4. Installa un client GraphQL (come Apollo o Relay) nel tuo progetto frontend.
5. Inizializza il client e collegalo all’API GraphQL.


Leave a reply

Your email address will not be published.