--- 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** --- ## Travail pratique Ensemble, nous allons mettre en place un serveur GraphQL permettant de gérer un blog. --- **Première étape**: Définir le schémas. Nous devons définir: - Le type `Post` définissant un article de blog - Les *queries* et *mutations* possibles sur notre graphe. Ici, on veut CRUD des articles. --- **Deuxième étape**: Installer Apollo Server => https://www.apollographql.com/docs/apollo-server/getting-started --- **Troisième étape**: Développer les resolvers. > Il est nécessaire de se répartir le travail pour éviter > de se marcher sur les pieds. --- **Quatrième étape**: Tester avec Apollo Sandbox Une interface graphique est automatiquement disponible sur le port utilisé par Apollo lorsqu'on est en mode dev. --- ## Requête depuis un client Une fois que le backend est prêt, on peut faire des requêtes 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: 'http://localhost:4000', cache: new InMemoryCache(), }); ``` 3. Mise à disposition du client pour React ```typescript , ``` --- ## Utilisation ```typescript import { gql } from '@apollo/client'; const POSTS_QUERY = gql` query getPosts { getPosts { id name } } ` const Compo = () => { const { loading, error, data } = useQuery(POSTS_QUERY); return ... } ``` --- ## Avec des arguments ```typescript import { gql } from '@apollo/client'; const POST_QUERY = gql` query getPost($postId: ID!) { getPost(id: $postId) { id name } } ` const Compo = () => { const { loading, error, data } = useQuery(POST_QUERY, { variables: {postId: 3} }); 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); ``` --- ## 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: {postId: 5}}); ``` --- ## GraphQL codegen Avec [codegen](https://the-guild.dev/graphql/codegen), on peut écrire l'ensemble de notre 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.