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