--- title: GraphQL theme: ./_themes/5ika.css highlightTheme: github verticalSeparator: revealOptions: transition: "fade" --- ![GraphQL](https://graphql.org/img/brand/logos/logo-wordmark.svg) _Tim Izzo - BDWA - Cours React_ --- ## Qu'est-ce que GraphQL ? - C'est un _language de requête_ (QL) pour requêter des données organisées _en graphe_. - Il permet de décrire de manière précise les données requises par une application cliente et d'obtenir ces données avec une seule requête. - C'est une alternative aux API REST avec une approche plus structurée et typée. --- ## Avantages de GraphQL - **Demande de données précises**: Les clients peuvent demander exactement les données dont ils ont besoin, ce qui évite le sur-fetching ou le under-fetching de données. - **Introspection**: GraphQL fournit un système de type pour découvrir et explorer le schéma de l'API. - **Réduction des aller-retours**: Les clients peuvent obtenir toutes les données nécessaires en une seule requête, ce qui réduit les allers-retours entre le client et le serveur. --- ## Fonctionnement On ne peut pas expliquer plus clairement que le site officiel => https://graphql.org/ --- Utiliser GraphQL dans un projet nécessite plusieurs étapes: 1. Définir un schéma GraphQL 2. Développer le backend 3. Faire des requêtes depuis le frontend --- ## Schéma GraphQL - Le schéma GraphQL est un contrat entre le client et le serveur. - Il définit les types de données disponibles et les opérations pouvant être effectuées sur ces types. ```graphql type User { id: ID! name: String! email: String! } type Query { getUser(id: ID!): User getUsers: [User]! } type Mutation { removeUser(id: ID!): Boolean } ``` --- ## Queries & Mutations - Une **Query** permet de récupérer des données (read-only) - Une **Mutation** permet d'effectuer un changement sur les données (création, modification, suppression,...) - Une **Subscription** permet à un front de suivre des changements côté backend [pas abordé] --- # Exploration d'un graphe existant => https://rickandmortyapi.com/graphql --- ## Backend Le backend doit faire correspondre un **resolver** à chaque élément de `Query` et `Mutation`. Par exemple: ```typescript const resolvers = { getUser: (id: string) => { const users = knex("users").select(["id", "name", "email"]).where({ id }); return users?.[0]; }, }; ``` --- Faire correspondre un schéma GraphQL à des resolvers demande un peu de code qui est toujours le même. En général, on préfère utiliser un framework tout prêt pour éviter de ré-inventer la roue quand on doit développer un backend GraphQL. Le framework le + utilisé est [Apollo](https://www.apollographql.com/). --- ## Apollo Apollo est un ensemble d'outils pour: - Créer un serveur GraphQL: **Apollo Server** - Créer un client GraphQL: **Apollo Client** - Gérer ses schémas à grande échelle: **GraphOS** --- ## Requête depuis un client On va utiliser pour cela [Apollo Client](https://www.apollographql.com/docs/react/) qui permet une utilisation directement dans React. --- ## Configuration du client 1. Installation des modules ```bash npm install @apollo/client graphql ``` 2. Création du client ```typescript import { ApolloClient, InMemoryCache } from "@apollo/client"; const client = new ApolloClient({ uri: "https://rickandmortyapi.com/graphql", cache: new InMemoryCache(), }); ``` 3. Mise à disposition du client pour React ```typescript , ``` --- ## Utilisation ```typescript import { gql } from '@apollo/client'; const CHARACTERS_QUERY = gql` query { characters { results { id name status } } } ` const Compo = () => { const { loading, error, data } = useQuery(CHARACTERS_QUERY); return ... } ``` --- ## Avec des arguments ```typescript import { gql } from '@apollo/client'; const CHARACTER_QUERY = gql` query getCharacter($id: ID!) { character(id: $id) { id name status } } ` const Compo = () => { const { loading, error, data } = useQuery(CHARACTER_QUERY, { variables: {id: 5} }); return ... } ``` --- ## Mutation ```typescript const CREATE_POST_MUTATION = gql` mutation createPost($post: PostInput!) { createPost(data: $post) { id name } } `; const [createPost, { data, loading, error }] = useMutation(CREATE_POST_MUTATION); ``` > Cet exemple ne fonctionnera pas sur l'API GraphQL de Rick & Morty. C'est uniquement pour donner un exemple de mutation. --- ## Mise en place pour le TP Tim crée un serveur Strapi avec un modèle "Post" permettant de stocker des articles ainsi que le plugin GraphQL. > Les permissions pour CRUD le nouveau modèle doivent être ouvertes. --- ## Travail pratique Créer un simple frontend **Typescript** avec ViteJS qui va lister les articles de blog disponibles et en créer un nouveau au clique sur un bouton (avec du contenu par défaut). --- On peut faire encore + pratique en générant automatiquement des hooks prêt-à-l'emploi pour chaque requête que l'on souhaite faire. Par exemple: ```typescript const { data, loading, error } = usePostsQuery(); const { data, loading, error } = usePostQuery({ variables: { id: 5 } }); ``` --- ## GraphQL codegen Avec [codegen](https://the-guild.dev/graphql/codegen), on peut écrire l'ensemble de nos queries et mutations dans des fichiers _.gql_ et lancer un petit script qui nous génère des hooks pratiques. --- ## Travail pratique Mettre en place [codegen](https://the-guild.dev/graphql/codegen) dans notre projet commun pour mieux organiser nos appels GraphQL. --- ## Hands-On - Authentification Dans le monde réel, il faut s'authentifier auprès d'une API pour pouvoir l'utiliser. Nous allons regarder comment configurer Apollo Client ensemble pour se connecter auprès de Strapi puis lui dire d'utilise le token JWT récupéré lorsqu'il fait une requête.