[{"data":1,"prerenderedAt":1655},["ShallowReactive",2],{"navigation_docs_fr":3,"-fr-recipes-ssr-hydration":342,"-fr-recipes-ssr-hydration-surround":1650},[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":177,"body":344,"description":1643,"extension":1644,"links":1645,"meta":1646,"navigation":1647,"path":178,"seo":1648,"stem":179,"__hash__":1649},"docs_fr/fr/04.recipes/09.ssr-hydration.md",{"type":345,"value":346,"toc":1628},"minimark",[347,362,376,379,384,440,442,446,458,768,779,784,786,790,799,1063,1091,1093,1097,1102,1138,1148,1150,1154,1167,1300,1302,1308,1313,1333,1337,1378,1384,1425,1427,1433,1445,1588,1590,1594,1624],[348,349,350,354,355,358,359,361],"p",{},[351,352,353],"code",{},"SsrHydrator"," lit le snapshot du cache rendu côté serveur depuis ",[351,356,357],{},"window.__QORA_STATE__"," et l'injecte dans ",[351,360,202],{}," avant le rendu de la première frame.",[348,363,364,366,367,371,372,375],{},[351,365,353],{}," est uniquement disponible sur ",[368,369,370],"strong",{},"Flutter Web",". Sur les cibles natives et serveur, l'import se résout en stub sans opération, de sorte que le même code compile partout sans gardes ",[351,373,374],{},"#if",".",[377,378],"hr",{},[380,381,383],"h2",{"id":382},"fonctionnement","Fonctionnement",[385,386,387,398,411,429],"ol",{},[388,389,390,391,394,395,375],"li",{},"Le serveur précharge les données et les intègre sous forme d'objet JSON dans une balise ",[351,392,393],{},"\u003Cscript>"," avant le chargement de ",[351,396,397],{},"main.dart.js",[388,399,400,403,404,406,407,410],{},[351,401,402],{},"SsrHydrator.hydrate()"," lit ",[351,405,357],{},", valide le payload et appelle ",[351,408,409],{},"client.queueHydration()"," pour chaque entrée.",[388,412,413,414,417,418,421,422,425,426,375],{},"Au premier appel ",[351,415,416],{},"fetchQuery\u003CT>"," ou ",[351,419,420],{},"watchQuery\u003CT>"," pour une clé, la valeur en file est castée en ",[351,423,424],{},"T"," et injectée comme état ",[351,427,428],{},"Success",[388,430,431,432,435,436,439],{},"Si ",[351,433,434],{},"updatedAtMs"," est omis ou si les données sont plus anciennes que ",[351,437,438],{},"staleTime",", Qora déclenche automatiquement une revalidation en arrière-plan (SWR).",[377,441],{},[380,443,445],{"id":444},"configuration-serveur","Configuration serveur",[348,447,448,449,451,452,451,455,457],{},"Intégrer les données préchargées dans une balise ",[351,450,393],{}," ",[368,453,454],{},"avant",[351,456,397],{}," :",[459,460,466],"pre",{"className":461,"code":462,"filename":463,"language":464,"meta":465,"style":465},"language-html shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript>\n  window.__QORA_STATE__ = {\n    '[\"users\",1]': {\n      \"data\": { \"id\": 1, \"name\": \"Ada\", \"email\": \"ada@example.com\" },\n      \"updatedAtMs\": 1700000000000\n    },\n    '[\"posts\"]': {\n      \"data\": [\n        { \"id\": 10, \"title\": \"Bonjour le monde\" },\n        { \"id\": 11, \"title\": \"Flutter Web\" }\n      ]\n    }\n  };\n\u003C/script>\n\u003Cscript src=\"main.dart.js\" defer>\u003C/script>\n","index.html","html","",[351,467,468,484,502,519,591,605,611,625,639,676,711,717,723,729,739],{"__ignoreMap":465},[469,470,473,477,481],"span",{"class":471,"line":472},"line",1,[469,474,476],{"class":475},"sMK4o","\u003C",[469,478,480],{"class":479},"swJcz","script",[469,482,483],{"class":475},">\n",[469,485,487,491,493,496,499],{"class":471,"line":486},2,[469,488,490],{"class":489},"sTEyZ","  window",[469,492,375],{"class":475},[469,494,495],{"class":489},"__QORA_STATE__ ",[469,497,498],{"class":475},"=",[469,500,501],{"class":475}," {\n",[469,503,505,508,511,514,517],{"class":471,"line":504},3,[469,506,507],{"class":475},"    '",[469,509,510],{"class":479},"[\"users\",1]",[469,512,513],{"class":475},"'",[469,515,516],{"class":475},":",[469,518,501],{"class":475},[469,520,522,525,528,531,533,536,539,542,544,546,550,553,555,558,560,562,564,568,570,572,574,577,579,581,583,586,588],{"class":471,"line":521},4,[469,523,524],{"class":475},"      \"",[469,526,527],{"class":479},"data",[469,529,530],{"class":475},"\"",[469,532,516],{"class":475},[469,534,535],{"class":475}," {",[469,537,538],{"class":475}," \"",[469,540,541],{"class":479},"id",[469,543,530],{"class":475},[469,545,516],{"class":475},[469,547,549],{"class":548},"sbssI"," 1",[469,551,552],{"class":475},",",[469,554,538],{"class":475},[469,556,557],{"class":479},"name",[469,559,530],{"class":475},[469,561,516],{"class":475},[469,563,538],{"class":475},[469,565,567],{"class":566},"sfazB","Ada",[469,569,530],{"class":475},[469,571,552],{"class":475},[469,573,538],{"class":475},[469,575,576],{"class":479},"email",[469,578,530],{"class":475},[469,580,516],{"class":475},[469,582,538],{"class":475},[469,584,585],{"class":566},"ada@example.com",[469,587,530],{"class":475},[469,589,590],{"class":475}," },\n",[469,592,594,596,598,600,602],{"class":471,"line":593},5,[469,595,524],{"class":475},[469,597,434],{"class":479},[469,599,530],{"class":475},[469,601,516],{"class":475},[469,603,604],{"class":548}," 1700000000000\n",[469,606,608],{"class":471,"line":607},6,[469,609,610],{"class":475},"    },\n",[469,612,614,616,619,621,623],{"class":471,"line":613},7,[469,615,507],{"class":475},[469,617,618],{"class":479},"[\"posts\"]",[469,620,513],{"class":475},[469,622,516],{"class":475},[469,624,501],{"class":475},[469,626,628,630,632,634,636],{"class":471,"line":627},8,[469,629,524],{"class":475},[469,631,527],{"class":479},[469,633,530],{"class":475},[469,635,516],{"class":475},[469,637,638],{"class":489}," [\n",[469,640,642,645,647,649,651,653,656,658,660,663,665,667,669,672,674],{"class":471,"line":641},9,[469,643,644],{"class":475},"        {",[469,646,538],{"class":475},[469,648,541],{"class":479},[469,650,530],{"class":475},[469,652,516],{"class":475},[469,654,655],{"class":548}," 10",[469,657,552],{"class":475},[469,659,538],{"class":475},[469,661,662],{"class":479},"title",[469,664,530],{"class":475},[469,666,516],{"class":475},[469,668,538],{"class":475},[469,670,671],{"class":566},"Bonjour le monde",[469,673,530],{"class":475},[469,675,590],{"class":475},[469,677,679,681,683,685,687,689,692,694,696,698,700,702,704,706,708],{"class":471,"line":678},10,[469,680,644],{"class":475},[469,682,538],{"class":475},[469,684,541],{"class":479},[469,686,530],{"class":475},[469,688,516],{"class":475},[469,690,691],{"class":548}," 11",[469,693,552],{"class":475},[469,695,538],{"class":475},[469,697,662],{"class":479},[469,699,530],{"class":475},[469,701,516],{"class":475},[469,703,538],{"class":475},[469,705,370],{"class":566},[469,707,530],{"class":475},[469,709,710],{"class":475}," }\n",[469,712,714],{"class":471,"line":713},11,[469,715,716],{"class":489},"      ]\n",[469,718,720],{"class":471,"line":719},12,[469,721,722],{"class":475},"    }\n",[469,724,726],{"class":471,"line":725},13,[469,727,728],{"class":475},"  };\n",[469,730,732,735,737],{"class":471,"line":731},14,[469,733,734],{"class":475},"\u003C/",[469,736,480],{"class":479},[469,738,483],{"class":475},[469,740,742,744,746,750,752,754,756,758,761,764,766],{"class":471,"line":741},15,[469,743,476],{"class":475},[469,745,480],{"class":479},[469,747,749],{"class":748},"spNyl"," src",[469,751,498],{"class":475},[469,753,530],{"class":475},[469,755,397],{"class":566},[469,757,530],{"class":475},[469,759,760],{"class":748}," defer",[469,762,763],{"class":475},">\u003C/",[469,765,480],{"class":479},[469,767,483],{"class":475},[348,769,770,771,774,775,778],{},"Les clés sont des clés de requête normalisées encodées en JSON : le même format qu'utilise Qora en interne (ex. ",[351,772,773],{},"'[\"users\",1]'"," pour la clé ",[351,776,777],{},"['users', 1]",").",[348,780,781,783],{},[351,782,434],{}," est optionnel. Quand omis, Qora traite les données comme datant de l'epoch (toujours périmées) : elles sont servies immédiatement mais une revalidation en arrière-plan se déclenche au premier montage.",[377,785],{},[380,787,789],{"id":788},"configuration-flutter","Configuration Flutter",[348,791,792,793,795,796,457],{},"Appeler ",[351,794,402],{}," avant ",[351,797,798],{},"runApp",[459,800,805],{"className":801,"code":802,"filename":803,"language":804,"meta":465,"style":465},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import 'package:flutter/material.dart';\nimport 'package:qora/qora.dart';\nimport 'package:qora_flutter/qora_flutter.dart';\n\nvoid main() {\n  final client = QoraClient();\n\n  // Hydrater depuis window.__QORA_STATE__ (sans opération sur non-web)\n  SsrHydrator(client).hydrate(\n    deserializers: {\n      '[\"users\",1]': (json) => User.fromJson(json as Map\u003CString, dynamic>),\n      '[\"posts\"]':   (json) => (json as List).map(Post.fromJson).toList(),\n    },\n  );\n\n  runApp(QoraScope(client: client, child: const MyApp()));\n}\n","main.dart","dart",[351,806,807,818,827,836,842,854,873,877,883,899,908,955,1003,1010,1017,1021,1057],{"__ignoreMap":465},[469,808,809,812,815],{"class":471,"line":472},[469,810,811],{"class":548},"import",[469,813,814],{"class":566}," 'package:flutter/material.dart'",[469,816,817],{"class":475},";\n",[469,819,820,822,825],{"class":471,"line":486},[469,821,811],{"class":548},[469,823,824],{"class":566}," 'package:qora/qora.dart'",[469,826,817],{"class":475},[469,828,829,831,834],{"class":471,"line":504},[469,830,811],{"class":548},[469,832,833],{"class":566}," 'package:qora_flutter/qora_flutter.dart'",[469,835,817],{"class":475},[469,837,838],{"class":471,"line":521},[469,839,841],{"emptyLinePlaceholder":840},true,"\n",[469,843,844,847,851],{"class":471,"line":593},[469,845,846],{"class":748},"void",[469,848,850],{"class":849},"s2Zo4"," main",[469,852,853],{"class":489},"() {\n",[469,855,856,859,862,864,868,871],{"class":471,"line":607},[469,857,858],{"class":748},"  final",[469,860,861],{"class":489}," client ",[469,863,498],{"class":475},[469,865,867],{"class":866},"sBMFI"," QoraClient",[469,869,870],{"class":489},"()",[469,872,817],{"class":475},[469,874,875],{"class":471,"line":613},[469,876,841],{"emptyLinePlaceholder":840},[469,878,879],{"class":471,"line":627},[469,880,882],{"class":881},"sHwdD","  // Hydrater depuis window.__QORA_STATE__ (sans opération sur non-web)\n",[469,884,885,888,891,893,896],{"class":471,"line":641},[469,886,887],{"class":866},"  SsrHydrator",[469,889,890],{"class":489},"(client)",[469,892,375],{"class":475},[469,894,895],{"class":849},"hydrate",[469,897,898],{"class":489},"(\n",[469,900,901,904,906],{"class":471,"line":678},[469,902,903],{"class":489},"    deserializers",[469,905,516],{"class":475},[469,907,501],{"class":489},[469,909,910,913,915,918,921,924,926,929,932,935,938,940,943,946,949,952],{"class":471,"line":713},[469,911,912],{"class":566},"      '[\"users\",1]'",[469,914,516],{"class":475},[469,916,917],{"class":489}," (json) ",[469,919,920],{"class":475},"=>",[469,922,923],{"class":866}," User",[469,925,375],{"class":475},[469,927,928],{"class":849},"fromJson",[469,930,931],{"class":489},"(json ",[469,933,934],{"class":475},"as",[469,936,937],{"class":866}," Map",[469,939,476],{"class":489},[469,941,942],{"class":866},"String",[469,944,945],{"class":489},", ",[469,947,948],{"class":866},"dynamic",[469,950,951],{"class":489},">)",[469,953,954],{"class":475},",\n",[469,956,957,960,962,965,967,970,972,975,978,980,983,986,989,991,994,996,999,1001],{"class":471,"line":719},[469,958,959],{"class":566},"      '[\"posts\"]'",[469,961,516],{"class":475},[469,963,964],{"class":489},"   (json) ",[469,966,920],{"class":475},[469,968,969],{"class":489}," (json ",[469,971,934],{"class":475},[469,973,974],{"class":866}," List",[469,976,977],{"class":489},")",[469,979,375],{"class":475},[469,981,982],{"class":849},"map",[469,984,985],{"class":489},"(",[469,987,988],{"class":866},"Post",[469,990,375],{"class":475},[469,992,993],{"class":489},"fromJson)",[469,995,375],{"class":475},[469,997,998],{"class":849},"toList",[469,1000,870],{"class":489},[469,1002,954],{"class":475},[469,1004,1005,1008],{"class":471,"line":725},[469,1006,1007],{"class":489},"    }",[469,1009,954],{"class":475},[469,1011,1012,1015],{"class":471,"line":731},[469,1013,1014],{"class":489},"  )",[469,1016,817],{"class":475},[469,1018,1019],{"class":471,"line":741},[469,1020,841],{"emptyLinePlaceholder":840},[469,1022,1024,1027,1029,1031,1034,1036,1039,1041,1044,1046,1049,1052,1055],{"class":471,"line":1023},16,[469,1025,1026],{"class":849},"  runApp",[469,1028,985],{"class":489},[469,1030,103],{"class":866},[469,1032,1033],{"class":489},"(client",[469,1035,516],{"class":475},[469,1037,1038],{"class":489}," client",[469,1040,552],{"class":475},[469,1042,1043],{"class":489}," child",[469,1045,516],{"class":475},[469,1047,1048],{"class":748}," const",[469,1050,1051],{"class":866}," MyApp",[469,1053,1054],{"class":489},"()))",[469,1056,817],{"class":475},[469,1058,1060],{"class":471,"line":1059},17,[469,1061,1062],{"class":489},"}\n",[348,1064,1065,1066,1068,1069,1072,1073,1075,1076,1078,1079,1082,1083,1086,1087,1090],{},"Les clés de ",[351,1067,357],{}," absentes de ",[351,1070,1071],{},"deserializers"," sont silencieusement ignorées. Si ",[351,1074,1071],{}," est entièrement omis, les valeurs ",[351,1077,948],{}," brutes de ",[351,1080,1081],{},"dartify()"," sont mises en file directement : adapté quand les données sont déjà des ",[351,1084,1085],{},"Map","/",[351,1088,1089],{},"List"," simples.",[377,1092],{},[380,1094,1096],{"id":1095},"sécurité","Sécurité",[348,1098,1099,1101],{},[351,1100,353],{}," est sûr contre les XSS par conception :",[1103,1104,1105,1118,1131],"ul",{},[388,1106,1107,1108,1110,1111,1114,1115,375],{},"Utilise ",[351,1109,1081],{}," pour la conversion JS → Dart : produit des maps/listes/chaînes simples, jamais de HTML. Pas d'",[351,1112,1113],{},"innerHTML"," ni d'",[351,1116,1117],{},"eval",[388,1119,1120,1121,1123,1124,1126,1127,1130],{},"Valide le type de niveau supérieur (",[351,1122,1085],{},") et chaque entrée (",[351,1125,1085],{}," avec une clé ",[351,1128,1129],{},"'data'",") avant traitement.",[388,1132,1133,1134,1137],{},"Encapsule chaque appel au désérialiseur dans un ",[351,1135,1136],{},"try/catch"," : une entrée corrompue ne peut pas planter l'application.",[348,1139,1140,1143,1144,1147],{},[368,1141,1142],{},"Responsabilité :"," encoder en JSON les données contrôlées par l'utilisateur côté serveur avant de les intégrer dans ",[351,1145,1146],{},"__QORA_STATE__",". L'interpolation HTML brute contourne les protections de Qora et permet des XSS.",[377,1149],{},[380,1151,1153],{"id":1152},"fraîcheur-et-swr","Fraîcheur et SWR",[348,1155,1156,1157,1159,1160,1163,1164,1166],{},"L'horodatage ",[351,1158,434],{}," est stocké comme ",[351,1161,1162],{},"updatedAt"," sur l'état ",[351,1165,428],{}," injecté. La logique stale-while-revalidate de Qora l'utilise pour décider de déclencher un fetch en arrière-plan :",[459,1168,1170],{"className":801,"code":1169,"filename":803,"language":804,"meta":465,"style":465},"// staleTime: 5 minutes\n// updatedAtMs: il y a 4 minutes → frais, pas de fetch en arrière-plan\n// updatedAtMs: il y a 6 minutes → périmé, SWR se déclenche immédiatement au montage\n// updatedAtMs: absent           → toujours périmé\nclient.watchQuery\u003CUser>(\n  key: ['users', 1],\n  fetcher: () => api.getUser(1),\n  options: const QoraOptions(staleTime: Duration(minutes: 5)),\n);\n",[351,1171,1172,1177,1182,1187,1192,1210,1232,1261,1294],{"__ignoreMap":465},[469,1173,1174],{"class":471,"line":472},[469,1175,1176],{"class":881},"// staleTime: 5 minutes\n",[469,1178,1179],{"class":471,"line":486},[469,1180,1181],{"class":881},"// updatedAtMs: il y a 4 minutes → frais, pas de fetch en arrière-plan\n",[469,1183,1184],{"class":471,"line":504},[469,1185,1186],{"class":881},"// updatedAtMs: il y a 6 minutes → périmé, SWR se déclenche immédiatement au montage\n",[469,1188,1189],{"class":471,"line":521},[469,1190,1191],{"class":881},"// updatedAtMs: absent           → toujours périmé\n",[469,1193,1194,1197,1199,1202,1204,1207],{"class":471,"line":593},[469,1195,1196],{"class":489},"client",[469,1198,375],{"class":475},[469,1200,1201],{"class":849},"watchQuery",[469,1203,476],{"class":489},[469,1205,1206],{"class":866},"User",[469,1208,1209],{"class":489},">(\n",[469,1211,1212,1215,1217,1220,1223,1225,1227,1230],{"class":471,"line":607},[469,1213,1214],{"class":489},"  key",[469,1216,516],{"class":475},[469,1218,1219],{"class":489}," [",[469,1221,1222],{"class":566},"'users'",[469,1224,552],{"class":475},[469,1226,549],{"class":548},[469,1228,1229],{"class":489},"]",[469,1231,954],{"class":475},[469,1233,1234,1237,1239,1242,1244,1247,1249,1252,1254,1257,1259],{"class":471,"line":613},[469,1235,1236],{"class":489},"  fetcher",[469,1238,516],{"class":475},[469,1240,1241],{"class":489}," () ",[469,1243,920],{"class":475},[469,1245,1246],{"class":489}," api",[469,1248,375],{"class":475},[469,1250,1251],{"class":849},"getUser",[469,1253,985],{"class":489},[469,1255,1256],{"class":548},"1",[469,1258,977],{"class":489},[469,1260,954],{"class":475},[469,1262,1263,1266,1268,1270,1273,1276,1278,1281,1284,1286,1289,1292],{"class":471,"line":627},[469,1264,1265],{"class":489},"  options",[469,1267,516],{"class":475},[469,1269,1048],{"class":748},[469,1271,1272],{"class":866}," QoraOptions",[469,1274,1275],{"class":489},"(staleTime",[469,1277,516],{"class":475},[469,1279,1280],{"class":866}," Duration",[469,1282,1283],{"class":489},"(minutes",[469,1285,516],{"class":475},[469,1287,1288],{"class":548}," 5",[469,1290,1291],{"class":489},"))",[469,1293,954],{"class":475},[469,1295,1296,1298],{"class":471,"line":641},[469,1297,977],{"class":489},[469,1299,817],{"class":475},[377,1301],{},[380,1303,1305,1306],{"id":1304},"api-ssrhydrator","API ",[351,1307,353],{},[1309,1310,1312],"h3",{"id":1311},"constructeur","Constructeur",[459,1314,1316],{"className":801,"code":1315,"language":804,"meta":465,"style":465},"const SsrHydrator(QoraClient client)\n",[351,1317,1318],{"__ignoreMap":465},[469,1319,1320,1323,1326,1328,1330],{"class":471,"line":472},[469,1321,1322],{"class":748},"const",[469,1324,1325],{"class":866}," SsrHydrator",[469,1327,985],{"class":489},[469,1329,202],{"class":866},[469,1331,1332],{"class":489}," client)\n",[1309,1334,1335],{"id":895},[351,1336,895],{},[459,1338,1340],{"className":801,"code":1339,"language":804,"meta":465,"style":465},"void hydrate({Map\u003CString, dynamic Function(dynamic)>? deserializers})\n",[351,1341,1342],{"__ignoreMap":465},[469,1343,1344,1346,1349,1352,1354,1356,1358,1360,1362,1365,1367,1369,1372,1375],{"class":471,"line":472},[469,1345,846],{"class":748},[469,1347,1348],{"class":849}," hydrate",[469,1350,1351],{"class":489},"({",[469,1353,1085],{"class":866},[469,1355,476],{"class":489},[469,1357,942],{"class":866},[469,1359,945],{"class":489},[469,1361,948],{"class":866},[469,1363,1364],{"class":866}," Function",[469,1366,985],{"class":489},[469,1368,948],{"class":866},[469,1370,1371],{"class":489},")>",[469,1373,1374],{"class":475},"?",[469,1376,1377],{"class":489}," deserializers})\n",[348,1379,1380,1381,1383],{},"Lire ",[351,1382,357],{}," et mettre en file les entrées d'hydratation.",[1385,1386,1387,1403],"table",{},[1388,1389,1390],"thead",{},[1391,1392,1393,1397,1400],"tr",{},[1394,1395,1396],"th",{},"Paramètre",[1394,1398,1399],{},"Type",[1394,1401,1402],{},"Description",[1404,1405,1406],"tbody",{},[1391,1407,1408,1413,1418],{},[1409,1410,1411],"td",{},[351,1412,1071],{},[1409,1414,1415],{},[351,1416,1417],{},"Map\u003CString, dynamic Function(dynamic)>?",[1409,1419,1420,1421,1424],{},"Map de clé encodée en chaîne vers une fonction convertissant le JSON brut en Dart typé. Les clés absentes de cette map sont ignorées. Passer ",[351,1422,1423],{},"null"," pour mettre en file les valeurs brutes.",[377,1426],{},[380,1428,1430,1431],{"id":1429},"avec-persistqoraclient","Avec ",[351,1432,229],{},[348,1434,1435,1437,1438,1440,1441,1444],{},[351,1436,353],{}," et ",[351,1439,229],{}," utilisent tous deux ",[351,1442,1443],{},"queueHydration()"," en interne. Ils se composent sans conflit : la dernière écriture pour une clé donnée gagne (le premier accès typé la récupère) :",[459,1446,1448],{"className":801,"code":1447,"filename":803,"language":804,"meta":465,"style":465},"final client = PersistQoraClient(storage: storage);\nclient.registerSerializer\u003CUser>(...);\n\nawait storage.init();\nawait client.hydrate();           // depuis le disque\nSsrHydrator(client).hydrate(...); // depuis le serveur (écrase l'entrée disque si la clé correspond)\n\nrunApp(QoraScope(client: client, child: const MyApp()));\n",[351,1449,1450,1472,1495,1499,1517,1535,1556,1560],{"__ignoreMap":465},[469,1451,1452,1455,1457,1459,1462,1465,1467,1470],{"class":471,"line":472},[469,1453,1454],{"class":748},"final",[469,1456,861],{"class":489},[469,1458,498],{"class":475},[469,1460,1461],{"class":866}," PersistQoraClient",[469,1463,1464],{"class":489},"(storage",[469,1466,516],{"class":475},[469,1468,1469],{"class":489}," storage)",[469,1471,817],{"class":475},[469,1473,1474,1476,1478,1481,1483,1485,1488,1491,1493],{"class":471,"line":486},[469,1475,1196],{"class":489},[469,1477,375],{"class":475},[469,1479,1480],{"class":849},"registerSerializer",[469,1482,476],{"class":489},[469,1484,1206],{"class":866},[469,1486,1487],{"class":489},">(",[469,1489,1490],{"class":475},"...",[469,1492,977],{"class":489},[469,1494,817],{"class":475},[469,1496,1497],{"class":471,"line":504},[469,1498,841],{"emptyLinePlaceholder":840},[469,1500,1501,1505,1508,1510,1513,1515],{"class":471,"line":521},[469,1502,1504],{"class":1503},"s7zQu","await",[469,1506,1507],{"class":489}," storage",[469,1509,375],{"class":475},[469,1511,1512],{"class":849},"init",[469,1514,870],{"class":489},[469,1516,817],{"class":475},[469,1518,1519,1521,1523,1525,1527,1529,1532],{"class":471,"line":593},[469,1520,1504],{"class":1503},[469,1522,1038],{"class":489},[469,1524,375],{"class":475},[469,1526,895],{"class":849},[469,1528,870],{"class":489},[469,1530,1531],{"class":475},";",[469,1533,1534],{"class":881},"           // depuis le disque\n",[469,1536,1537,1539,1541,1543,1545,1547,1549,1551,1553],{"class":471,"line":607},[469,1538,353],{"class":866},[469,1540,890],{"class":489},[469,1542,375],{"class":475},[469,1544,895],{"class":849},[469,1546,985],{"class":489},[469,1548,1490],{"class":475},[469,1550,977],{"class":489},[469,1552,1531],{"class":475},[469,1554,1555],{"class":881}," // depuis le serveur (écrase l'entrée disque si la clé correspond)\n",[469,1557,1558],{"class":471,"line":613},[469,1559,841],{"emptyLinePlaceholder":840},[469,1561,1562,1564,1566,1568,1570,1572,1574,1576,1578,1580,1582,1584,1586],{"class":471,"line":627},[469,1563,798],{"class":849},[469,1565,985],{"class":489},[469,1567,103],{"class":866},[469,1569,1033],{"class":489},[469,1571,516],{"class":475},[469,1573,1038],{"class":489},[469,1575,552],{"class":475},[469,1577,1043],{"class":489},[469,1579,516],{"class":475},[469,1581,1048],{"class":748},[469,1583,1051],{"class":866},[469,1585,1054],{"class":489},[469,1587,817],{"class":475},[377,1589],{},[380,1591,1593],{"id":1592},"voir-aussi","Voir aussi",[1103,1595,1596,1606,1619],{},[388,1597,1598,1603,1604],{},[1599,1600,1602],"a",{"href":1601},"./persistence","Guide de persistance"," : Cache sur disque avec ",[351,1605,229],{},[388,1607,1608,1612,1613,945,1616],{},[1599,1609,1611],{"href":1610},"../api-reference/qora-client","API QoraClient"," : ",[351,1614,1615],{},"queueHydration",[351,1617,1618],{},"hydrateQuery",[388,1620,1621],{},[1599,1622,21],{"href":1623},"../getting-started/quick-start",[1625,1626,1627],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .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":465,"searchDepth":486,"depth":486,"links":1629},[1630,1631,1632,1633,1634,1635,1640,1642],{"id":382,"depth":486,"text":383},{"id":444,"depth":486,"text":445},{"id":788,"depth":486,"text":789},{"id":1095,"depth":486,"text":1096},{"id":1152,"depth":486,"text":1153},{"id":1304,"depth":486,"text":1636,"children":1637},"API SsrHydrator",[1638,1639],{"id":1311,"depth":504,"text":1312},{"id":895,"depth":504,"text":895},{"id":1429,"depth":486,"text":1641},"Avec PersistQoraClient",{"id":1592,"depth":486,"text":1593},"Éliminer le flash de chargement sur les pages Flutter Web rendues côté serveur en injectant le cache serveur dans QoraClient via SsrHydrator.","md",null,{},{"icon":180},{"title":177,"description":1643},"f_Df9C_PcKqUQmbfJR1MjmKt3Rf3FnngwINpx1RI9N0",[1651,1653],{"title":172,"path":173,"stem":174,"description":1652,"icon":175,"children":-1},"Utiliser CancelToken pour interrompre coopérativement les fetchs en cours : lors de la navigation, d'un timeout ou d'une action utilisateur.",{"title":182,"path":183,"stem":184,"description":1654,"icon":185,"children":-1},"Comprendre comment Qora remonte les erreurs, configure le comportement de retry et active la dégradation gracieuse avec previousData.",1794040408895]