[{"data":1,"prerenderedAt":2616},["ShallowReactive",2],{"navigation_docs_fr":3,"-fr-third-party-with-rxdart":342,"-fr-third-party-with-rxdart-surround":2611},[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":278,"body":344,"description":2604,"extension":2605,"links":2606,"meta":2607,"navigation":2608,"path":279,"seo":2609,"stem":280,"__hash__":2610},"docs_fr/fr/07.third-party/4.with-rxdart.md",{"type":345,"value":346,"toc":2587},"minimark",[347,351,364,367,370,373,420,422,426,431,917,921,1614,1616,1620,1624,1631,1825,1829,1835,1872,1879,1883,1889,1973,1976,1978,1982,2053,2057,2065,2229,2234,2236,2240,2246,2561,2576,2583],[348,349,243],"h2",{"id":350},"vue-densemble",[352,353,354,355,359,360,363],"p",{},"RxDart étend les streams Dart avec des opérateurs composables. Combiné à ",[356,357,358],"code",{},"QoraClient.watchQuery",", l'opérateur ",[356,361,362],{},"switchMap"," fournit un pattern déclaratif pour la commutation dynamique de clés de requête : l'abonnement actif est annulé atomiquement à chaque émission upstream, et un nouvel abonnement est ouvert pour la nouvelle clé.",[352,365,366],{},"Ce pattern remplace la gestion manuelle des abonnements dans les ViewModels et les notifiers d'état qui doivent répondre aux changements d'une valeur pilote (un ID sélectionné, un filtre, un index d'onglet).",[368,369],"hr",{},[348,371,98],{"id":372},"configuration",[374,375,381],"pre",{"className":376,"code":377,"filename":378,"language":379,"meta":380,"style":380},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","dependencies:\n  qora: ^1.3.1\n  rxdart: ^0.28.0\n","pubspec.yaml","yaml","",[356,382,383,396,409],{"__ignoreMap":380},[384,385,388,392],"span",{"class":386,"line":387},"line",1,[384,389,391],{"class":390},"swJcz","dependencies",[384,393,395],{"class":394},"sMK4o",":\n",[384,397,399,402,405],{"class":386,"line":398},2,[384,400,401],{"class":390},"  qora",[384,403,404],{"class":394},":",[384,406,408],{"class":407},"sfazB"," ^1.3.1\n",[384,410,412,415,417],{"class":386,"line":411},3,[384,413,414],{"class":390},"  rxdart",[384,416,404],{"class":394},[384,418,419],{"class":407}," ^0.28.0\n",[368,421],{},[348,423,425],{"id":424},"gestion-réactive-des-clés","Gestion réactive des clés",[427,428,430],"h3",{"id":429},"le-pattern","Le pattern",[374,432,437],{"className":433,"code":434,"filename":435,"language":436,"meta":380,"style":380},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import 'package:rxdart/rxdart.dart';\nimport 'package:qora/qora.dart';\n\nclass UserViewModel {\n  UserViewModel(this._client);\n\n  final QoraClient _client;\n\n  // Subject pilote: émet l'ID utilisateur actuellement sélectionné.\n  final _idSubject = BehaviorSubject\u003CString>.seeded('1');\n\n  // Stream dérivé: commute l'abonnement watchQuery actif à chaque\n  // nouvel ID. L'abonnement précédent est annulé avant l'ouverture du suivant.\n  late final Stream\u003CQoraState\u003CUser>> userState = _idSubject\n      .switchMap(\n        (id) => _client.watchQuery\u003CUser>(\n          key: ['users', id],\n          fetcher: () => api.getUser(id),\n          options: const QoraOptions(staleTime: Duration(minutes: 5)),\n        ),\n      )\n      .doOnData((state) {\n        // Les effets de bord s'exécutent après chaque émission d'état, avant le rebuild du widget.\n        if (state case Success(:final data)) {\n          analytics.track('user_loaded', {'id': data.id});\n        }\n      });\n\n  // Avancer le subject pilote. switchMap gère le reste.\n  void selectUser(String id) => _idSubject.add(id);\n\n  void dispose() => _idSubject.close();\n}\n","lib/features/user/user_view_model.dart","dart",[356,438,439,451,460,466,480,497,502,517,522,529,569,574,580,586,615,626,649,672,698,733,741,747,758,764,790,826,832,840,845,851,881,886,911],{"__ignoreMap":380},[384,440,441,445,448],{"class":386,"line":387},[384,442,444],{"class":443},"sbssI","import",[384,446,447],{"class":407}," 'package:rxdart/rxdart.dart'",[384,449,450],{"class":394},";\n",[384,452,453,455,458],{"class":386,"line":398},[384,454,444],{"class":443},[384,456,457],{"class":407}," 'package:qora/qora.dart'",[384,459,450],{"class":394},[384,461,462],{"class":386,"line":411},[384,463,465],{"emptyLinePlaceholder":464},true,"\n",[384,467,469,472,476],{"class":386,"line":468},4,[384,470,471],{"class":394},"class",[384,473,475],{"class":474},"sBMFI"," UserViewModel",[384,477,479],{"class":478},"sTEyZ"," {\n",[384,481,483,486,489,492,495],{"class":386,"line":482},5,[384,484,485],{"class":474},"  UserViewModel",[384,487,488],{"class":478},"(this",[384,490,491],{"class":394},".",[384,493,494],{"class":478},"_client)",[384,496,450],{"class":394},[384,498,500],{"class":386,"line":499},6,[384,501,465],{"emptyLinePlaceholder":464},[384,503,505,509,512,515],{"class":386,"line":504},7,[384,506,508],{"class":507},"spNyl","  final",[384,510,511],{"class":474}," QoraClient",[384,513,514],{"class":478}," _client",[384,516,450],{"class":394},[384,518,520],{"class":386,"line":519},8,[384,521,465],{"emptyLinePlaceholder":464},[384,523,525],{"class":386,"line":524},9,[384,526,528],{"class":527},"sHwdD","  // Subject pilote: émet l'ID utilisateur actuellement sélectionné.\n",[384,530,532,534,537,540,543,546,549,552,554,558,561,564,567],{"class":386,"line":531},10,[384,533,508],{"class":507},[384,535,536],{"class":478}," _idSubject ",[384,538,539],{"class":394},"=",[384,541,542],{"class":474}," BehaviorSubject",[384,544,545],{"class":478},"\u003C",[384,547,548],{"class":474},"String",[384,550,551],{"class":478},">",[384,553,491],{"class":394},[384,555,557],{"class":556},"s2Zo4","seeded",[384,559,560],{"class":478},"(",[384,562,563],{"class":407},"'1'",[384,565,566],{"class":478},")",[384,568,450],{"class":394},[384,570,572],{"class":386,"line":571},11,[384,573,465],{"emptyLinePlaceholder":464},[384,575,577],{"class":386,"line":576},12,[384,578,579],{"class":527},"  // Stream dérivé: commute l'abonnement watchQuery actif à chaque\n",[384,581,583],{"class":386,"line":582},13,[384,584,585],{"class":527},"  // nouvel ID. L'abonnement précédent est annulé avant l'ouverture du suivant.\n",[384,587,589,592,595,598,600,602,604,607,610,612],{"class":386,"line":588},14,[384,590,591],{"class":507},"  late",[384,593,594],{"class":507}," final",[384,596,597],{"class":474}," Stream",[384,599,545],{"class":478},[384,601,211],{"class":474},[384,603,545],{"class":478},[384,605,606],{"class":474},"User",[384,608,609],{"class":478},">> userState ",[384,611,539],{"class":394},[384,613,614],{"class":478}," _idSubject\n",[384,616,618,621,623],{"class":386,"line":617},15,[384,619,620],{"class":394},"      .",[384,622,362],{"class":556},[384,624,625],{"class":478},"(\n",[384,627,629,632,635,637,639,642,644,646],{"class":386,"line":628},16,[384,630,631],{"class":478},"        (id) ",[384,633,634],{"class":394},"=>",[384,636,514],{"class":478},[384,638,491],{"class":394},[384,640,641],{"class":556},"watchQuery",[384,643,545],{"class":478},[384,645,606],{"class":474},[384,647,648],{"class":478},">(\n",[384,650,652,655,657,660,663,666,669],{"class":386,"line":651},17,[384,653,654],{"class":478},"          key",[384,656,404],{"class":394},[384,658,659],{"class":478}," [",[384,661,662],{"class":407},"'users'",[384,664,665],{"class":394},",",[384,667,668],{"class":478}," id]",[384,670,671],{"class":394},",\n",[384,673,675,678,680,683,685,688,690,693,696],{"class":386,"line":674},18,[384,676,677],{"class":478},"          fetcher",[384,679,404],{"class":394},[384,681,682],{"class":478}," () ",[384,684,634],{"class":394},[384,686,687],{"class":478}," api",[384,689,491],{"class":394},[384,691,692],{"class":556},"getUser",[384,694,695],{"class":478},"(id)",[384,697,671],{"class":394},[384,699,701,704,706,709,712,715,717,720,723,725,728,731],{"class":386,"line":700},19,[384,702,703],{"class":478},"          options",[384,705,404],{"class":394},[384,707,708],{"class":507}," const",[384,710,711],{"class":474}," QoraOptions",[384,713,714],{"class":478},"(staleTime",[384,716,404],{"class":394},[384,718,719],{"class":474}," Duration",[384,721,722],{"class":478},"(minutes",[384,724,404],{"class":394},[384,726,727],{"class":443}," 5",[384,729,730],{"class":478},"))",[384,732,671],{"class":394},[384,734,736,739],{"class":386,"line":735},20,[384,737,738],{"class":478},"        )",[384,740,671],{"class":394},[384,742,744],{"class":386,"line":743},21,[384,745,746],{"class":478},"      )\n",[384,748,750,752,755],{"class":386,"line":749},22,[384,751,620],{"class":394},[384,753,754],{"class":556},"doOnData",[384,756,757],{"class":478},"((state) {\n",[384,759,761],{"class":386,"line":760},23,[384,762,763],{"class":527},"        // Les effets de bord s'exécutent après chaque émission d'état, avant le rebuild du widget.\n",[384,765,767,771,774,777,780,782,784,787],{"class":386,"line":766},24,[384,768,770],{"class":769},"s7zQu","        if",[384,772,773],{"class":478}," (state ",[384,775,776],{"class":769},"case",[384,778,779],{"class":474}," Success",[384,781,560],{"class":478},[384,783,404],{"class":394},[384,785,786],{"class":507},"final",[384,788,789],{"class":478}," data)) {\n",[384,791,793,796,798,801,803,806,808,811,814,816,819,821,824],{"class":386,"line":792},25,[384,794,795],{"class":478},"          analytics",[384,797,491],{"class":394},[384,799,800],{"class":556},"track",[384,802,560],{"class":478},[384,804,805],{"class":407},"'user_loaded'",[384,807,665],{"class":394},[384,809,810],{"class":478}," {",[384,812,813],{"class":407},"'id'",[384,815,404],{"class":394},[384,817,818],{"class":478}," data",[384,820,491],{"class":394},[384,822,823],{"class":478},"id})",[384,825,450],{"class":394},[384,827,829],{"class":386,"line":828},26,[384,830,831],{"class":478},"        }\n",[384,833,835,838],{"class":386,"line":834},27,[384,836,837],{"class":478},"      })",[384,839,450],{"class":394},[384,841,843],{"class":386,"line":842},28,[384,844,465],{"emptyLinePlaceholder":464},[384,846,848],{"class":386,"line":847},29,[384,849,850],{"class":527},"  // Avancer le subject pilote. switchMap gère le reste.\n",[384,852,854,857,860,862,864,867,869,872,874,877,879],{"class":386,"line":853},30,[384,855,856],{"class":507},"  void",[384,858,859],{"class":556}," selectUser",[384,861,560],{"class":478},[384,863,548],{"class":474},[384,865,866],{"class":478}," id) ",[384,868,634],{"class":394},[384,870,871],{"class":478}," _idSubject",[384,873,491],{"class":394},[384,875,876],{"class":556},"add",[384,878,695],{"class":478},[384,880,450],{"class":394},[384,882,884],{"class":386,"line":883},31,[384,885,465],{"emptyLinePlaceholder":464},[384,887,889,891,894,897,899,901,903,906,909],{"class":386,"line":888},32,[384,890,856],{"class":507},[384,892,893],{"class":556}," dispose",[384,895,896],{"class":478},"() ",[384,898,634],{"class":394},[384,900,871],{"class":478},[384,902,491],{"class":394},[384,904,905],{"class":556},"close",[384,907,908],{"class":478},"()",[384,910,450],{"class":394},[384,912,914],{"class":386,"line":913},33,[384,915,916],{"class":478},"}\n",[427,918,920],{"id":919},"binding-du-widget","Binding du widget",[374,922,925],{"className":433,"code":923,"filename":924,"language":436,"meta":380,"style":380},"class UserScreen extends StatefulWidget {\n  const UserScreen({super.key});\n\n  @override\n  State\u003CUserScreen> createState() => _UserScreenState();\n}\n\nclass _UserScreenState extends State\u003CUserScreen> {\n  late final UserViewModel _vm;\n  late final StreamSubscription\u003CQoraState\u003CUser>> _sub;\n  QoraState\u003CUser> _state = const Initial();\n\n  @override\n  void initState() {\n    super.initState();\n    _vm = UserViewModel(context.qora);\n    _sub = _vm.userState.listen((state) {\n      setState(() => _state = state);\n    });\n  }\n\n  @override\n  void dispose() {\n    _sub.cancel();\n    _vm.dispose();\n    super.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return switch (_state) {\n      Initial() => const SizedBox.shrink(),\n      Loading(:final previousData) => previousData != null\n          ? UserCard(previousData)\n          : const CircularProgressIndicator(),\n      Success(:final data) => Column(\n          children: [\n            UserCard(data),\n            Row(\n              children: [\n                TextButton(\n                  onPressed: () => _vm.selectUser('1'),\n                  child: const Text('Utilisateur 1'),\n                ),\n                TextButton(\n                  onPressed: () => _vm.selectUser('2'),\n                  child: const Text('Utilisateur 2'),\n                ),\n              ],\n            ),\n          ],\n        ),\n      Failure(:final error) => ErrorView(error),\n    };\n  }\n}\n","lib/features/user/user_screen.dart",[356,926,927,942,959,963,968,995,999,1003,1021,1034,1056,1079,1083,1087,1097,1111,1130,1151,1171,1178,1183,1187,1191,1199,1213,1227,1239,1243,1247,1251,1267,1278,1301,1326,1338,1353,1375,1386,1397,1405,1415,1423,1450,1472,1480,1487,1513,1533,1540,1548,1556,1564,1571,1596,1604,1609],{"__ignoreMap":380},[384,928,929,931,934,937,940],{"class":386,"line":387},[384,930,471],{"class":394},[384,932,933],{"class":474}," UserScreen",[384,935,936],{"class":394}," extends",[384,938,939],{"class":474}," StatefulWidget",[384,941,479],{"class":478},[384,943,944,947,949,952,954,957],{"class":386,"line":398},[384,945,946],{"class":507},"  const",[384,948,933],{"class":474},[384,950,951],{"class":478},"({super",[384,953,491],{"class":394},[384,955,956],{"class":478},"key})",[384,958,450],{"class":394},[384,960,961],{"class":386,"line":411},[384,962,465],{"emptyLinePlaceholder":464},[384,964,965],{"class":386,"line":468},[384,966,967],{"class":507},"  @override\n",[384,969,970,973,975,978,981,984,986,988,991,993],{"class":386,"line":482},[384,971,972],{"class":474},"  State",[384,974,545],{"class":478},[384,976,977],{"class":474},"UserScreen",[384,979,980],{"class":478},"> ",[384,982,983],{"class":556},"createState",[384,985,896],{"class":478},[384,987,634],{"class":394},[384,989,990],{"class":474}," _UserScreenState",[384,992,908],{"class":478},[384,994,450],{"class":394},[384,996,997],{"class":386,"line":499},[384,998,916],{"class":478},[384,1000,1001],{"class":386,"line":504},[384,1002,465],{"emptyLinePlaceholder":464},[384,1004,1005,1007,1009,1011,1014,1016,1018],{"class":386,"line":519},[384,1006,471],{"class":394},[384,1008,990],{"class":474},[384,1010,936],{"class":394},[384,1012,1013],{"class":474}," State",[384,1015,545],{"class":478},[384,1017,977],{"class":474},[384,1019,1020],{"class":478},"> {\n",[384,1022,1023,1025,1027,1029,1032],{"class":386,"line":524},[384,1024,591],{"class":507},[384,1026,594],{"class":507},[384,1028,475],{"class":474},[384,1030,1031],{"class":478}," _vm",[384,1033,450],{"class":394},[384,1035,1036,1038,1040,1043,1045,1047,1049,1051,1054],{"class":386,"line":531},[384,1037,591],{"class":507},[384,1039,594],{"class":507},[384,1041,1042],{"class":474}," StreamSubscription",[384,1044,545],{"class":478},[384,1046,211],{"class":474},[384,1048,545],{"class":478},[384,1050,606],{"class":474},[384,1052,1053],{"class":478},">> _sub",[384,1055,450],{"class":394},[384,1057,1058,1061,1063,1065,1068,1070,1072,1075,1077],{"class":386,"line":571},[384,1059,1060],{"class":474},"  QoraState",[384,1062,545],{"class":478},[384,1064,606],{"class":474},[384,1066,1067],{"class":478},"> _state ",[384,1069,539],{"class":394},[384,1071,708],{"class":507},[384,1073,1074],{"class":474}," Initial",[384,1076,908],{"class":478},[384,1078,450],{"class":394},[384,1080,1081],{"class":386,"line":576},[384,1082,465],{"emptyLinePlaceholder":464},[384,1084,1085],{"class":386,"line":582},[384,1086,967],{"class":507},[384,1088,1089,1091,1094],{"class":386,"line":588},[384,1090,856],{"class":507},[384,1092,1093],{"class":556}," initState",[384,1095,1096],{"class":478},"() {\n",[384,1098,1099,1102,1104,1107,1109],{"class":386,"line":617},[384,1100,1101],{"class":478},"    super",[384,1103,491],{"class":394},[384,1105,1106],{"class":556},"initState",[384,1108,908],{"class":478},[384,1110,450],{"class":394},[384,1112,1113,1116,1118,1120,1123,1125,1128],{"class":386,"line":628},[384,1114,1115],{"class":478},"    _vm ",[384,1117,539],{"class":394},[384,1119,475],{"class":474},[384,1121,1122],{"class":478},"(context",[384,1124,491],{"class":394},[384,1126,1127],{"class":478},"qora)",[384,1129,450],{"class":394},[384,1131,1132,1135,1137,1139,1141,1144,1146,1149],{"class":386,"line":651},[384,1133,1134],{"class":478},"    _sub ",[384,1136,539],{"class":394},[384,1138,1031],{"class":478},[384,1140,491],{"class":394},[384,1142,1143],{"class":478},"userState",[384,1145,491],{"class":394},[384,1147,1148],{"class":556},"listen",[384,1150,757],{"class":478},[384,1152,1153,1156,1159,1161,1164,1166,1169],{"class":386,"line":674},[384,1154,1155],{"class":556},"      setState",[384,1157,1158],{"class":478},"(() ",[384,1160,634],{"class":394},[384,1162,1163],{"class":478}," _state ",[384,1165,539],{"class":394},[384,1167,1168],{"class":478}," state)",[384,1170,450],{"class":394},[384,1172,1173,1176],{"class":386,"line":700},[384,1174,1175],{"class":478},"    })",[384,1177,450],{"class":394},[384,1179,1180],{"class":386,"line":735},[384,1181,1182],{"class":478},"  }\n",[384,1184,1185],{"class":386,"line":743},[384,1186,465],{"emptyLinePlaceholder":464},[384,1188,1189],{"class":386,"line":749},[384,1190,967],{"class":507},[384,1192,1193,1195,1197],{"class":386,"line":760},[384,1194,856],{"class":507},[384,1196,893],{"class":556},[384,1198,1096],{"class":478},[384,1200,1201,1204,1206,1209,1211],{"class":386,"line":766},[384,1202,1203],{"class":478},"    _sub",[384,1205,491],{"class":394},[384,1207,1208],{"class":556},"cancel",[384,1210,908],{"class":478},[384,1212,450],{"class":394},[384,1214,1215,1218,1220,1223,1225],{"class":386,"line":792},[384,1216,1217],{"class":478},"    _vm",[384,1219,491],{"class":394},[384,1221,1222],{"class":556},"dispose",[384,1224,908],{"class":478},[384,1226,450],{"class":394},[384,1228,1229,1231,1233,1235,1237],{"class":386,"line":828},[384,1230,1101],{"class":478},[384,1232,491],{"class":394},[384,1234,1222],{"class":556},[384,1236,908],{"class":478},[384,1238,450],{"class":394},[384,1240,1241],{"class":386,"line":834},[384,1242,1182],{"class":478},[384,1244,1245],{"class":386,"line":842},[384,1246,465],{"emptyLinePlaceholder":464},[384,1248,1249],{"class":386,"line":847},[384,1250,967],{"class":507},[384,1252,1253,1256,1259,1261,1264],{"class":386,"line":853},[384,1254,1255],{"class":474},"  Widget",[384,1257,1258],{"class":556}," build",[384,1260,560],{"class":478},[384,1262,1263],{"class":474},"BuildContext",[384,1265,1266],{"class":478}," context) {\n",[384,1268,1269,1272,1275],{"class":386,"line":883},[384,1270,1271],{"class":769},"    return",[384,1273,1274],{"class":769}," switch",[384,1276,1277],{"class":478}," (_state) {\n",[384,1279,1280,1283,1285,1287,1289,1292,1294,1297,1299],{"class":386,"line":888},[384,1281,1282],{"class":474},"      Initial",[384,1284,896],{"class":478},[384,1286,634],{"class":394},[384,1288,708],{"class":507},[384,1290,1291],{"class":474}," SizedBox",[384,1293,491],{"class":394},[384,1295,1296],{"class":556},"shrink",[384,1298,908],{"class":478},[384,1300,671],{"class":394},[384,1302,1303,1306,1308,1310,1312,1315,1317,1320,1323],{"class":386,"line":913},[384,1304,1305],{"class":474},"      Loading",[384,1307,560],{"class":478},[384,1309,404],{"class":394},[384,1311,786],{"class":507},[384,1313,1314],{"class":478}," previousData) ",[384,1316,634],{"class":394},[384,1318,1319],{"class":478}," previousData ",[384,1321,1322],{"class":394},"!=",[384,1324,1325],{"class":394}," null\n",[384,1327,1329,1332,1335],{"class":386,"line":1328},34,[384,1330,1331],{"class":394},"          ?",[384,1333,1334],{"class":474}," UserCard",[384,1336,1337],{"class":478},"(previousData)\n",[384,1339,1341,1344,1346,1349,1351],{"class":386,"line":1340},35,[384,1342,1343],{"class":394},"          :",[384,1345,708],{"class":507},[384,1347,1348],{"class":474}," CircularProgressIndicator",[384,1350,908],{"class":478},[384,1352,671],{"class":394},[384,1354,1356,1359,1361,1363,1365,1368,1370,1373],{"class":386,"line":1355},36,[384,1357,1358],{"class":474},"      Success",[384,1360,560],{"class":478},[384,1362,404],{"class":394},[384,1364,786],{"class":507},[384,1366,1367],{"class":478}," data) ",[384,1369,634],{"class":394},[384,1371,1372],{"class":474}," Column",[384,1374,625],{"class":478},[384,1376,1378,1381,1383],{"class":386,"line":1377},37,[384,1379,1380],{"class":478},"          children",[384,1382,404],{"class":394},[384,1384,1385],{"class":478}," [\n",[384,1387,1389,1392,1395],{"class":386,"line":1388},38,[384,1390,1391],{"class":474},"            UserCard",[384,1393,1394],{"class":478},"(data)",[384,1396,671],{"class":394},[384,1398,1400,1403],{"class":386,"line":1399},39,[384,1401,1402],{"class":474},"            Row",[384,1404,625],{"class":478},[384,1406,1408,1411,1413],{"class":386,"line":1407},40,[384,1409,1410],{"class":478},"              children",[384,1412,404],{"class":394},[384,1414,1385],{"class":478},[384,1416,1418,1421],{"class":386,"line":1417},41,[384,1419,1420],{"class":474},"                TextButton",[384,1422,625],{"class":478},[384,1424,1426,1429,1431,1433,1435,1437,1439,1442,1444,1446,1448],{"class":386,"line":1425},42,[384,1427,1428],{"class":478},"                  onPressed",[384,1430,404],{"class":394},[384,1432,682],{"class":478},[384,1434,634],{"class":394},[384,1436,1031],{"class":478},[384,1438,491],{"class":394},[384,1440,1441],{"class":556},"selectUser",[384,1443,560],{"class":478},[384,1445,563],{"class":407},[384,1447,566],{"class":478},[384,1449,671],{"class":394},[384,1451,1453,1456,1458,1460,1463,1465,1468,1470],{"class":386,"line":1452},43,[384,1454,1455],{"class":478},"                  child",[384,1457,404],{"class":394},[384,1459,708],{"class":507},[384,1461,1462],{"class":474}," Text",[384,1464,560],{"class":478},[384,1466,1467],{"class":407},"'Utilisateur 1'",[384,1469,566],{"class":478},[384,1471,671],{"class":394},[384,1473,1475,1478],{"class":386,"line":1474},44,[384,1476,1477],{"class":478},"                )",[384,1479,671],{"class":394},[384,1481,1483,1485],{"class":386,"line":1482},45,[384,1484,1420],{"class":474},[384,1486,625],{"class":478},[384,1488,1490,1492,1494,1496,1498,1500,1502,1504,1506,1509,1511],{"class":386,"line":1489},46,[384,1491,1428],{"class":478},[384,1493,404],{"class":394},[384,1495,682],{"class":478},[384,1497,634],{"class":394},[384,1499,1031],{"class":478},[384,1501,491],{"class":394},[384,1503,1441],{"class":556},[384,1505,560],{"class":478},[384,1507,1508],{"class":407},"'2'",[384,1510,566],{"class":478},[384,1512,671],{"class":394},[384,1514,1516,1518,1520,1522,1524,1526,1529,1531],{"class":386,"line":1515},47,[384,1517,1455],{"class":478},[384,1519,404],{"class":394},[384,1521,708],{"class":507},[384,1523,1462],{"class":474},[384,1525,560],{"class":478},[384,1527,1528],{"class":407},"'Utilisateur 2'",[384,1530,566],{"class":478},[384,1532,671],{"class":394},[384,1534,1536,1538],{"class":386,"line":1535},48,[384,1537,1477],{"class":478},[384,1539,671],{"class":394},[384,1541,1543,1546],{"class":386,"line":1542},49,[384,1544,1545],{"class":478},"              ]",[384,1547,671],{"class":394},[384,1549,1551,1554],{"class":386,"line":1550},50,[384,1552,1553],{"class":478},"            )",[384,1555,671],{"class":394},[384,1557,1559,1562],{"class":386,"line":1558},51,[384,1560,1561],{"class":478},"          ]",[384,1563,671],{"class":394},[384,1565,1567,1569],{"class":386,"line":1566},52,[384,1568,738],{"class":478},[384,1570,671],{"class":394},[384,1572,1574,1577,1579,1581,1583,1586,1588,1591,1594],{"class":386,"line":1573},53,[384,1575,1576],{"class":474},"      Failure",[384,1578,560],{"class":478},[384,1580,404],{"class":394},[384,1582,786],{"class":507},[384,1584,1585],{"class":478}," error) ",[384,1587,634],{"class":394},[384,1589,1590],{"class":474}," ErrorView",[384,1592,1593],{"class":478},"(error)",[384,1595,671],{"class":394},[384,1597,1599,1602],{"class":386,"line":1598},54,[384,1600,1601],{"class":478},"    }",[384,1603,450],{"class":394},[384,1605,1607],{"class":386,"line":1606},55,[384,1608,1182],{"class":478},[384,1610,1612],{"class":386,"line":1611},56,[384,1613,916],{"class":478},[368,1615],{},[348,1617,1619],{"id":1618},"analyse-du-cycle-de-vie","Analyse du cycle de vie",[427,1621,1623],{"id":1622},"ce-qui-se-passe-lors-dun-changement-de-clé","Ce qui se passe lors d'un changement de clé",[352,1625,1626,1627,1630],{},"Quand ",[356,1628,1629],{},"_idSubject.add('2')"," est appelé, la séquence suivante s'exécute atomiquement :",[1632,1633,1634,1651,1748,1773,1808],"ol",{},[1635,1636,1637,1639,1640,1643,1644,1647,1648,491],"li",{},[356,1638,362],{}," appelle ",[356,1641,1642],{},".cancel()"," sur le ",[356,1645,1646],{},"StreamSubscription"," vers ",[356,1649,1650],{},"watchQuery(key: ['users', '1'], ...)",[1635,1652,1653,1654,1657,1658,1660,1661],{},"Le runtime du générateur asynchrone Dart déclenche le bloc ",[356,1655,1656],{},"finally"," à l'intérieur de ",[356,1659,641],{}," :",[374,1662,1664],{"className":433,"code":1663,"language":436,"meta":380,"style":380},"// packages/dart: qora_client.dart, bloc finally de watchQuery\n} finally {\n  depSub?.cancel();          // annuler l'abonnement de dépendance, le cas échéant\n  localRefetchTimer?.cancel(); // annuler tout timer de polling actif\n  entry.removeSubscriber();   // décrémenter CacheEntry._subscriberCount\n  _scheduleGC(normalized);    // démarrer le timer GC s'il n'y a plus d'abonnés\n}\n",[356,1665,1666,1671,1680,1698,1714,1731,1744],{"__ignoreMap":380},[384,1667,1668],{"class":386,"line":387},[384,1669,1670],{"class":527},"// packages/dart: qora_client.dart, bloc finally de watchQuery\n",[384,1672,1673,1676,1678],{"class":386,"line":398},[384,1674,1675],{"class":478},"} ",[384,1677,1656],{"class":769},[384,1679,479],{"class":478},[384,1681,1682,1685,1688,1690,1692,1695],{"class":386,"line":411},[384,1683,1684],{"class":478},"  depSub",[384,1686,1687],{"class":394},"?.",[384,1689,1208],{"class":556},[384,1691,908],{"class":478},[384,1693,1694],{"class":394},";",[384,1696,1697],{"class":527},"          // annuler l'abonnement de dépendance, le cas échéant\n",[384,1699,1700,1703,1705,1707,1709,1711],{"class":386,"line":468},[384,1701,1702],{"class":478},"  localRefetchTimer",[384,1704,1687],{"class":394},[384,1706,1208],{"class":556},[384,1708,908],{"class":478},[384,1710,1694],{"class":394},[384,1712,1713],{"class":527}," // annuler tout timer de polling actif\n",[384,1715,1716,1719,1721,1724,1726,1728],{"class":386,"line":482},[384,1717,1718],{"class":478},"  entry",[384,1720,491],{"class":394},[384,1722,1723],{"class":556},"removeSubscriber",[384,1725,908],{"class":478},[384,1727,1694],{"class":394},[384,1729,1730],{"class":527},"   // décrémenter CacheEntry._subscriberCount\n",[384,1732,1733,1736,1739,1741],{"class":386,"line":499},[384,1734,1735],{"class":556},"  _scheduleGC",[384,1737,1738],{"class":478},"(normalized)",[384,1740,1694],{"class":394},[384,1742,1743],{"class":527},"    // démarrer le timer GC s'il n'y a plus d'abonnés\n",[384,1745,1746],{"class":386,"line":504},[384,1747,916],{"class":478},[1635,1749,1750,1753,1754,1757,1758,1761,1762,1765,1766,1769,1770,491],{},[356,1751,1752],{},"removeSubscriber()"," décrémente ",[356,1755,1756],{},"CacheEntry._subscriberCount"," et appelle ",[356,1759,1760],{},"touch()"," (met à jour ",[356,1763,1764],{},"lastAccessedAt","). Si le compteur atteint zéro, ",[356,1767,1768],{},"entry.isActive"," devient ",[356,1771,1772],{},"false",[1635,1774,1775,1778,1779,1781,1782,1784,1785,1788,1789,1792,1793,1796,1797,1799,1800,1803,1804,1807],{},[356,1776,1777],{},"_scheduleGC(key)"," inspecte ",[356,1780,1768],{},". Si ",[356,1783,1772],{},", il démarre un ",[356,1786,1787],{},"Timer"," avec une durée de ",[356,1790,1791],{},"gcTime"," (défaut : ",[356,1794,1795],{},"Duration(minutes: 5)","). Si ",[356,1798,1768],{}," est toujours ",[356,1801,1802],{},"true",", parce qu'une autre partie de l'app maintient un abonnement séparé à la même clé, ",[356,1805,1806],{},"_scheduleGC"," est un no-op.",[1635,1809,1810,1812,1813,1816,1817,1820,1821,1824],{},[356,1811,362],{}," ouvre un nouvel abonnement vers ",[356,1814,1815],{},"watchQuery(key: ['users', '2'], ...)",". ",[356,1818,1819],{},"addSubscriber()"," incrémente le ",[356,1822,1823],{},"_subscriberCount"," de la nouvelle entrée.",[427,1826,1828],{"id":1827},"pourquoi-les-données-de-lancienne-clé-survivent","Pourquoi les données de l'ancienne clé survivent",[352,1830,1831,1832,1834],{},"Le timer GC se déclenche ",[356,1833,1791],{}," après l'annulation du dernier abonné, pas immédiatement. Pendant cette fenêtre :",[1836,1837,1838,1848,1869],"ul",{},[1635,1839,1840,1841,1844,1845,491],{},"L'entrée de cache pour ",[356,1842,1843],{},"['users', '1']"," reste en mémoire avec son dernier état ",[356,1846,1847],{},"Success",[1635,1849,1850,1851,1854,1855,1639,1857,1859,1860,1862,1863,1865,1866,1868],{},"Si ",[356,1852,1853],{},"selectUser('1')"," est rappelé avant le déclenchement du timer, un nouvel abonnement ",[356,1856,641],{},[356,1858,1819],{},", ",[356,1861,1768],{}," redevient ",[356,1864,1802],{},", et ",[356,1867,1806],{}," est un no-op, le timer est annulé s'il était déjà en cours.",[1635,1870,1871],{},"Le prochain accès sert les données en cache immédiatement, puis revalide en arrière-plan si les données sont périmées.",[352,1873,1874,1875,1878],{},"Cela signifie que la navigation entre deux enregistrements utilisateurs avec ",[356,1876,1877],{},"staleTime: Duration(minutes: 5)"," résulte en au maximum une requête réseau par fenêtre de 5 minutes par clé, quel que soit le nombre de fois que l'utilisateur commute.",[427,1880,1882],{"id":1881},"re-vérification-à-lexpiration-du-gc","Re-vérification à l'expiration du GC",[352,1884,1885,1886,1888],{},"Le timer GC re-vérifie ",[356,1887,1768],{}," avant de supprimer l'entrée :",[374,1890,1892],{"className":433,"code":1891,"language":436,"meta":380,"style":380},"entry.gcTimer = Timer(config.defaultOptions.gcTime, () {\n  if (!entry.isActive) {   // re-vérifier: un nouvel abonné a pu s'attacher\n    _cache.remove(key);\n  }\n});\n",[356,1893,1894,1926,1947,1962,1966],{"__ignoreMap":380},[384,1895,1896,1899,1901,1904,1906,1909,1912,1914,1917,1919,1921,1923],{"class":386,"line":387},[384,1897,1898],{"class":478},"entry",[384,1900,491],{"class":394},[384,1902,1903],{"class":478},"gcTimer ",[384,1905,539],{"class":394},[384,1907,1908],{"class":474}," Timer",[384,1910,1911],{"class":478},"(config",[384,1913,491],{"class":394},[384,1915,1916],{"class":478},"defaultOptions",[384,1918,491],{"class":394},[384,1920,1791],{"class":478},[384,1922,665],{"class":394},[384,1924,1925],{"class":478}," () {\n",[384,1927,1928,1931,1934,1937,1939,1941,1944],{"class":386,"line":398},[384,1929,1930],{"class":769},"  if",[384,1932,1933],{"class":478}," (",[384,1935,1936],{"class":394},"!",[384,1938,1898],{"class":478},[384,1940,491],{"class":394},[384,1942,1943],{"class":478},"isActive) {   ",[384,1945,1946],{"class":527},"// re-vérifier: un nouvel abonné a pu s'attacher\n",[384,1948,1949,1952,1954,1957,1960],{"class":386,"line":411},[384,1950,1951],{"class":478},"    _cache",[384,1953,491],{"class":394},[384,1955,1956],{"class":556},"remove",[384,1958,1959],{"class":478},"(key)",[384,1961,450],{"class":394},[384,1963,1964],{"class":386,"line":468},[384,1965,1182],{"class":478},[384,1967,1968,1971],{"class":386,"line":482},[384,1969,1970],{"class":478},"})",[384,1972,450],{"class":394},[352,1974,1975],{},"Un nouvel abonné qui s'attache après la planification du timer mais avant son déclenchement trouvera l'entrée intacte et empêchera sa suppression.",[368,1977],{},[348,1979,1981],{"id":1980},"référence-des-opérateurs","Référence des opérateurs",[1983,1984,1985,1998],"table",{},[1986,1987,1988],"thead",{},[1989,1990,1991,1995],"tr",{},[1992,1993,1994],"th",{},"Opérateur RxDart",[1992,1996,1997],{},"Rôle dans ce pattern",[1999,2000,2001,2012,2024,2033,2043],"tbody",{},[1989,2002,2003,2009],{},[2004,2005,2006],"td",{},[356,2007,2008],{},"BehaviorSubject",[2004,2010,2011],{},"Maintient la valeur de clé actuelle ; rejoue la dernière émission aux nouveaux listeners.",[1989,2013,2014,2018],{},[2004,2015,2016],{},[356,2017,362],{},[2004,2019,2020,2021,2023],{},"Annule l'abonnement ",[356,2022,641],{}," précédent à chaque émission ; ouvre un nouveau.",[1989,2025,2026,2030],{},[2004,2027,2028],{},[356,2029,754],{},[2004,2031,2032],{},"Exécute des effets de bord (journalisation, analytics) sur chaque état émis sans modifier le stream.",[1989,2034,2035,2040],{},[2004,2036,2037],{},[356,2038,2039],{},"debounceTime",[2004,2041,2042],{},"Optionnel : débouce les changements de clé rapides (ex. saisie de recherche) pour éviter de lancer un fetch par frappe.",[1989,2044,2045,2050],{},[2004,2046,2047],{},[356,2048,2049],{},"distinctUnchanged",[2004,2051,2052],{},"Optionnel : supprime le re-abonnement quand la même clé est émise deux fois consécutivement.",[427,2054,2056],{"id":2055},"debouce-des-changements-de-clé-rapides","Debouce des changements de clé rapides",[352,2058,2059,2060,2062,2063,1660],{},"Pour les saisies de recherche ou autres pilotes à haute fréquence, ajouter ",[356,2061,2039],{}," avant ",[356,2064,362],{},[374,2066,2068],{"className":433,"code":2067,"language":436,"meta":380,"style":380},"late final Stream\u003CQoraState\u003CList\u003CProduct>>> searchResults = _querySubject\n    .debounceTime(const Duration(milliseconds: 300))\n    .distinct()\n    .switchMap(\n      (query) => _client.watchQuery\u003CList\u003CProduct>>(\n        key: ['products', 'search', query],\n        fetcher: () => api.searchProducts(query),\n      ),\n    );\n",[356,2069,2070,2101,2126,2136,2144,2168,2192,2215,2222],{"__ignoreMap":380},[384,2071,2072,2075,2077,2079,2081,2083,2085,2088,2090,2093,2096,2098],{"class":386,"line":387},[384,2073,2074],{"class":507},"late",[384,2076,594],{"class":507},[384,2078,597],{"class":474},[384,2080,545],{"class":478},[384,2082,211],{"class":474},[384,2084,545],{"class":478},[384,2086,2087],{"class":474},"List",[384,2089,545],{"class":478},[384,2091,2092],{"class":474},"Product",[384,2094,2095],{"class":478},">>> searchResults ",[384,2097,539],{"class":394},[384,2099,2100],{"class":478}," _querySubject\n",[384,2102,2103,2106,2108,2110,2113,2115,2118,2120,2123],{"class":386,"line":398},[384,2104,2105],{"class":394},"    .",[384,2107,2039],{"class":556},[384,2109,560],{"class":478},[384,2111,2112],{"class":507},"const",[384,2114,719],{"class":474},[384,2116,2117],{"class":478},"(milliseconds",[384,2119,404],{"class":394},[384,2121,2122],{"class":443}," 300",[384,2124,2125],{"class":478},"))\n",[384,2127,2128,2130,2133],{"class":386,"line":411},[384,2129,2105],{"class":394},[384,2131,2132],{"class":556},"distinct",[384,2134,2135],{"class":478},"()\n",[384,2137,2138,2140,2142],{"class":386,"line":468},[384,2139,2105],{"class":394},[384,2141,362],{"class":556},[384,2143,625],{"class":478},[384,2145,2146,2149,2151,2153,2155,2157,2159,2161,2163,2165],{"class":386,"line":482},[384,2147,2148],{"class":478},"      (query) ",[384,2150,634],{"class":394},[384,2152,514],{"class":478},[384,2154,491],{"class":394},[384,2156,641],{"class":556},[384,2158,545],{"class":478},[384,2160,2087],{"class":474},[384,2162,545],{"class":478},[384,2164,2092],{"class":474},[384,2166,2167],{"class":478},">>(\n",[384,2169,2170,2173,2175,2177,2180,2182,2185,2187,2190],{"class":386,"line":499},[384,2171,2172],{"class":478},"        key",[384,2174,404],{"class":394},[384,2176,659],{"class":478},[384,2178,2179],{"class":407},"'products'",[384,2181,665],{"class":394},[384,2183,2184],{"class":407}," 'search'",[384,2186,665],{"class":394},[384,2188,2189],{"class":478}," query]",[384,2191,671],{"class":394},[384,2193,2194,2197,2199,2201,2203,2205,2207,2210,2213],{"class":386,"line":504},[384,2195,2196],{"class":478},"        fetcher",[384,2198,404],{"class":394},[384,2200,682],{"class":478},[384,2202,634],{"class":394},[384,2204,687],{"class":478},[384,2206,491],{"class":394},[384,2208,2209],{"class":556},"searchProducts",[384,2211,2212],{"class":478},"(query)",[384,2214,671],{"class":394},[384,2216,2217,2220],{"class":386,"line":519},[384,2218,2219],{"class":478},"      )",[384,2221,671],{"class":394},[384,2223,2224,2227],{"class":386,"line":524},[384,2225,2226],{"class":478},"    )",[384,2228,450],{"class":394},[352,2230,2231,2233],{},[356,2232,362],{}," annule toujours l'abonnement en cours à chaque émission, donc un debouce de 300 ms est suffisant pour éviter de lancer un fetch par caractère tout en préservant l'annulation instantanée de toute requête qui démarre.",[368,2235],{},[348,2237,2239],{"id":2238},"équivalent-avec-les-hooks","Équivalent avec les hooks",[352,2241,1850,2242,2245],{},[356,2243,2244],{},"qora_hooks"," est disponible, le même comportement s'exprime sans RxDart :",[374,2247,2249],{"className":433,"code":2248,"filename":924,"language":436,"meta":380,"style":380},"class UserScreen extends HookWidget {\n  const UserScreen({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    final selectedId = useState('1');\n    final state = useQuery\u003CUser>(\n      key: ['users', selectedId.value],\n      fetcher: () => api.getUser(selectedId.value),\n      options: const QoraOptions(staleTime: Duration(minutes: 5)),\n    );\n\n    // useQuery se ré-abonne automatiquement quand la clé change.\n    // L'abonnement précédent est annulé dans son nettoyage useEffect.\n\n    return switch (state) {\n      Initial() => const SizedBox.shrink(),\n      Loading(:final previousData) => previousData != null\n          ? UserCard(previousData)\n          : const CircularProgressIndicator(),\n      Success(:final data) => UserCard(data),\n      Failure(:final error) => ErrorView(error),\n    };\n  }\n}\n",[356,2250,2251,2264,2278,2282,2286,2298,2319,2337,2360,2387,2414,2420,2424,2429,2434,2438,2447,2467,2487,2495,2507,2527,2547,2553,2557],{"__ignoreMap":380},[384,2252,2253,2255,2257,2259,2262],{"class":386,"line":387},[384,2254,471],{"class":394},[384,2256,933],{"class":474},[384,2258,936],{"class":394},[384,2260,2261],{"class":474}," HookWidget",[384,2263,479],{"class":478},[384,2265,2266,2268,2270,2272,2274,2276],{"class":386,"line":398},[384,2267,946],{"class":507},[384,2269,933],{"class":474},[384,2271,951],{"class":478},[384,2273,491],{"class":394},[384,2275,956],{"class":478},[384,2277,450],{"class":394},[384,2279,2280],{"class":386,"line":411},[384,2281,465],{"emptyLinePlaceholder":464},[384,2283,2284],{"class":386,"line":468},[384,2285,967],{"class":507},[384,2287,2288,2290,2292,2294,2296],{"class":386,"line":482},[384,2289,1255],{"class":474},[384,2291,1258],{"class":556},[384,2293,560],{"class":478},[384,2295,1263],{"class":474},[384,2297,1266],{"class":478},[384,2299,2300,2303,2306,2308,2311,2313,2315,2317],{"class":386,"line":499},[384,2301,2302],{"class":507},"    final",[384,2304,2305],{"class":478}," selectedId ",[384,2307,539],{"class":394},[384,2309,2310],{"class":556}," useState",[384,2312,560],{"class":478},[384,2314,563],{"class":407},[384,2316,566],{"class":478},[384,2318,450],{"class":394},[384,2320,2321,2323,2326,2328,2331,2333,2335],{"class":386,"line":504},[384,2322,2302],{"class":507},[384,2324,2325],{"class":478}," state ",[384,2327,539],{"class":394},[384,2329,2330],{"class":556}," useQuery",[384,2332,545],{"class":478},[384,2334,606],{"class":474},[384,2336,648],{"class":478},[384,2338,2339,2342,2344,2346,2348,2350,2353,2355,2358],{"class":386,"line":519},[384,2340,2341],{"class":478},"      key",[384,2343,404],{"class":394},[384,2345,659],{"class":478},[384,2347,662],{"class":407},[384,2349,665],{"class":394},[384,2351,2352],{"class":478}," selectedId",[384,2354,491],{"class":394},[384,2356,2357],{"class":478},"value]",[384,2359,671],{"class":394},[384,2361,2362,2365,2367,2369,2371,2373,2375,2377,2380,2382,2385],{"class":386,"line":524},[384,2363,2364],{"class":478},"      fetcher",[384,2366,404],{"class":394},[384,2368,682],{"class":478},[384,2370,634],{"class":394},[384,2372,687],{"class":478},[384,2374,491],{"class":394},[384,2376,692],{"class":556},[384,2378,2379],{"class":478},"(selectedId",[384,2381,491],{"class":394},[384,2383,2384],{"class":478},"value)",[384,2386,671],{"class":394},[384,2388,2389,2392,2394,2396,2398,2400,2402,2404,2406,2408,2410,2412],{"class":386,"line":531},[384,2390,2391],{"class":478},"      options",[384,2393,404],{"class":394},[384,2395,708],{"class":507},[384,2397,711],{"class":474},[384,2399,714],{"class":478},[384,2401,404],{"class":394},[384,2403,719],{"class":474},[384,2405,722],{"class":478},[384,2407,404],{"class":394},[384,2409,727],{"class":443},[384,2411,730],{"class":478},[384,2413,671],{"class":394},[384,2415,2416,2418],{"class":386,"line":571},[384,2417,2226],{"class":478},[384,2419,450],{"class":394},[384,2421,2422],{"class":386,"line":576},[384,2423,465],{"emptyLinePlaceholder":464},[384,2425,2426],{"class":386,"line":582},[384,2427,2428],{"class":527},"    // useQuery se ré-abonne automatiquement quand la clé change.\n",[384,2430,2431],{"class":386,"line":588},[384,2432,2433],{"class":527},"    // L'abonnement précédent est annulé dans son nettoyage useEffect.\n",[384,2435,2436],{"class":386,"line":617},[384,2437,465],{"emptyLinePlaceholder":464},[384,2439,2440,2442,2444],{"class":386,"line":628},[384,2441,1271],{"class":769},[384,2443,1274],{"class":769},[384,2445,2446],{"class":478}," (state) {\n",[384,2448,2449,2451,2453,2455,2457,2459,2461,2463,2465],{"class":386,"line":651},[384,2450,1282],{"class":474},[384,2452,896],{"class":478},[384,2454,634],{"class":394},[384,2456,708],{"class":507},[384,2458,1291],{"class":474},[384,2460,491],{"class":394},[384,2462,1296],{"class":556},[384,2464,908],{"class":478},[384,2466,671],{"class":394},[384,2468,2469,2471,2473,2475,2477,2479,2481,2483,2485],{"class":386,"line":674},[384,2470,1305],{"class":474},[384,2472,560],{"class":478},[384,2474,404],{"class":394},[384,2476,786],{"class":507},[384,2478,1314],{"class":478},[384,2480,634],{"class":394},[384,2482,1319],{"class":478},[384,2484,1322],{"class":394},[384,2486,1325],{"class":394},[384,2488,2489,2491,2493],{"class":386,"line":700},[384,2490,1331],{"class":394},[384,2492,1334],{"class":474},[384,2494,1337],{"class":478},[384,2496,2497,2499,2501,2503,2505],{"class":386,"line":735},[384,2498,1343],{"class":394},[384,2500,708],{"class":507},[384,2502,1348],{"class":474},[384,2504,908],{"class":478},[384,2506,671],{"class":394},[384,2508,2509,2511,2513,2515,2517,2519,2521,2523,2525],{"class":386,"line":743},[384,2510,1358],{"class":474},[384,2512,560],{"class":478},[384,2514,404],{"class":394},[384,2516,786],{"class":507},[384,2518,1367],{"class":478},[384,2520,634],{"class":394},[384,2522,1334],{"class":474},[384,2524,1394],{"class":478},[384,2526,671],{"class":394},[384,2528,2529,2531,2533,2535,2537,2539,2541,2543,2545],{"class":386,"line":749},[384,2530,1576],{"class":474},[384,2532,560],{"class":478},[384,2534,404],{"class":394},[384,2536,786],{"class":507},[384,2538,1585],{"class":478},[384,2540,634],{"class":394},[384,2542,1590],{"class":474},[384,2544,1593],{"class":478},[384,2546,671],{"class":394},[384,2548,2549,2551],{"class":386,"line":760},[384,2550,1601],{"class":478},[384,2552,450],{"class":394},[384,2554,2555],{"class":386,"line":766},[384,2556,1182],{"class":478},[384,2558,2559],{"class":386,"line":792},[384,2560,916],{"class":478},[352,2562,2563,2566,2567,2570,2571,2573,2574,491],{},[356,2564,2565],{},"useQuery"," utilise ",[356,2568,2569],{},"useEffect([Object.hashAll(key)])"," pour annuler et se ré-abonner lors du changement de clé. Le cycle de vie GC est identique : le chemin d'annulation est le même bloc ",[356,2572,1656],{}," de ",[356,2575,641],{},[352,2577,2578,2579,2582],{},"Utiliser le pattern RxDart dans les contextes non-",[356,2580,2581],{},"HookWidget"," ou quand la logique de pilotage des clés réside dans une couche ViewModel en dehors de l'arbre de widgets.",[2584,2585,2586],"style",{},"html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}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}",{"title":380,"searchDepth":398,"depth":398,"links":2588},[2589,2590,2591,2595,2600,2603],{"id":350,"depth":398,"text":243},{"id":372,"depth":398,"text":98},{"id":424,"depth":398,"text":425,"children":2592},[2593,2594],{"id":429,"depth":411,"text":430},{"id":919,"depth":411,"text":920},{"id":1618,"depth":398,"text":1619,"children":2596},[2597,2598,2599],{"id":1622,"depth":411,"text":1623},{"id":1827,"depth":411,"text":1828},{"id":1881,"depth":411,"text":1882},{"id":1980,"depth":398,"text":1981,"children":2601},[2602],{"id":2055,"depth":411,"text":2056},{"id":2238,"depth":398,"text":2239},"Gestion réactive des clés avec RxDart et QoraClient, commutation dynamique de requêtes avec nettoyage garanti des ressources.","md",null,{},{"icon":281},{"title":278,"description":2604},"Ti_OJCY3YegkCZtOMK9ZnQd37804uBGxyEdkYXV0Ntc",[2612,2614],{"title":273,"path":274,"stem":275,"description":2613,"icon":276,"children":-1},"Ajouter Qora à un projet Riverpod pour compléter FutureProvider avec SWR, le comportement hors ligne et les APIs de requête orientées hooks.",{"title":283,"path":284,"stem":285,"description":2615,"children":-1},"[object Object]",1794040411282]