Local First avec React Native et Expo - 7. Query API

Mise en ligne : dimanche 13 octobre 2024

image de Local First avec React Native et Expo - 7. Query API}

Query API

Pour suivre cet article dans les meilleurs conditions, je vous propose de récupérer le code de démarrage dans ce repo GitHub :

Branche startQueryApi du repo Github

Vous pourrez également comparer votre code avec mon code ici, si vous rencontrez des problèmes :

Branche endQueryApi du repo Github

Pensez bien, également, à lancer Expo, via le development build et non via Expo Go.

Pour iOS :

npm run ios

ou

Pour Android :

npm run android

Pour récupérer nos données depuis watermelonDB, nous utiliserons un useState et un useEffect. Mais, dans les prochains articles, nous verrons qu'il y a une autre manière de récupérer nos données et même que nous pourrons observer leur modification !

Pour le moment, on fait au plus simple, car nous allons nous concentrer sur les query API

Nous utiliserons useState pour afficher nos données dans une FlatList, qui se trouve dans le composant enfant <ListPost /> :

const [posts, setPosts] = useState<Post[]>([]);
<ListPost posts={posts} />

Nous utiliserons un useEffect pour fetch les données, via une fonction fetchPosts, défini dans la page :

useEffect(() => { fetchPosts(); }, []); const fetchPosts = async () => { // fonction dans laquelle nous importerons nos fonctions (avec les query). const posts = await getPosts(); // On met la data dans notre state setPosts(posts); };

Avant de commencer à récupérer nos données, nous allons créer des Pots, via le bouton Créer un post.

1. Query simple

Pour récupérer des données, nous utiliserons la méthode query qui permet de réaliser une requête sql. Par défaut, elle permet de récupérer tous les éléments de la collection sur laquelle nous effectuons la requête.

const posts = await database.get<Post>('posts').query().fetch(); };

Une variante permet de récupérer le nombre d'occurrences que nous récupérons avec la requête.

const count = await database.get<Post('posts').query().fetchCount(); };

2. Utilisation de Q pour des requêtes plus complexes

Les requêtes via Qsont équivalentes à ce que nous pourrions réaliser avec du javascript, en terme de performances.

Vous pouvez retrouver le tableau des équivalences, via un lien vers la documentation officielle sur les query API : Equivalences javascript

Nous pouvons spécifier des paramètres à notre requête, comme pour des requêtes sql. A cet effet, watermelonDB met à notre disposition Q, que nous devons importer.

import { Q } from '@nozbe/watermelondb';

3. Q.sortBy, Q.asc et Q.desc pour trier les résultats

Pour trier les résultats d'une requête, nous avons sortByque nous utiliserons avec ascou desc.

Par exemple :

const posts = await database .get<Post>('posts') .query(Q.sortBy('title', Q.asc)) .fetch();

4. Q.where pour tester des conditions

Nous utiliserons Q.where, avec comme paramètres, le nom de la colonne et la comparaison elle-même.

5. Q.eq

Pour tester si une condition est vrai (ou fausse), nous avons eq. Voici un exemple d'utilisation :

const posts = await database .get<Post>('posts') .query(Q.where('is_pinned', Q.eq(false))) .fetch();

Nous pouvons utiliser une syntaxe courte, avec uniquement true ou false à la place de eq(false) ou eq(true).

Ce qui donnerait :

const posts = await database .get<Post>('posts') .query(Q.where('is_pinned', false)) .fetch();

6. Q.gt, Q.gte, Q.lte, Q.lt, Q.between pour comparer des nombres.

  • gt : plus grand que
  • gte : plus grand ou égal que
  • lte : plus petit ou égal que
  • lt : plus petit que
  • between : compris entre deux nombres

Utilisation de gte :

const posts = await database .get<Post>('posts') .query(Q.where('likes', Q.gte(50))) .fetch();

Utilisation de between :

const posts = await database .get<Post>('posts') .query(Q.where('likes', Q.between(30, 50))) .fetch();

7. Q.like Q.notLike

C'est l'équivalent des regex en javascript, ce qui nous permet de filtrer un texte en ignorant la casse (case-insensitive).

const posts = await database .get<Post>('posts') .query(Q.where('title', Q.like(`%${text}%`))) .fetch();

8. Q.sanitizeLikeString

Pour gérer les entrées utilisateurs, vous ne devez pas utiliser directement Q.like ou Q.notLike dans vos requêtes, utilisez les couplé à Q.sanitizeLikeString, pour les rendre safe.

const posts = await database .get<Post>('posts') .query(Q.where('title', Q.like(`%${Q.sanitizeLikeString(text)}%`))) .fetch();

9. G.includes

A le même effet que Q.like, mais est sensible à la casse.

const posts = await database .get<Post>('posts') .query(Q.where('title'.toLowerCase(), Q.includes(text))) .fetch();

10. Les requêtes multiples avec Q.and et Q.or

Nous pourrons combiner des requêtes en utilisant Q.and et Q.or.

Par exemple :

const posts = await database .get<Post>('posts') .query(Q.or(Q.where('likes', Q.gt(60)), Q.where('is_pinned', true))) .fetch();

Si nous enchaînons uniquement des and, nous n'avons pas besoin de le spécifier :

const posts = await database .get<Post>('posts') .query(Q.where('likes', Q.gte(60)), Q.where('is_pinned', true)) .fetch();

11. Allez plus loin avec les query API

Documentation officielle des query API