[{"data":1,"prerenderedAt":1480},["ShallowReactive",2],{"navigation_docs_fr":3,"-fr-help-faq":342,"-fr-help-faq-surround":1475},[4,45,91,137,195,236,257,291,327],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Prise en main","i-lucide-rocket","/fr/getting-started","fr/01.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Qu'est-ce que Qora ?","/fr/getting-started/what-is-qora","fr/01.getting-started/2.what-is-qora","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Installation","/fr/getting-started/installation","fr/01.getting-started/3.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":6},"Démarrage rapide","/fr/getting-started/quick-start","fr/01.getting-started/4.quick-start",{"title":25,"path":26,"stem":27,"icon":28},"Comparaison","/fr/getting-started/comparison","fr/01.getting-started/5.comparison","i-lucide-scale",{"title":30,"path":31,"stem":32,"icon":33},"Venant de TanStack Query","/fr/getting-started/coming-from-tanstack-query","fr/01.getting-started/6.coming-from-tanstack-query","i-lucide-arrow-left-right",{"title":35,"path":36,"stem":37,"icon":38},"Migrer depuis d'Autres Librairies","/fr/getting-started/migrating-from-other-libraries","fr/01.getting-started/7.migrating-from-other-libraries","i-lucide-arrow-right-left",{"title":40,"path":41,"stem":42,"icon":43},"Assistants IA","/fr/getting-started/ai-assistants","fr/01.getting-started/8.ai-assistants","i-lucide-sparkles",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"Concepts clés","i-lucide-book-open","/fr/core-concepts","fr/02.core-concepts",[51,56,61,66,71,76,81,86],{"title":52,"path":53,"stem":54,"icon":55},"Requêtes","/fr/core-concepts/queries","fr/02.core-concepts/1.queries","i-lucide-database",{"title":57,"path":58,"stem":59,"icon":60},"Clés de requête","/fr/core-concepts/query-keys","fr/02.core-concepts/2.query-keys","i-lucide-key-round",{"title":62,"path":63,"stem":64,"icon":65},"États des requêtes","/fr/core-concepts/query-states","fr/02.core-concepts/3.query-states","i-lucide-activity",{"title":67,"path":68,"stem":69,"icon":70},"Cache","/fr/core-concepts/caching","fr/02.core-concepts/4.caching","i-lucide-layers-3",{"title":72,"path":73,"stem":74,"icon":75},"Stale-While-Revalidate","/fr/core-concepts/stale-while-revalidate","fr/02.core-concepts/5.stale-while-revalidate","i-lucide-timer-reset",{"title":77,"path":78,"stem":79,"icon":80},"Déduplication","/fr/core-concepts/deduplication","fr/02.core-concepts/6.deduplication","i-lucide-copy-minus",{"title":82,"path":83,"stem":84,"icon":85},"Mutations et invalidation","/fr/core-concepts/mutations","fr/02.core-concepts/7.mutations","i-lucide-pencil-line",{"title":87,"path":88,"stem":89,"icon":90},"Hors-ligne et réseau","/fr/core-concepts/offline","fr/02.core-concepts/8.offline","i-lucide-wifi-off",{"title":92,"icon":93,"path":94,"stem":95,"children":96,"page":44},"Usage avec Flutter","i-lucide-smartphone","/fr/flutter-integration","fr/03.flutter-integration",[97,102,107,112,117,122,127,132],{"title":98,"path":99,"stem":100,"icon":101},"Configuration","/fr/flutter-integration/setup","fr/03.flutter-integration/1.setup","i-lucide-wrench",{"title":103,"path":104,"stem":105,"icon":106},"QoraScope","/fr/flutter-integration/qora-scope","fr/03.flutter-integration/2.qora-scope","i-lucide-share-2",{"title":108,"path":109,"stem":110,"icon":111},"QoraBuilder","/fr/flutter-integration/qora-builder","fr/03.flutter-integration/3.qora-builder","i-lucide-blocks",{"title":113,"path":114,"stem":115,"icon":116},"QoraMutationBuilder","/fr/flutter-integration/qora-mutation-builder","fr/03.flutter-integration/4.qora-mutation-builder","i-lucide-pencil",{"title":118,"path":119,"stem":120,"icon":121},"InfiniteQueryBuilder","/fr/flutter-integration/infinite-query-builder","fr/03.flutter-integration/5.infinite-query-builder","i-lucide-infinity",{"title":123,"path":124,"stem":125,"icon":126},"Hooks (flutter_hooks)","/fr/flutter-integration/hooks","fr/03.flutter-integration/6.hooks","i-lucide-anchor",{"title":128,"path":129,"stem":130,"icon":131},"Widgets de statut réseau","/fr/flutter-integration/network-status","fr/03.flutter-integration/7.network-status","i-lucide-wifi",{"title":133,"path":134,"stem":135,"icon":136},"Bonnes pratiques","/fr/flutter-integration/best-practices","fr/03.flutter-integration/8.best-practices","i-lucide-badge-check",{"title":138,"icon":139,"path":140,"stem":141,"children":142,"page":44},"Guides Pratiques","i-lucide-chef-hat","/fr/recipes","fr/04.recipes",[143,147,152,157,162,166,171,176,181,186,191],{"title":144,"path":145,"stem":146,"icon":85},"Mutations","/fr/recipes/mutations","fr/04.recipes/02.mutations",{"title":148,"path":149,"stem":150,"icon":151},"Mises à jour optimistes","/fr/recipes/optimistic-updates","fr/04.recipes/03.optimistic-updates","i-lucide-zap",{"title":153,"path":154,"stem":155,"icon":156},"Persistance","/fr/recipes/persistence","fr/04.recipes/04.persistence","i-lucide-hard-drive",{"title":158,"path":159,"stem":160,"icon":161},"Réseau adaptatif","/fr/recipes/network-aware","fr/04.recipes/05.network-aware","i-lucide-signal",{"title":163,"path":164,"stem":165,"icon":121},"Requêtes infinies","/fr/recipes/infinite-queries","fr/04.recipes/06.infinite-queries",{"title":167,"path":168,"stem":169,"icon":170},"Requêtes dépendantes","/fr/recipes/dependent-queries","fr/04.recipes/07.dependent-queries","i-lucide-link-2",{"title":172,"path":173,"stem":174,"icon":175},"Annulation","/fr/recipes/cancel-token","fr/04.recipes/08.cancel-token","i-lucide-circle-slash",{"title":177,"path":178,"stem":179,"icon":180},"Hydratation SSR","/fr/recipes/ssr-hydration","fr/04.recipes/09.ssr-hydration","i-lucide-server",{"title":182,"path":183,"stem":184,"icon":185},"Gestion des erreurs","/fr/recipes/error-handling","fr/04.recipes/10.error-handling","i-lucide-shield-alert",{"title":187,"path":188,"stem":189,"icon":190},"Tests","/fr/recipes/testing","fr/04.recipes/11.testing","i-lucide-flask-conical",{"title":192,"path":193,"stem":194},"Prefetch au Niveau des Routes","/fr/recipes/prefetch","fr/04.recipes/12.prefetch",{"title":196,"icon":197,"path":198,"stem":199,"children":200,"page":44},"Référence de l'API","i-lucide-file-code","/fr/api-reference","fr/05.api-reference",[201,206,210,214,219,224,228,232],{"title":202,"path":203,"stem":204,"icon":205},"QoraClient","/fr/api-reference/qora-client","fr/05.api-reference/1.qora-client","i-lucide-cpu",{"title":207,"path":208,"stem":209,"icon":60},"QoraKey","/fr/api-reference/qora-key","fr/05.api-reference/2.qora-key",{"title":211,"path":212,"stem":213,"icon":65},"QoraState","/fr/api-reference/qora-state","fr/05.api-reference/3.qora-state",{"title":215,"path":216,"stem":217,"icon":218},"QoraOptions","/fr/api-reference/qora-options","fr/05.api-reference/4.qora-options","i-lucide-sliders-horizontal",{"title":220,"path":221,"stem":222,"icon":223},"QoraClientConfig","/fr/api-reference/qora-client-config","fr/05.api-reference/5.qora-client-config","i-lucide-settings-2",{"title":225,"path":226,"stem":227,"icon":85},"API Mutation","/fr/api-reference/qora-mutation","fr/05.api-reference/6.qora-mutation",{"title":229,"path":230,"stem":231,"icon":156},"PersistQoraClient","/fr/api-reference/persist-qora-client","fr/05.api-reference/7.persist-qora-client",{"title":233,"path":234,"stem":235,"icon":121},"Requête infinie","/fr/api-reference/infinite-query","fr/05.api-reference/8.infinite-query",{"title":237,"icon":238,"path":239,"stem":240,"children":241,"page":44},"Outils de debug","i-lucide-bug","/fr/devtools","fr/06.devtools",[242,247,252],{"title":243,"path":244,"stem":245,"icon":246},"Vue d'ensemble","/fr/devtools/overview","fr/06.devtools/1.overview","i-lucide-layout-dashboard",{"title":248,"path":249,"stem":250,"icon":251},"Overlay intégré","/fr/devtools/overlay","fr/06.devtools/2.overlay","i-lucide-layers",{"title":253,"path":254,"stem":255,"icon":256},"Sérialisation des données","/fr/devtools/data-display","fr/06.devtools/4.data-display","i-lucide-eye",{"title":258,"icon":259,"path":260,"stem":261,"children":262,"page":44},"Intégrations tierces","i-lucide-puzzle","/fr/third-party","fr/07.third-party",[263,268,272,277,282,286],{"title":264,"path":265,"stem":266,"icon":267},"Avec Provider","/fr/third-party/with-provider","fr/07.third-party/1.with-provider","i-lucide-plug",{"title":269,"path":270,"stem":271,"icon":111},"Avec BLoC","/fr/third-party/with-bloc","fr/07.third-party/2.with-bloc",{"title":273,"path":274,"stem":275,"icon":276},"Avec Riverpod","/fr/third-party/with-riverpod","fr/07.third-party/3.with-riverpod","i-lucide-droplets",{"title":278,"path":279,"stem":280,"icon":281},"Avec RxDart","/fr/third-party/with-rxdart","fr/07.third-party/4.with-rxdart","i-lucide-git-branch",{"title":283,"path":284,"stem":285},"Avec Dio","/fr/third-party/with-dio","fr/07.third-party/5.with-dio",{"title":287,"path":288,"stem":289,"icon":290},"Avec GraphQL","/fr/third-party/with-graphql","fr/07.third-party/6.with-graphql","i-lucide-binary",{"title":292,"icon":190,"path":293,"stem":294,"children":295,"page":44},"Exemples","/fr/examples","fr/08.examples",[296,301,305,310,314,318,322],{"title":297,"path":298,"stem":299,"icon":300},"Étude de cas : Liste et détail utilisateur","/fr/examples/basic-query","fr/08.examples/1.basic-query","i-lucide-play-circle",{"title":302,"path":303,"stem":304,"icon":151},"Étude de cas : Mutations optimistes et rollback","/fr/examples/mutations-optimistic","fr/08.examples/2.mutations-optimistic",{"title":306,"path":307,"stem":308,"icon":309},"Étude de cas : Feed à défilement infini","/fr/examples/infinite-scroll","fr/08.examples/3.infinite-scroll","i-lucide-scroll",{"title":311,"path":312,"stem":313,"icon":90},"Étude de cas : Application Todo offline-first","/fr/examples/offline-first","fr/08.examples/4.offline-first",{"title":315,"path":316,"stem":317,"icon":161},"Étude de cas : Conscience réseau","/fr/examples/network-awareness","fr/08.examples/5.network-awareness",{"title":319,"path":320,"stem":321,"icon":126},"Étude de cas : Intégration des hooks","/fr/examples/hooks-integration","fr/08.examples/6.hooks-integration",{"title":323,"path":324,"stem":325,"icon":326},"Étude de cas : Application Todo complète","/fr/examples/complete-todo-app","fr/08.examples/7.complete-todo-app","i-lucide-check-square",{"title":328,"icon":329,"path":330,"stem":331,"children":332,"page":44},"Aide","i-lucide-life-buoy","/fr/help","fr/09.help",[333,338],{"title":334,"path":335,"stem":336,"icon":337},"FAQ","/fr/help/faq","fr/09.help/1.faq","i-lucide-circle-help",{"title":339,"path":340,"stem":341,"icon":101},"Dépannage","/fr/help/troubleshooting","fr/09.help/2.troubleshooting",{"id":343,"title":334,"body":344,"description":1468,"extension":1469,"links":1470,"meta":1471,"navigation":1472,"path":335,"seo":1473,"stem":336,"__hash__":1474},"docs_fr/fr/09.help/1.faq.md",{"type":345,"value":346,"toc":1420},"minimark",[347,352,366,377,390,393,402,416,446,455,457,466,482,526,528,540,546,556,569,572,574,582,587,601,603,611,639,641,645,654,662,675,682,684,691,704,724,726,734,755,757,761,769,781,794,796,800,815,1032,1038,1040,1050,1059,1062,1073,1075,1079,1098,1120,1122,1125,1136,1152,1155,1243,1245,1253,1277,1286,1288,1291,1300,1320,1336,1338,1345,1359,1361,1365,1369,1376,1379,1381,1385,1416],[348,349,351],"h2",{"id":350},"api-principale","API principale",[353,354,356,357,361,362,365],"h3",{"id":355},"quelle-est-la-différence-entre-fetchquery-et-watchquery","Quelle est la différence entre ",[358,359,360],"code",{},"fetchQuery"," et ",[358,363,364],{},"watchQuery"," ?",[367,368,369,372,373,376],"p",{},[358,370,371],{},"fetchQuery\u003CT>"," exécute un fetch unique et retourne un ",[358,374,375],{},"Future\u003CT>",". Il ne s'abonne pas aux changements d'état.",[367,378,379,382,383,386,387,389],{},[358,380,381],{},"watchQuery\u003CT>"," retourne un ",[358,384,385],{},"Stream\u003CQoraState\u003CT>>"," qui émet à chaque transition d'état. Il déclenche un fetch au premier abonnement et gère automatiquement stale-while-revalidate, la déduplication et les événements de cycle de vie. Utiliser ",[358,388,364],{}," dès qu'un widget doit refléter l'état live du cache.",[391,392],"hr",{},[353,394,356,396,361,399,365],{"id":395},"quelle-est-la-différence-entre-getquerydata-et-getquerystate",[358,397,398],{},"getQueryData",[358,400,401],{},"getQueryState",[367,403,404,407,408,411,412,415],{},[358,405,406],{},"getQueryData\u003CT>(key)"," retourne ",[358,409,410],{},"T?"," : la valeur de données brute de l'entrée de cache courante, ou ",[358,413,414],{},"null"," si aucune donnée n'est disponible.",[367,417,418,407,421,424,425,428,429,428,432,428,435,438,439,361,442,445],{},[358,419,420],{},"getQueryState\u003CT>(key)",[358,422,423],{},"QoraState\u003CT>"," : l'état sealed complet incluant le variant (",[358,426,427],{},"Initial",", ",[358,430,431],{},"Loading",[358,433,434],{},"Success",[358,436,437],{},"Failure",") et tous les champs associés tels que ",[358,440,441],{},"updatedAt",[358,443,444],{},"previousData",".",[367,447,448,449,451,452,454],{},"Utiliser ",[358,450,398],{}," quand seule la valeur de données est nécessaire (par exemple, pour un snapshot avant une écriture optimiste). Utiliser ",[358,453,401],{}," quand l'état complet est requis pour l'affichage ou la logique de branchement.",[391,456],{},[353,458,356,460,361,463,365],{"id":459},"quelle-est-la-différence-entre-restorequerydata-et-setquerydata",[358,461,462],{},"restoreQueryData",[358,464,465],{},"setQueryData",[367,467,468,471,472,475,476,478,479,445],{},[358,469,470],{},"setQueryData\u003CT>(key, T data)"," requiert un ",[358,473,474],{},"T"," non-null. Il produit toujours un état ",[358,477,434],{}," avec ",[358,480,481],{},"updatedAt: DateTime.now()",[367,483,484,487,488,490,491,494,495,497,498,501,502,490,504,506,507,510,511,513,514,516,517,519,520,522,523,525],{},[358,485,486],{},"restoreQueryData\u003CT>(key, T? data)"," accepte ",[358,489,410],{},". Quand ",[358,492,493],{},"data"," est ",[358,496,414],{},", il appelle ",[358,499,500],{},"removeQuery(key)",", ce qui restaure l'état ",[358,503,427],{},[358,505,493],{}," est non-null, il appelle ",[358,508,509],{},"setQueryData(key, data)",". ",[358,512,462],{}," est le choix correct pour le rollback : le snapshot retourné par ",[358,515,398],{}," peut être ",[358,518,414],{}," s'il n'y avait pas de données précédentes, et passer ce ",[358,521,414],{}," à ",[358,524,462],{}," supprime proprement l'entrée optimiste.",[391,527],{},[353,529,356,531,428,534,361,537,365],{"id":530},"quelle-est-la-différence-entre-invalidate-invalidatewhere-et-invalidatequeries",[358,532,533],{},"invalidate",[358,535,536],{},"invalidateWhere",[358,538,539],{},"invalidateQueries",[367,541,542,545],{},[358,543,544],{},"invalidate(key)"," marque une clé spécifique comme périmée.",[367,547,548,551,552,555],{},[358,549,550],{},"invalidateWhere(bool Function(List\u003Cdynamic> key) predicate)"," marque comme périmée chaque clé en cache satisfaisant le prédicat. Permet d'invalider une famille de clés liées en un seul appel (par exemple, toutes les clés commençant par ",[358,553,554],{},"'users'",").",[367,557,558,561,562,564,565,568],{},[358,559,560],{},"invalidateQueries({required QueryFilter filter})"," est l'équivalent typé de ",[358,563,536],{},", acceptant un objet ",[358,566,567],{},"QueryFilter"," plutôt qu'un prédicat brut.",[367,570,571],{},"Les trois déclenchent un refetch en arrière-plan pour chaque abonné actuellement actif sur les clés affectées.",[391,573],{},[353,575,356,577,361,580,365],{"id":576},"quelle-est-la-différence-entre-removequery-et-invalidate",[358,578,579],{},"removeQuery",[358,581,533],{},[367,583,584,586],{},[358,585,544],{}," marque l'entrée comme périmée et déclenche un refetch en arrière-plan pour les abonnés actifs. L'entrée reste dans le cache.",[367,588,589,591,592,594,595,597,598,445],{},[358,590,500],{}," supprime entièrement l'entrée du cache. Les abonnés actifs transitent vers ",[358,593,427],{},". Sur ",[358,596,229],{},", il supprime également l'entrée persistée depuis ",[358,599,600],{},"StorageAdapter",[391,602],{},[353,604,606,607,610],{"id":605},"quest-ce-que-qorastatus-et-quand-lutiliser-à-la-place-de-la-classe-sealed","Qu'est-ce que ",[358,608,609],{},"QoraStatus"," et quand l'utiliser à la place de la classe sealed ?",[367,612,613,615,616,619,620,623,624,627,628,428,630,428,633,635,636,638],{},[358,614,609],{}," est un enum simple (",[358,617,618],{},"initial | loading | success | error",") accessible via ",[358,621,622],{},"state.status",". Il est utile quand la logique de branchement n'a pas besoin d'accéder aux champs associés de l'état (par exemple, basculer un spinner via ",[358,625,626],{},"state.status.isLoading","). Quand ",[358,629,493],{},[358,631,632],{},"error",[358,634,444],{}," ou ",[358,637,441],{}," sont nécessaires, pattern-matcher directement la classe sealed.",[391,640],{},[348,642,644],{"id":643},"sémantique-du-cache","Sémantique du cache",[353,646,356,648,361,651,365],{"id":647},"quelle-est-la-différence-entre-staletime-et-gctime",[358,649,650],{},"staleTime",[358,652,653],{},"gcTime",[367,655,656,658,659,661],{},[358,657,650],{}," contrôle la fraîcheur. Les données dans la fenêtre de fraîcheur sont servies depuis le cache sans appel réseau. Après expiration de ",[358,660,650],{},", les données sont toujours servies depuis le cache, mais une revalidation en arrière-plan est déclenchée simultanément (stale-while-revalidate).",[367,663,664,666,667,669,670,672,673,445],{},[358,665,653],{}," contrôle l'éviction. Quand le dernier abonné ",[358,668,364],{}," se désabonne, un timer GC est démarré. Si aucun nouvel abonné ne s'attache avant l'expiration de ",[358,671,653],{},", l'entrée est supprimée du cache. Le prochain accès repart de ",[358,674,427],{},[367,676,677,678,681],{},"Configuration courante : ",[358,679,680],{},"staleTime \u003C gcTime",". Les données deviennent périmées et déclenchent une revalidation en arrière-plan, mais l'entrée survit suffisamment longtemps pour que la navigation retour vers un écran soit instantanée.",[391,683],{},[353,685,687,688,690],{"id":686},"quand-qorabuilder-refetch-il-au-montage","Quand ",[358,689,108],{}," refetch-il au montage ?",[367,692,693,694,697,698,700,701,703],{},"Par défaut (",[358,695,696],{},"refetchOnMount: true"," au niveau ",[358,699,220],{},"), ",[358,702,364],{}," déclenche un fetch au premier abonnement quel que soit l'état du cache existant.",[367,705,687,706,709,710,712,713,700,715,717,718,720,721,723],{},[358,707,708],{},"refetchOnMount: false"," (défini par requête via ",[358,711,215],{}," ou globalement via ",[358,714,220],{},[358,716,364],{}," ne fetche que si l'entrée est dans l'état ",[358,719,427],{},". Si un état en cache existe, y compris un ",[358,722,434],{}," périmé, aucun fetch n'est déclenché au montage.",[391,725],{},[353,727,729,730,733],{"id":728},"que-se-passe-t-il-quand-maxcachesize-est-atteint","Que se passe-t-il quand ",[358,731,732],{},"maxCacheSize"," est atteint ?",[367,735,736,737,739,740,744,745,747,748,751,752,754],{},"Quand le cache atteint ",[358,738,732],{},", Qora évince l'entrée ",[741,742,743],"strong",{},"inactive"," la moins récemment utilisée (une entrée sans abonné ",[358,746,364],{}," actif). Les entrées actives ne sont jamais évincées par la pression LRU. Le callback ",[358,749,750],{},"onCacheEvict"," dans ",[358,753,220],{}," est invoqué pour chaque entrée évincée.",[391,756],{},[348,758,760],{"id":759},"intégration-flutter","Intégration Flutter",[353,762,356,764,361,766,365],{"id":763},"quelle-est-la-différence-entre-qorabuilder-et-qorastatebuilder",[358,765,108],{},[358,767,768],{},"QoraStateBuilder",[367,770,771,774,775,777,778,445],{},[358,772,773],{},"QoraBuilder\u003CT>"," appelle ",[358,776,364],{}," au montage, ce qui déclenche un fetch et s'abonne aux changements d'état. Il prend un builder à 3 paramètres : ",[358,779,780],{},"Widget Function(BuildContext, QoraState\u003CT>, FetchStatus)",[367,782,783,774,786,789,790,793],{},[358,784,785],{},"QoraStateBuilder\u003CT>",[358,787,788],{},"watchState"," à la place. Il observe l'état du cache existant sans jamais déclencher de fetch. Il prend un builder à 2 paramètres : ",[358,791,792],{},"Widget Function(BuildContext, QoraState\u003CT>)",". A utiliser quand un autre widget est propriétaire du cycle de vie du fetch et que ce widget doit uniquement afficher le résultat.",[391,795],{},[353,797,799],{"id":798},"comment-obtenir-un-indicateur-de-chargement-global","Comment obtenir un indicateur de chargement global ?",[367,801,802,803,806,807,810,811,814],{},"Avec ",[358,804,805],{},"qora_hooks",", utiliser ",[358,808,809],{},"useIsFetching()",". Retourne ",[358,812,813],{},"true"," tant qu'une requête a une demande en vol et ne rebuild que lors du franchissement de la frontière zéro :",[816,817,823],"pre",{"className":818,"code":819,"filename":820,"language":821,"meta":822,"style":822},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","class AppProgressBar extends HookWidget {\n  const AppProgressBar({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    final isFetching = useIsFetching();\n    return AnimatedOpacity(\n      opacity: isFetching ? 1.0 : 0.0,\n      duration: const Duration(milliseconds: 250),\n      child: const LinearProgressIndicator(minHeight: 2),\n    );\n  }\n}\n","lib/shared/widgets/app_progress_bar.dart","dart","",[358,824,825,848,868,875,881,900,920,933,960,987,1012,1020,1026],{"__ignoreMap":822},[826,827,830,834,838,841,844],"span",{"class":828,"line":829},"line",1,[826,831,833],{"class":832},"sMK4o","class",[826,835,837],{"class":836},"sBMFI"," AppProgressBar",[826,839,840],{"class":832}," extends",[826,842,843],{"class":836}," HookWidget",[826,845,847],{"class":846},"sTEyZ"," {\n",[826,849,851,855,857,860,862,865],{"class":828,"line":850},2,[826,852,854],{"class":853},"spNyl","  const",[826,856,837],{"class":836},[826,858,859],{"class":846},"({super",[826,861,445],{"class":832},[826,863,864],{"class":846},"key})",[826,866,867],{"class":832},";\n",[826,869,871],{"class":828,"line":870},3,[826,872,874],{"emptyLinePlaceholder":873},true,"\n",[826,876,878],{"class":828,"line":877},4,[826,879,880],{"class":853},"  @override\n",[826,882,884,887,891,894,897],{"class":828,"line":883},5,[826,885,886],{"class":836},"  Widget",[826,888,890],{"class":889},"s2Zo4"," build",[826,892,893],{"class":846},"(",[826,895,896],{"class":836},"BuildContext",[826,898,899],{"class":846}," context) {\n",[826,901,903,906,909,912,915,918],{"class":828,"line":902},6,[826,904,905],{"class":853},"    final",[826,907,908],{"class":846}," isFetching ",[826,910,911],{"class":832},"=",[826,913,914],{"class":889}," useIsFetching",[826,916,917],{"class":846},"()",[826,919,867],{"class":832},[826,921,923,927,930],{"class":828,"line":922},7,[826,924,926],{"class":925},"s7zQu","    return",[826,928,929],{"class":836}," AnimatedOpacity",[826,931,932],{"class":846},"(\n",[826,934,936,939,942,944,947,951,954,957],{"class":828,"line":935},8,[826,937,938],{"class":846},"      opacity",[826,940,941],{"class":832},":",[826,943,908],{"class":846},[826,945,946],{"class":832},"?",[826,948,950],{"class":949},"sbssI"," 1.0",[826,952,953],{"class":832}," :",[826,955,956],{"class":949}," 0.0",[826,958,959],{"class":832},",\n",[826,961,963,966,968,971,974,977,979,982,985],{"class":828,"line":962},9,[826,964,965],{"class":846},"      duration",[826,967,941],{"class":832},[826,969,970],{"class":853}," const",[826,972,973],{"class":836}," Duration",[826,975,976],{"class":846},"(milliseconds",[826,978,941],{"class":832},[826,980,981],{"class":949}," 250",[826,983,984],{"class":846},")",[826,986,959],{"class":832},[826,988,990,993,995,997,1000,1003,1005,1008,1010],{"class":828,"line":989},10,[826,991,992],{"class":846},"      child",[826,994,941],{"class":832},[826,996,970],{"class":853},[826,998,999],{"class":836}," LinearProgressIndicator",[826,1001,1002],{"class":846},"(minHeight",[826,1004,941],{"class":832},[826,1006,1007],{"class":949}," 2",[826,1009,984],{"class":846},[826,1011,959],{"class":832},[826,1013,1015,1018],{"class":828,"line":1014},11,[826,1016,1017],{"class":846},"    )",[826,1019,867],{"class":832},[826,1021,1023],{"class":828,"line":1022},12,[826,1024,1025],{"class":846},"  }\n",[826,1027,1029],{"class":828,"line":1028},13,[826,1030,1031],{"class":846},"}\n",[367,1033,1034,1035,445],{},"Sans hooks, s'abonner directement à ",[358,1036,1037],{},"client.fetchingCountStream",[391,1039],{},[353,1041,1043,361,1046,1049],{"id":1042},"flutterlifecyclemanager-et-flutterconnectivitymanager-sont-ils-obligatoires",[358,1044,1045],{},"FlutterLifecycleManager",[358,1047,1048],{},"FlutterConnectivityManager"," sont-ils obligatoires ?",[367,1051,1052,1053,1055,1056,1058],{},"Les deux sont optionnels. Sans ",[358,1054,1045],{},", les requêtes ne refetchent pas quand l'app revient au premier plan. Sans ",[358,1057,1048],{},", les requêtes ne se mettent pas en pause hors ligne et ne rejouent pas à la reconnexion : tous les fetches s'exécutent toujours quel que soit l'état de la connectivité.",[367,1060,1061],{},"Pour les apps avec support hors ligne, fournir les deux. Pour les apps dans des environnements contrôlés (tableaux de bord, outils internes), les omettre est acceptable.",[367,1063,1064,1066,1067,1069,1070,445],{},[358,1065,1048],{}," ne prend aucun paramètre de constructeur. ",[358,1068,1045],{}," requiert ",[358,1071,1072],{},"qoraClient: client",[391,1074],{},[353,1076,1078],{"id":1077},"peut-on-utiliser-qora-sans-flutter","Peut-on utiliser Qora sans Flutter ?",[367,1080,1081,1082,1085,1086,428,1088,428,1090,428,1092,361,1095,1097],{},"Oui. Le package ",[358,1083,1084],{},"qora"," est du Dart pur sans dépendance Flutter. ",[358,1087,202],{},[358,1089,211],{},[358,1091,215],{},[358,1093,1094],{},"MutationController",[358,1096,229],{}," sont tous disponibles dans les environnements non-Flutter (CLI Dart, côté serveur, tests).",[367,1099,1100,1101,1104,1105,428,1107,428,1109,428,1111,428,1113,428,1115,361,1117,445],{},"Le package ",[358,1102,1103],{},"qora_flutter"," ajoute ",[358,1106,103],{},[358,1108,108],{},[358,1110,113],{},[358,1112,118],{},[358,1114,1045],{},[358,1116,1048],{},[358,1118,1119],{},"NetworkStatusIndicator",[391,1121],{},[348,1123,153],{"id":1124},"persistance",[353,1126,1128,1129,1132,1133,365],{"id":1127},"faut-il-appeler-storageadapterinit-avant-hydrate","Faut-il appeler ",[358,1130,1131],{},"StorageAdapter.init()"," avant ",[358,1134,1135],{},"hydrate()",[367,1137,1138,1139,1132,1142,1145,1146,1132,1148,1151],{},"Oui. Appeler ",[358,1140,1141],{},"await storage.init()",[358,1143,1144],{},"await client.hydrate()",". Appeler ",[358,1147,1135],{},[358,1149,1150],{},"init()"," produit un comportement indéfini pour les adaptateurs qui ouvrent des handles de fichiers ou des connexions de base de données pendant l'initialisation.",[367,1153,1154],{},"Séquence de démarrage correcte :",[816,1156,1159],{"className":818,"code":1157,"filename":1158,"language":821,"meta":822,"style":822},"await storage.init();\nclient.registerSerializer\u003CUser>(userSerializer, name: 'User');\nawait client.hydrate();\nrunApp(...);\n","main.dart",[358,1160,1161,1178,1213,1229],{"__ignoreMap":822},[826,1162,1163,1166,1169,1171,1174,1176],{"class":828,"line":829},[826,1164,1165],{"class":925},"await",[826,1167,1168],{"class":846}," storage",[826,1170,445],{"class":832},[826,1172,1173],{"class":889},"init",[826,1175,917],{"class":846},[826,1177,867],{"class":832},[826,1179,1180,1183,1185,1188,1191,1194,1197,1200,1203,1205,1209,1211],{"class":828,"line":850},[826,1181,1182],{"class":846},"client",[826,1184,445],{"class":832},[826,1186,1187],{"class":889},"registerSerializer",[826,1189,1190],{"class":846},"\u003C",[826,1192,1193],{"class":836},"User",[826,1195,1196],{"class":846},">(userSerializer",[826,1198,1199],{"class":832},",",[826,1201,1202],{"class":846}," name",[826,1204,941],{"class":832},[826,1206,1208],{"class":1207},"sfazB"," 'User'",[826,1210,984],{"class":846},[826,1212,867],{"class":832},[826,1214,1215,1217,1220,1222,1225,1227],{"class":828,"line":870},[826,1216,1165],{"class":925},[826,1218,1219],{"class":846}," client",[826,1221,445],{"class":832},[826,1223,1224],{"class":889},"hydrate",[826,1226,917],{"class":846},[826,1228,867],{"class":832},[826,1230,1231,1234,1236,1239,1241],{"class":828,"line":877},[826,1232,1233],{"class":889},"runApp",[826,1235,893],{"class":846},[826,1237,1238],{"class":832},"...",[826,1240,984],{"class":846},[826,1242,867],{"class":832},[391,1244],{},[353,1246,1248,1249,1252],{"id":1247},"pourquoi-le-name-du-sérialiseur-est-il-important","Pourquoi le ",[358,1250,1251],{},"name"," du sérialiseur est-il important ?",[367,1254,1255,1256,1258,1259,1261,1262,1265,1266,1268,1269,1272,1273,1276],{},"La chaîne ",[358,1257,1251],{}," est stockée avec chaque entrée persistée comme discriminant de type. Lors de ",[358,1260,1135],{},", Qora l'utilise pour trouver le convertisseur ",[358,1263,1264],{},"fromJson"," correct. Si ",[358,1267,1251],{}," est omis, il est défini par défaut à ",[358,1270,1271],{},"T.toString()",", qui est altéré par l'obfuscation Dart (",[358,1274,1275],{},"--obfuscate",") et la minification dans les builds Flutter Web.",[367,1278,1279,1280,1282,1283,1285],{},"Toujours passer un ",[358,1281,1251],{}," explicite pour les types persistés dans les builds release. Maintenir le ",[358,1284,1251],{}," stable entre les versions de l'app : le modifier invalide toutes les entrées précédemment persistées pour ce type.",[391,1287],{},[348,1289,144],{"id":1290},"mutations",[353,1292,1294,1295,635,1297,365],{"id":1293},"faut-il-utiliser-qoramutationbuilder-ou-usemutation","Faut-il utiliser ",[358,1296,113],{},[358,1298,1299],{},"useMutation",[367,1301,1302,1304,1305,635,1308,510,1311,1069,1313,1316,1317,1319],{},[358,1303,113],{}," fonctionne dans tout ",[358,1306,1307],{},"StatelessWidget",[358,1309,1310],{},"StatefulWidget",[358,1312,1299],{},[358,1314,1315],{},"HookWidget",". Les deux créent et disposent un ",[358,1318,1094],{}," lié au cycle de vie du widget.",[367,1321,1322,1323,1325,1326,1329,1330,428,1333,1335],{},"Sur les écrans combinant une requête et une mutation, ",[358,1324,1299],{}," aux côtés de ",[358,1327,1328],{},"useQuery"," évite les callbacks de builder imbriqués et réduit la profondeur d'indentation. Sur les écrans avec uniquement une mutation ou dans les bases de code n'utilisant pas ",[358,1331,1332],{},"flutter_hooks",[358,1334,113],{}," est le choix correct.",[391,1337],{},[353,1339,687,1341,1344],{"id":1340},"quand-onsuccess-sexécute-t-il-pour-les-mutations-mises-en-file-hors-ligne",[358,1342,1343],{},"onSuccess"," s'exécute-t-il pour les mutations mises en file hors ligne ?",[367,1346,1347,1349,1350,1353,1354,635,1356,1358],{},[358,1348,1343],{}," s'exécute uniquement quand la mutation se complète avec une vraie réponse serveur (",[358,1351,1352],{},"isOptimistic: false","). Il ne s'exécute pas quand une réponse optimiste est appliquée localement en mode hors ligne. Cela garantit que l'invalidation du cache via ",[358,1355,533],{},[358,1357,465],{}," n'a lieu qu'après confirmation de l'écriture par le serveur.",[391,1360],{},[348,1362,1364],{"id":1363},"devtools","DevTools",[353,1366,1368],{"id":1367},"quelle-surface-devtools-utiliser","Quelle surface DevTools utiliser ?",[367,1370,1371,1372,1375],{},"L'overlay in-app (",[358,1373,1374],{},"qora_devtools_overlay",") est stable et disponible. Il s'affiche à l'intérieur de l'app en cours d'exécution, et n'affiche rien en build release.",[367,1377,1378],{},"Une extension Flutter DevTools est en développement et n'est pas publiée. Utilisez l'overlay.",[391,1380],{},[353,1382,1384],{"id":1383},"pourquoi-loverlay-est-il-vide","Pourquoi l'overlay est-il vide ?",[367,1386,1387,1388,1391,1392,1395,1396,1399,1400,1403,1404,1407,1408,1411,1412,1415],{},"Vérifiez que l'application tourne en mode debug (",[358,1389,1390],{},"flutter run",", pas ",[358,1393,1394],{},"--release"," ni ",[358,1397,1398],{},"--profile",") : sinon l'overlay ne construit rien. Vérifiez ensuite que la ",[741,1401,1402],{},"même"," instance d'",[358,1405,1406],{},"OverlayTracker"," est passée à ",[358,1409,1410],{},"QoraClient(tracker: ...)"," et à ",[358,1413,1414],{},"QoraInspector(tracker: ...)",". Un client créé sans le tracker n'émet aucun événement.",[1417,1418,1419],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":822,"searchDepth":850,"depth":850,"links":1421},[1422,1436,1444,1452,1458,1464],{"id":350,"depth":850,"text":351,"children":1423},[1424,1426,1428,1430,1432,1434],{"id":355,"depth":870,"text":1425},"Quelle est la différence entre fetchQuery et watchQuery ?",{"id":395,"depth":870,"text":1427},"Quelle est la différence entre getQueryData et getQueryState ?",{"id":459,"depth":870,"text":1429},"Quelle est la différence entre restoreQueryData et setQueryData ?",{"id":530,"depth":870,"text":1431},"Quelle est la différence entre invalidate, invalidateWhere et invalidateQueries ?",{"id":576,"depth":870,"text":1433},"Quelle est la différence entre removeQuery et invalidate ?",{"id":605,"depth":870,"text":1435},"Qu'est-ce que QoraStatus et quand l'utiliser à la place de la classe sealed ?",{"id":643,"depth":850,"text":644,"children":1437},[1438,1440,1442],{"id":647,"depth":870,"text":1439},"Quelle est la différence entre staleTime et gcTime ?",{"id":686,"depth":870,"text":1441},"Quand QoraBuilder refetch-il au montage ?",{"id":728,"depth":870,"text":1443},"Que se passe-t-il quand maxCacheSize est atteint ?",{"id":759,"depth":850,"text":760,"children":1445},[1446,1448,1449,1451],{"id":763,"depth":870,"text":1447},"Quelle est la différence entre QoraBuilder et QoraStateBuilder ?",{"id":798,"depth":870,"text":799},{"id":1042,"depth":870,"text":1450},"FlutterLifecycleManager et FlutterConnectivityManager sont-ils obligatoires ?",{"id":1077,"depth":870,"text":1078},{"id":1124,"depth":850,"text":153,"children":1453},[1454,1456],{"id":1127,"depth":870,"text":1455},"Faut-il appeler StorageAdapter.init() avant hydrate() ?",{"id":1247,"depth":870,"text":1457},"Pourquoi le name du sérialiseur est-il important ?",{"id":1290,"depth":850,"text":144,"children":1459},[1460,1462],{"id":1293,"depth":870,"text":1461},"Faut-il utiliser QoraMutationBuilder ou useMutation ?",{"id":1340,"depth":870,"text":1463},"Quand onSuccess s'exécute-t-il pour les mutations mises en file hors ligne ?",{"id":1363,"depth":850,"text":1364,"children":1465},[1466,1467],{"id":1367,"depth":870,"text":1368},{"id":1383,"depth":870,"text":1384},"Réponses aux questions fréquentes sur l'API Qora, la sémantique du cache et l'intégration Flutter.","md",null,{},{"icon":337},{"title":334,"description":1468},"s8axE8gd7EkQEGvmvJIyFcS9oxtPJCH45MC4bZ9vqk8",[1476,1478],{"title":323,"path":324,"stem":325,"description":1477,"icon":326,"children":-1},"Une app Flutter de niveau production combinant toutes les capacités Qora : PersistQoraClient, défilement infini avec pagination, create/toggle/delete optimistes, file de mutations hors ligne et bascule de connectivité simulée.",{"title":339,"path":340,"stem":341,"description":1479,"icon":101,"children":-1},"Diagnostiquer et résoudre les problèmes courants de Qora, notamment les échecs de persistance, les requêtes bloquées, les refetches manquants et les abonnements répétés de widgets.",1794040411600]