crea/react/GraphQL.md (view raw)
1---
2title: GraphQL
3theme: ./_themes/5ika.css
4highlightTheme: github
5verticalSeparator: <!--v-->
6revealOptions:
7 transition: "fade"
8---
9
10![GraphQL](https://graphql.org/img/brand/logos/logo-wordmark.svg)
11
12_Tim Izzo - BDWA - Cours React_
13
14---
15
16## Qu'est-ce que GraphQL ?
17
18- C'est un _language de requête_ (QL) pour requêter des données organisées _en graphe_.
19- 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.
20- C'est une alternative aux API REST avec une approche plus structurée et typée.
21
22---
23
24## Avantages de GraphQL
25
26- **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.
27- **Introspection**: GraphQL fournit un système de type pour découvrir et explorer le schéma de l'API.
28- **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.
29
30---
31
32## Fonctionnement
33
34On ne peut pas expliquer plus clairement que le site officiel
35
36=> https://graphql.org/
37
38---
39
40Utiliser GraphQL dans un projet nécessite plusieurs étapes:
41
421. Définir un schéma GraphQL
432. Développer le backend
443. Faire des requêtes depuis le frontend
45
46---
47
48## Schéma GraphQL
49
50- Le schéma GraphQL est un contrat entre le client et le serveur.
51- Il définit les types de données disponibles et les opérations pouvant être effectuées sur ces types.
52
53```graphql
54type User {
55 id: ID!
56 name: String!
57 email: String!
58}
59
60type Query {
61 getUser(id: ID!): User
62 getUsers: [User]!
63}
64
65type Mutation {
66 removeUser(id: ID!): Boolean
67}
68```
69
70---
71
72## Queries & Mutations
73
74- Une **Query** permet de récupérer des données (read-only)
75- Une **Mutation** permet d'effectuer un changement sur les données (création, modification, suppression,...)
76- Une **Subscription** permet à un front de suivre des changements côté backend [pas abordé]
77
78---
79
80# Exploration d'un graphe existant
81
82=> https://rickandmortyapi.com/graphql
83
84---
85
86## Backend
87
88Le backend doit faire correspondre un **resolver** à chaque élément
89de `Query` et `Mutation`.
90
91Par exemple:
92
93```typescript
94const resolvers = {
95 getUser: (id: string) => {
96 const users = knex("users").select(["id", "name", "email"]).where({ id });
97 return users?.[0];
98 },
99};
100```
101
102---
103
104Faire correspondre un schéma GraphQL à des resolvers demande un peu de code
105qui est toujours le même.
106
107En général, on préfère utiliser un framework tout prêt pour éviter
108de ré-inventer la roue quand on doit développer un backend GraphQL.
109
110Le framework le + utilisé est [Apollo](https://www.apollographql.com/).
111
112---
113
114## Apollo
115
116Apollo est un ensemble d'outils pour:
117
118- Créer un serveur GraphQL: **Apollo Server**
119- Créer un client GraphQL: **Apollo Client**
120- Gérer ses schémas à grande échelle: **GraphOS**
121
122---
123
124## Requête depuis un client
125
126On va utiliser pour cela [Apollo Client](https://www.apollographql.com/docs/react/)
127qui permet une utilisation directement dans React.
128
129---
130
131## Configuration du client
132
1331. Installation des modules
134
135 ```bash
136 npm install @apollo/client graphql
137 ```
138
1392. Création du client
140
141 ```typescript
142 import { ApolloClient, InMemoryCache } from "@apollo/client";
143
144 const client = new ApolloClient({
145 uri: "https://rickandmortyapi.com/graphql",
146 cache: new InMemoryCache(),
147 });
148 ```
149
1503. Mise à disposition du client pour React
151 ```typescript
152 <ApolloProvider client={client}>
153 <App />
154 </ApolloProvider>,
155 ```
156
157---
158
159## Utilisation
160
161```typescript
162import { gql } from '@apollo/client';
163
164const CHARACTERS_QUERY = gql`
165 query {
166 characters {
167 results {
168 id
169 name
170 status
171 }
172 }
173 }
174`
175
176const Compo = () => {
177 const { loading, error, data } = useQuery(CHARACTERS_QUERY);
178
179 return ...
180}
181
182```
183
184---
185
186## Avec des arguments
187
188```typescript
189import { gql } from '@apollo/client';
190
191const CHARACTER_QUERY = gql`
192 query getCharacter($id: ID!) {
193 character(id: $id) {
194 id
195 name
196 status
197 }
198 }
199`
200
201const Compo = () => {
202 const { loading, error, data } = useQuery(CHARACTER_QUERY, {
203 variables: {id: 5}
204 });
205
206 return ...
207}
208```
209
210---
211
212## Mutation
213
214```typescript
215const CREATE_POST_MUTATION = gql`
216 mutation createPost($post: PostInput!) {
217 createPost(data: $post) {
218 id
219 name
220 }
221 }
222`;
223
224const [createPost, { data, loading, error }] =
225 useMutation(CREATE_POST_MUTATION);
226```
227
228> Cet exemple ne fonctionnera pas sur l'API GraphQL de Rick & Morty. C'est uniquement pour donner un exemple de mutation.
229
230---
231
232## Mise en place pour le TP
233
234Tim crée un serveur Strapi avec un modèle "Post" permettant de stocker des articles ainsi que le plugin GraphQL.
235
236> Les permissions pour CRUD le nouveau modèle doivent être ouvertes.
237
238---
239
240## Travail pratique
241
242Créer un simple frontend **Typescript** avec ViteJS qui va lister les articles de blog
243disponibles et en créer un nouveau au clique sur un bouton (avec du
244contenu par défaut).
245
246---
247
248On peut faire encore + pratique en générant
249automatiquement des hooks prêt-à-l'emploi pour chaque
250requête que l'on souhaite faire.
251
252Par exemple:
253
254```typescript
255const { data, loading, error } = usePostsQuery();
256const { data, loading, error } = usePostQuery({ variables: { id: 5 } });
257```
258
259---
260
261## GraphQL codegen
262
263Avec [codegen](https://the-guild.dev/graphql/codegen), on peut écrire l'ensemble
264de notre queries et mutations dans des fichiers _.gql_ et lancer un petit
265script qui nous génère des hooks pratiques.
266
267---
268
269## Travail pratique
270
271Mettre en place [codegen](https://the-guild.dev/graphql/codegen) dans notre projet
272commun pour mieux organiser nos appels GraphQL.
273
274---
275
276## Hands-On - Authentification
277
278Dans le monde réel, il faut s'authentifier auprès d'une API pour pouvoir l'utiliser.
279
280Nous 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.