Guides Pratiques

Requêtes dépendantes

Utiliser QoraOptions.dependsOn pour chaîner les requêtes de sorte qu'une ne se déclenche qu'après la résolution d'une autre.

Une requête dépendante ne se déclenche qu'après qu'une autre requête ait chargé ses données avec succès. C'est le pattern pour la récupération de données séquentielle : charger d'abord la session, puis le profil utilisateur ; charger un projet, puis ses membres.


dependsOn

Définir QoraOptions.dependsOn à la clé de la requête prérequise. Qora s'abonne en interne et déclenche le fetch dépendant quand les données deviennent disponibles.

main.dart
// Étape 1 : récupérer la session
client.watchQuery<Session>(
  key: ['session'],
  fetcher: () => api.getSession(),
);

// Étape 2 : se déclenche automatiquement une fois que ['session'] a des données
client.watchQuery<User>(
  key: ['user'],
  fetcher: () => api.getUser(session!.userId),
  options: QoraOptions(dependsOn: ['session']),
);

Comportement par API

APIComportement quand la dépendance n'est pas résolue
watchQueryS'abonne de façon réactive ; se déclenche quand la dépendance atteint Success
fetchQueryLève StateError immédiatement. Appeler après la résolution de la dépendance.
prefetchIgnore silencieusement. Sûr à appeler de façon spéculative.

Dans Flutter : QoraBuilder

Le pattern Flutter le plus propre est d'imbriquer un QoraBuilder pour la requête dépendante dans le cas success du parent :

profile_screen.dart
QoraBuilder<Session>(
  queryKey: ['session'],
  fetcher: () => api.getSession(),
  builder: (context, sessionState, refetch) => switch (sessionState) {
    Loading() || Initial() => const CircularProgressIndicator(),
    Failure(:final error) => ErrorWidget('$error'),
    Success(:final data) => QoraBuilder<User>(
      queryKey: ['user', data.userId],
      fetcher: () => api.getUser(data.userId),
      builder: (context, userState, _) => switch (userState) {
        Success(:final data) => ProfileCard(data),
        Loading() => const CircularProgressIndicator(),
        Failure(:final error) => ErrorWidget('$error'),
        Initial() => const SizedBox.shrink(),
      },
    ),
  },
)

Le QoraBuilder interne ne se monte que quand la session est prête, donc le fetch dépendant ne se déclenche jamais prématurément.


Utiliser dependsOn avec watchQuery

Quand les deux requêtes doivent être actives simultanément (ex. dans une couche repository sans Flutter), utiliser dependsOn :

user_repository.dart
class UserRepository {
  final QoraClient _client;

  Stream<QoraState<User>> watchCurrentUser() {
    // S'assurer que la requête de session est en cours
    _client.watchQuery<Session>(
      key: ['session'],
      fetcher: () => api.getSession(),
    );

    // Cette requête attend que ['session'] ait des données avant de fetcher
    return _client.watchQuery<User>(
      key: ['user'],
      fetcher: () async {
        final session = _client.getQueryData<Session>(['session'])!;
        return api.getUser(session.userId);
      },
      options: const QoraOptions(dependsOn: ['session']),
    );
  }
}

Chaîner plusieurs dépendances

Une requête ne peut déclarer qu'un seul dependsOn. Pour une chaîne de trois requêtes, imbriquer le dependsOn à chaque étape :

main.dart
// 1 : session
client.watchQuery<Session>(key: ['session'], fetcher: () => api.getSession());

// 2 : user (dépend de session)
client.watchQuery<User>(
  key: ['user'],
  fetcher: () => api.getUser(session!.userId),
  options: const QoraOptions(dependsOn: ['session']),
);

// 3 : projects (dépend de user)
client.watchQuery<List<Project>>(
  key: ['projects'],
  fetcher: () => api.getProjects(user!.orgId),
  options: const QoraOptions(dependsOn: ['user']),
);

fetchQuery et dépendances

fetchQuery lève une exception immédiatement si la dépendance n'est pas résolue. L'utiliser uniquement après avoir vérifié que la dépendance a des données :

main.dart
// Sûr uniquement une fois que ['session'] est à l'état Success
final user = await client.fetchQuery<User>(
  key: ['user'],
  fetcher: () => api.getUser(session!.userId),
  options: QoraOptions(dependsOn: ['session']),
);

Pour le code réactif, préférer watchQuery : il gère automatiquement le timing.


Voir aussi

Copyright © 2026