[{"data":1,"prerenderedAt":3267},["ShallowReactive",2],{"navigation_docs_en":3,"-en-help-troubleshooting":342,"-en-help-troubleshooting-surround":3264},[4,45,91,137,195,236,257,291,327],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","/en/getting-started","en/01.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"What is Qora?","/en/getting-started/what-is-qora","en/01.getting-started/2.what-is-qora","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Installation","/en/getting-started/installation","en/01.getting-started/3.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":6},"Quick Start","/en/getting-started/quick-start","en/01.getting-started/4.quick-start",{"title":25,"path":26,"stem":27,"icon":28},"Comparison","/en/getting-started/comparison","en/01.getting-started/5.comparison","i-lucide-scale",{"title":30,"path":31,"stem":32,"icon":33},"Coming from TanStack Query","/en/getting-started/coming-from-tanstack-query","en/01.getting-started/6.coming-from-tanstack-query","i-lucide-arrow-left-right",{"title":35,"path":36,"stem":37,"icon":38},"Migrating from Other Libraries","/en/getting-started/migrating-from-other-libraries","en/01.getting-started/7.migrating-from-other-libraries","i-lucide-arrow-right-left",{"title":40,"path":41,"stem":42,"icon":43},"AI Assistants","/en/getting-started/ai-assistants","en/01.getting-started/8.ai-assistants","i-lucide-sparkles",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"Core Concepts","i-lucide-book-open","/en/core-concepts","en/02.core-concepts",[51,56,61,66,71,76,81,86],{"title":52,"path":53,"stem":54,"icon":55},"Queries","/en/core-concepts/queries","en/02.core-concepts/1.queries","i-lucide-database",{"title":57,"path":58,"stem":59,"icon":60},"Query Keys","/en/core-concepts/query-keys","en/02.core-concepts/2.query-keys","i-lucide-key-round",{"title":62,"path":63,"stem":64,"icon":65},"Query States","/en/core-concepts/query-states","en/02.core-concepts/3.query-states","i-lucide-activity",{"title":67,"path":68,"stem":69,"icon":70},"Caching","/en/core-concepts/caching","en/02.core-concepts/4.caching","i-lucide-layers-3",{"title":72,"path":73,"stem":74,"icon":75},"Stale-While-Revalidate","/en/core-concepts/stale-while-revalidate","en/02.core-concepts/5.stale-while-revalidate","i-lucide-timer-reset",{"title":77,"path":78,"stem":79,"icon":80},"Deduplication","/en/core-concepts/deduplication","en/02.core-concepts/6.deduplication","i-lucide-copy-minus",{"title":82,"path":83,"stem":84,"icon":85},"Mutations & Invalidation","/en/core-concepts/mutations","en/02.core-concepts/7.mutations","i-lucide-pencil-line",{"title":87,"path":88,"stem":89,"icon":90},"Offline & Network","/en/core-concepts/offline","en/02.core-concepts/8.offline","i-lucide-wifi-off",{"title":92,"icon":93,"path":94,"stem":95,"children":96,"page":44},"Flutter Integration","i-lucide-smartphone","/en/flutter-integration","en/03.flutter-integration",[97,102,107,112,117,122,127,132],{"title":98,"path":99,"stem":100,"icon":101},"Setup","/en/flutter-integration/setup","en/03.flutter-integration/1.setup","i-lucide-wrench",{"title":103,"path":104,"stem":105,"icon":106},"QoraScope","/en/flutter-integration/qora-scope","en/03.flutter-integration/2.qora-scope","i-lucide-share-2",{"title":108,"path":109,"stem":110,"icon":111},"QoraBuilder","/en/flutter-integration/qora-builder","en/03.flutter-integration/3.qora-builder","i-lucide-blocks",{"title":113,"path":114,"stem":115,"icon":116},"QoraMutationBuilder","/en/flutter-integration/qora-mutation-builder","en/03.flutter-integration/4.qora-mutation-builder","i-lucide-pencil",{"title":118,"path":119,"stem":120,"icon":121},"InfiniteQueryBuilder","/en/flutter-integration/infinite-query-builder","en/03.flutter-integration/5.infinite-query-builder","i-lucide-infinity",{"title":123,"path":124,"stem":125,"icon":126},"Hooks (flutter_hooks)","/en/flutter-integration/hooks","en/03.flutter-integration/6.hooks","i-lucide-anchor",{"title":128,"path":129,"stem":130,"icon":131},"Network Status Widgets","/en/flutter-integration/network-status","en/03.flutter-integration/7.network-status","i-lucide-wifi",{"title":133,"path":134,"stem":135,"icon":136},"Best Practices","/en/flutter-integration/best-practices","en/03.flutter-integration/8.best-practices","i-lucide-badge-check",{"title":138,"icon":139,"path":140,"stem":141,"children":142,"page":44},"Recipes","i-lucide-chef-hat","/en/recipes","en/04.recipes",[143,147,152,157,162,166,171,176,181,186,191],{"title":144,"path":145,"stem":146,"icon":85},"Mutations","/en/recipes/mutations","en/04.recipes/02.mutations",{"title":148,"path":149,"stem":150,"icon":151},"Optimistic Updates","/en/recipes/optimistic-updates","en/04.recipes/03.optimistic-updates","i-lucide-zap",{"title":153,"path":154,"stem":155,"icon":156},"Persistence","/en/recipes/persistence","en/04.recipes/04.persistence","i-lucide-hard-drive",{"title":158,"path":159,"stem":160,"icon":161},"Network Aware","/en/recipes/network-aware","en/04.recipes/05.network-aware","i-lucide-signal",{"title":163,"path":164,"stem":165,"icon":121},"Infinite Queries","/en/recipes/infinite-queries","en/04.recipes/06.infinite-queries",{"title":167,"path":168,"stem":169,"icon":170},"Dependent Queries","/en/recipes/dependent-queries","en/04.recipes/07.dependent-queries","i-lucide-link-2",{"title":172,"path":173,"stem":174,"icon":175},"Cancellation","/en/recipes/cancel-token","en/04.recipes/08.cancel-token","i-lucide-circle-slash",{"title":177,"path":178,"stem":179,"icon":180},"SSR Hydration","/en/recipes/ssr-hydration","en/04.recipes/09.ssr-hydration","i-lucide-server",{"title":182,"path":183,"stem":184,"icon":185},"Error Handling","/en/recipes/error-handling","en/04.recipes/10.error-handling","i-lucide-shield-alert",{"title":187,"path":188,"stem":189,"icon":190},"Testing","/en/recipes/testing","en/04.recipes/11.testing","i-lucide-flask-conical",{"title":192,"path":193,"stem":194},"Route-Level Prefetching","/en/recipes/prefetch","en/04.recipes/12.prefetch",{"title":196,"icon":197,"path":198,"stem":199,"children":200,"page":44},"API Reference","i-lucide-file-code","/en/api-reference","en/05.api-reference",[201,206,210,214,219,224,228,232],{"title":202,"path":203,"stem":204,"icon":205},"QoraClient","/en/api-reference/qora-client","en/05.api-reference/1.qora-client","i-lucide-cpu",{"title":207,"path":208,"stem":209,"icon":60},"QoraKey","/en/api-reference/qora-key","en/05.api-reference/2.qora-key",{"title":211,"path":212,"stem":213,"icon":65},"QoraState","/en/api-reference/qora-state","en/05.api-reference/3.qora-state",{"title":215,"path":216,"stem":217,"icon":218},"QoraOptions","/en/api-reference/qora-options","en/05.api-reference/4.qora-options","i-lucide-sliders-horizontal",{"title":220,"path":221,"stem":222,"icon":223},"QoraClientConfig","/en/api-reference/qora-client-config","en/05.api-reference/5.qora-client-config","i-lucide-settings-2",{"title":225,"path":226,"stem":227,"icon":85},"Mutation API","/en/api-reference/qora-mutation","en/05.api-reference/6.qora-mutation",{"title":229,"path":230,"stem":231,"icon":156},"PersistQoraClient","/en/api-reference/persist-qora-client","en/05.api-reference/7.persist-qora-client",{"title":233,"path":234,"stem":235,"icon":121},"Infinite Query","/en/api-reference/infinite-query","en/05.api-reference/8.infinite-query",{"title":237,"icon":238,"path":239,"stem":240,"children":241,"page":44},"DevTools","i-lucide-bug","/en/devtools","en/06.devtools",[242,247,252],{"title":243,"path":244,"stem":245,"icon":246},"Overview","/en/devtools/overview","en/06.devtools/1.overview","i-lucide-layout-dashboard",{"title":248,"path":249,"stem":250,"icon":251},"In-App Overlay","/en/devtools/overlay","en/06.devtools/2.overlay","i-lucide-layers",{"title":253,"path":254,"stem":255,"icon":256},"Data Serialization","/en/devtools/data-display","en/06.devtools/4.data-display","i-lucide-eye",{"title":258,"icon":259,"path":260,"stem":261,"children":262,"page":44},"Third Party","i-lucide-puzzle","/en/third-party","en/07.third-party",[263,268,272,277,282,286],{"title":264,"path":265,"stem":266,"icon":267},"With Provider","/en/third-party/with-provider","en/07.third-party/1.with-provider","i-lucide-plug",{"title":269,"path":270,"stem":271,"icon":111},"With BLoC","/en/third-party/with-bloc","en/07.third-party/2.with-bloc",{"title":273,"path":274,"stem":275,"icon":276},"With Riverpod","/en/third-party/with-riverpod","en/07.third-party/3.with-riverpod","i-lucide-droplets",{"title":278,"path":279,"stem":280,"icon":281},"With RxDart","/en/third-party/with-rxdart","en/07.third-party/4.with-rxdart","i-lucide-git-branch",{"title":283,"path":284,"stem":285},"With Dio","/en/third-party/with-dio","en/07.third-party/5.with-dio",{"title":287,"path":288,"stem":289,"icon":290},"With GraphQL","/en/third-party/with-graphql","en/07.third-party/6.with-graphql","i-lucide-binary",{"title":292,"icon":190,"path":293,"stem":294,"children":295,"page":44},"Examples","/en/examples","en/08.examples",[296,301,305,310,314,318,322],{"title":297,"path":298,"stem":299,"icon":300},"Case Study: User List & Detail","/en/examples/basic-query","en/08.examples/1.basic-query","i-lucide-play-circle",{"title":302,"path":303,"stem":304,"icon":151},"Case Study: Optimistic Mutations & Rollback","/en/examples/mutations-optimistic","en/08.examples/2.mutations-optimistic",{"title":306,"path":307,"stem":308,"icon":309},"Case Study: Infinite Scroll Feed","/en/examples/infinite-scroll","en/08.examples/3.infinite-scroll","i-lucide-scroll",{"title":311,"path":312,"stem":313,"icon":90},"Case Study: Offline-First Todo App","/en/examples/offline-first","en/08.examples/4.offline-first",{"title":315,"path":316,"stem":317,"icon":161},"Case Study: Network Awareness","/en/examples/network-awareness","en/08.examples/5.network-awareness",{"title":319,"path":320,"stem":321,"icon":126},"Case Study: Hooks Integration","/en/examples/hooks-integration","en/08.examples/6.hooks-integration",{"title":323,"path":324,"stem":325,"icon":326},"Case Study: Complete Todo App","/en/examples/complete-todo-app","en/08.examples/7.complete-todo-app","i-lucide-check-square",{"title":328,"icon":329,"path":330,"stem":331,"children":332,"page":44},"Help","i-lucide-life-buoy","/en/help","en/09.help",[333,338],{"title":334,"path":335,"stem":336,"icon":337},"FAQ","/en/help/faq","en/09.help/1.faq","i-lucide-circle-help",{"title":339,"path":340,"stem":341,"icon":101},"Troubleshooting","/en/help/troubleshooting","en/09.help/2.troubleshooting",{"id":343,"title":339,"body":344,"description":3257,"extension":3258,"links":3259,"meta":3260,"navigation":3261,"path":340,"seo":3262,"stem":341,"__hash__":3263},"docs_en/en/09.help/2.troubleshooting.md",{"type":345,"value":346,"toc":3210},"minimark",[347,352,365,440,443,447,452,462,472,658,665,667,674,688,797,799,803,813,1003,1005,1013,1029,1125,1134,1136,1143,1151,1159,1162,1318,1332,1334,1338,1346,1361,1407,1425,1427,1434,1449,1597,1616,1641,1643,1647,1657,1754,1764,1766,1770,1778,1835,1848,1850,1854,1858,1867,2002,2004,2010,2026,2154,2157,2159,2170,2191,2263,2265,2268,2272,2281,2460,2462,2471,2498,2531,2660,2662,2665,2674,2688,2752,2762,2764,2768,2772,2782,2794,2872,2884,2886,2890,2895,2906,2908,2911,2918,2936,3051,3053,3060,3076,3082,3206],[348,349,351],"h2",{"id":350},"enable-debug-mode-first","Enable debug mode first",[353,354,355,356,360,361,364],"p",{},"Enable ",[357,358,359],"code",{},"debugMode"," before any investigation. Qora logs cache hits, cache misses, persistence writes, hydration skips, and serializer errors with the ",[357,362,363],{},"[Qora]"," prefix.",[366,367,373],"pre",{"className":368,"code":369,"filename":370,"language":371,"meta":372,"style":372},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","final client = QoraClient( // or PersistQoraClient\n  config: const QoraClientConfig(debugMode: true),\n);\n","main.dart","dart","",[357,374,375,403,432],{"__ignoreMap":372},[376,377,380,384,388,392,396,399],"span",{"class":378,"line":379},"line",1,[376,381,383],{"class":382},"spNyl","final",[376,385,387],{"class":386},"sTEyZ"," client ",[376,389,391],{"class":390},"sMK4o","=",[376,393,395],{"class":394},"sBMFI"," QoraClient",[376,397,398],{"class":386},"( ",[376,400,402],{"class":401},"sHwdD","// or PersistQoraClient\n",[376,404,406,409,412,415,418,421,423,426,429],{"class":378,"line":405},2,[376,407,408],{"class":386},"  config",[376,410,411],{"class":390},":",[376,413,414],{"class":382}," const",[376,416,417],{"class":394}," QoraClientConfig",[376,419,420],{"class":386},"(debugMode",[376,422,411],{"class":390},[376,424,425],{"class":390}," true",[376,427,428],{"class":386},")",[376,430,431],{"class":390},",\n",[376,433,435,437],{"class":378,"line":434},3,[376,436,428],{"class":386},[376,438,439],{"class":390},";\n",[441,442],"hr",{},[348,444,446],{"id":445},"persistence-hydration","Persistence & Hydration",[448,449,451],"h3",{"id":450},"data-is-not-persisted-across-restarts","Data is not persisted across restarts",[353,453,454,458,459,461],{},[455,456,457],"strong",{},"Symptom",": ",[357,460,229],{}," is configured, but the application always starts with a loading state and no cached data.",[353,463,464,467,468,471],{},[455,465,466],{},"Cause",": No ",[357,469,470],{},"QoraSerializer\u003CT>"," is registered for the fetched type. Qora caches the data in memory but does not persist it to disk.",[366,473,475],{"className":368,"code":474,"filename":370,"language":371,"meta":372,"style":372},"// Good: Register before calling hydrate()\nclient.registerSerializer\u003CList\u003CPost>>(\n  QoraSerializer(\n    toJson:   (posts) => posts.map((p) => p.toJson()).toList(),\n    fromJson: (json)  => (json as List).map(Post.fromJson).toList(),\n  ),\n  name: 'List\u003CPost>',\n);\nawait client.hydrate();\n",[357,476,477,482,508,516,564,610,618,632,639],{"__ignoreMap":372},[376,478,479],{"class":378,"line":379},[376,480,481],{"class":401},"// Good: Register before calling hydrate()\n",[376,483,484,487,490,494,497,500,502,505],{"class":378,"line":405},[376,485,486],{"class":386},"client",[376,488,489],{"class":390},".",[376,491,493],{"class":492},"s2Zo4","registerSerializer",[376,495,496],{"class":386},"\u003C",[376,498,499],{"class":394},"List",[376,501,496],{"class":386},[376,503,504],{"class":394},"Post",[376,506,507],{"class":386},">>(\n",[376,509,510,513],{"class":378,"line":434},[376,511,512],{"class":394},"  QoraSerializer",[376,514,515],{"class":386},"(\n",[376,517,519,522,524,527,530,533,535,538,541,543,546,548,551,554,556,559,562],{"class":378,"line":518},4,[376,520,521],{"class":386},"    toJson",[376,523,411],{"class":390},[376,525,526],{"class":386},"   (posts) ",[376,528,529],{"class":390},"=>",[376,531,532],{"class":386}," posts",[376,534,489],{"class":390},[376,536,537],{"class":492},"map",[376,539,540],{"class":386},"((p) ",[376,542,529],{"class":390},[376,544,545],{"class":386}," p",[376,547,489],{"class":390},[376,549,550],{"class":492},"toJson",[376,552,553],{"class":386},"())",[376,555,489],{"class":390},[376,557,558],{"class":492},"toList",[376,560,561],{"class":386},"()",[376,563,431],{"class":390},[376,565,567,570,572,575,577,580,583,586,588,590,592,595,597,599,602,604,606,608],{"class":378,"line":566},5,[376,568,569],{"class":386},"    fromJson",[376,571,411],{"class":390},[376,573,574],{"class":386}," (json)  ",[376,576,529],{"class":390},[376,578,579],{"class":386}," (json ",[376,581,582],{"class":390},"as",[376,584,585],{"class":394}," List",[376,587,428],{"class":386},[376,589,489],{"class":390},[376,591,537],{"class":492},[376,593,594],{"class":386},"(",[376,596,504],{"class":394},[376,598,489],{"class":390},[376,600,601],{"class":386},"fromJson)",[376,603,489],{"class":390},[376,605,558],{"class":492},[376,607,561],{"class":386},[376,609,431],{"class":390},[376,611,613,616],{"class":378,"line":612},6,[376,614,615],{"class":386},"  )",[376,617,431],{"class":390},[376,619,621,624,626,630],{"class":378,"line":620},7,[376,622,623],{"class":386},"  name",[376,625,411],{"class":390},[376,627,629],{"class":628},"sfazB"," 'List\u003CPost>'",[376,631,431],{"class":390},[376,633,635,637],{"class":378,"line":634},8,[376,636,428],{"class":386},[376,638,439],{"class":390},[376,640,642,646,649,651,654,656],{"class":378,"line":641},9,[376,643,645],{"class":644},"s7zQu","await",[376,647,648],{"class":386}," client",[376,650,489],{"class":390},[376,652,653],{"class":492},"hydrate",[376,655,561],{"class":386},[376,657,439],{"class":390},[353,659,660,661,664],{},"With ",[357,662,663],{},"debugMode: true",", Qora logs the skipped persistence event for unregistered types.",[441,666],{},[448,668,670,673],{"id":669},"hydrate-runs-but-the-cache-is-still-empty",[357,671,672],{},"hydrate()"," runs but the cache is still empty",[353,675,676,458,678,680,681,683,684,687],{},[455,677,466],{},[357,679,493],{}," is called after ",[357,682,672],{},". During hydration, Qora resolves serializers from stored ",[357,685,686],{},"typeName"," values. Entries without a matching serializer are skipped.",[366,689,691],{"className":368,"code":690,"filename":370,"language":371,"meta":372,"style":372},"// Wrong order\nawait client.hydrate();\nclient.registerSerializer\u003CUser>(...); // too late. User entries are skipped\n\n// Correct order\nclient.registerSerializer\u003CUser>(...);\nawait client.hydrate();\nrunApp(...);\n",[357,692,693,698,712,739,745,750,770,784],{"__ignoreMap":372},[376,694,695],{"class":378,"line":379},[376,696,697],{"class":401},"// Wrong order\n",[376,699,700,702,704,706,708,710],{"class":378,"line":405},[376,701,645],{"class":644},[376,703,648],{"class":386},[376,705,489],{"class":390},[376,707,653],{"class":492},[376,709,561],{"class":386},[376,711,439],{"class":390},[376,713,714,716,718,720,722,725,728,731,733,736],{"class":378,"line":434},[376,715,486],{"class":386},[376,717,489],{"class":390},[376,719,493],{"class":492},[376,721,496],{"class":386},[376,723,724],{"class":394},"User",[376,726,727],{"class":386},">(",[376,729,730],{"class":390},"...",[376,732,428],{"class":386},[376,734,735],{"class":390},";",[376,737,738],{"class":401}," // too late. User entries are skipped\n",[376,740,741],{"class":378,"line":518},[376,742,744],{"emptyLinePlaceholder":743},true,"\n",[376,746,747],{"class":378,"line":566},[376,748,749],{"class":401},"// Correct order\n",[376,751,752,754,756,758,760,762,764,766,768],{"class":378,"line":612},[376,753,486],{"class":386},[376,755,489],{"class":390},[376,757,493],{"class":492},[376,759,496],{"class":386},[376,761,724],{"class":394},[376,763,727],{"class":386},[376,765,730],{"class":390},[376,767,428],{"class":386},[376,769,439],{"class":390},[376,771,772,774,776,778,780,782],{"class":378,"line":620},[376,773,645],{"class":644},[376,775,648],{"class":386},[376,777,489],{"class":390},[376,779,653],{"class":492},[376,781,561],{"class":386},[376,783,439],{"class":390},[376,785,786,789,791,793,795],{"class":378,"line":634},[376,787,788],{"class":492},"runApp",[376,790,594],{"class":386},[376,792,730],{"class":390},[376,794,428],{"class":386},[376,796,439],{"class":390},[441,798],{},[448,800,802],{"id":801},"cache-is-warm-but-widgets-still-show-a-spinner-on-first-frame","Cache is warm but widgets still show a spinner on first frame",[353,804,805,458,807,809,810,812],{},[455,806,466],{},[357,808,672],{}," is not awaited before ",[357,811,788],{},". The widget tree is mounted before hydration completes.",[366,814,816],{"className":368,"code":815,"filename":370,"language":371,"meta":372,"style":372},"// Bad: hydrate() fires but isn't awaited\nvoid main() {\n  client.hydrate(); // no await\n  runApp(QoraScope(client: client, child: const MyApp()));\n}\n\n// Good: Await before runApp\nFuture\u003Cvoid> main() async {\n  WidgetsFlutterBinding.ensureInitialized();\n  await storage.init();\n  await client.hydrate();\n  runApp(QoraScope(client: client, child: const MyApp()));\n}\n",[357,817,818,823,834,850,884,889,893,898,922,936,954,969,998],{"__ignoreMap":372},[376,819,820],{"class":378,"line":379},[376,821,822],{"class":401},"// Bad: hydrate() fires but isn't awaited\n",[376,824,825,828,831],{"class":378,"line":405},[376,826,827],{"class":382},"void",[376,829,830],{"class":492}," main",[376,832,833],{"class":386},"() {\n",[376,835,836,839,841,843,845,847],{"class":378,"line":434},[376,837,838],{"class":386},"  client",[376,840,489],{"class":390},[376,842,653],{"class":492},[376,844,561],{"class":386},[376,846,735],{"class":390},[376,848,849],{"class":401}," // no await\n",[376,851,852,855,857,859,862,864,866,869,872,874,876,879,882],{"class":378,"line":518},[376,853,854],{"class":492},"  runApp",[376,856,594],{"class":386},[376,858,103],{"class":394},[376,860,861],{"class":386},"(client",[376,863,411],{"class":390},[376,865,648],{"class":386},[376,867,868],{"class":390},",",[376,870,871],{"class":386}," child",[376,873,411],{"class":390},[376,875,414],{"class":382},[376,877,878],{"class":394}," MyApp",[376,880,881],{"class":386},"()))",[376,883,439],{"class":390},[376,885,886],{"class":378,"line":566},[376,887,888],{"class":386},"}\n",[376,890,891],{"class":378,"line":612},[376,892,744],{"emptyLinePlaceholder":743},[376,894,895],{"class":378,"line":620},[376,896,897],{"class":401},"// Good: Await before runApp\n",[376,899,900,903,905,907,910,913,916,919],{"class":378,"line":634},[376,901,902],{"class":394},"Future",[376,904,496],{"class":386},[376,906,827],{"class":382},[376,908,909],{"class":386},"> ",[376,911,912],{"class":492},"main",[376,914,915],{"class":386},"() ",[376,917,918],{"class":644},"async",[376,920,921],{"class":386}," {\n",[376,923,924,927,929,932,934],{"class":378,"line":641},[376,925,926],{"class":394},"  WidgetsFlutterBinding",[376,928,489],{"class":390},[376,930,931],{"class":492},"ensureInitialized",[376,933,561],{"class":386},[376,935,439],{"class":390},[376,937,939,942,945,947,950,952],{"class":378,"line":938},10,[376,940,941],{"class":644},"  await",[376,943,944],{"class":386}," storage",[376,946,489],{"class":390},[376,948,949],{"class":492},"init",[376,951,561],{"class":386},[376,953,439],{"class":390},[376,955,957,959,961,963,965,967],{"class":378,"line":956},11,[376,958,941],{"class":644},[376,960,648],{"class":386},[376,962,489],{"class":390},[376,964,653],{"class":492},[376,966,561],{"class":386},[376,968,439],{"class":390},[376,970,972,974,976,978,980,982,984,986,988,990,992,994,996],{"class":378,"line":971},12,[376,973,854],{"class":492},[376,975,594],{"class":386},[376,977,103],{"class":394},[376,979,861],{"class":386},[376,981,411],{"class":390},[376,983,648],{"class":386},[376,985,868],{"class":390},[376,987,871],{"class":386},[376,989,411],{"class":390},[376,991,414],{"class":382},[376,993,878],{"class":394},[376,995,881],{"class":386},[376,997,439],{"class":390},[376,999,1001],{"class":378,"line":1000},13,[376,1002,888],{"class":386},[441,1004],{},[448,1006,1008,1009,1012],{"id":1007},"hydration-breaks-after-a-flutter-web-or-obfuscate-build","Hydration breaks after a Flutter Web or ",[357,1010,1011],{},"--obfuscate"," build",[353,1014,1015,1017,1018,1021,1022,1024,1025,1028],{},[455,1016,466],{},": Without an explicit ",[357,1019,1020],{},"name",", ",[357,1023,493],{}," uses ",[357,1026,1027],{},"T.toString()"," as the type discriminator. Obfuscation changes this value. Persisted entries from one build mode do not match discriminators in another build mode.",[366,1030,1032],{"className":368,"code":1031,"filename":370,"language":371,"meta":372,"style":372},"// Unsafe. Name becomes 'a' under obfuscation.\nclient.registerSerializer\u003CUser>(userSerializer);\n\n// Good: Stable across all build modes\nclient.registerSerializer\u003CUser>(userSerializer, name: 'User');\nclient.registerSerializer\u003CList\u003CPost>>(postListSerializer, name: 'List\u003CPost>');\n",[357,1033,1034,1039,1056,1060,1065,1094],{"__ignoreMap":372},[376,1035,1036],{"class":378,"line":379},[376,1037,1038],{"class":401},"// Unsafe. Name becomes 'a' under obfuscation.\n",[376,1040,1041,1043,1045,1047,1049,1051,1054],{"class":378,"line":405},[376,1042,486],{"class":386},[376,1044,489],{"class":390},[376,1046,493],{"class":492},[376,1048,496],{"class":386},[376,1050,724],{"class":394},[376,1052,1053],{"class":386},">(userSerializer)",[376,1055,439],{"class":390},[376,1057,1058],{"class":378,"line":434},[376,1059,744],{"emptyLinePlaceholder":743},[376,1061,1062],{"class":378,"line":518},[376,1063,1064],{"class":401},"// Good: Stable across all build modes\n",[376,1066,1067,1069,1071,1073,1075,1077,1080,1082,1085,1087,1090,1092],{"class":378,"line":566},[376,1068,486],{"class":386},[376,1070,489],{"class":390},[376,1072,493],{"class":492},[376,1074,496],{"class":386},[376,1076,724],{"class":394},[376,1078,1079],{"class":386},">(userSerializer",[376,1081,868],{"class":390},[376,1083,1084],{"class":386}," name",[376,1086,411],{"class":390},[376,1088,1089],{"class":628}," 'User'",[376,1091,428],{"class":386},[376,1093,439],{"class":390},[376,1095,1096,1098,1100,1102,1104,1106,1108,1110,1113,1115,1117,1119,1121,1123],{"class":378,"line":612},[376,1097,486],{"class":386},[376,1099,489],{"class":390},[376,1101,493],{"class":492},[376,1103,496],{"class":386},[376,1105,499],{"class":394},[376,1107,496],{"class":386},[376,1109,504],{"class":394},[376,1111,1112],{"class":386},">>(postListSerializer",[376,1114,868],{"class":390},[376,1116,1084],{"class":386},[376,1118,411],{"class":390},[376,1120,629],{"class":628},[376,1122,428],{"class":386},[376,1124,439],{"class":390},[353,1126,1127,1128,1130,1131,1133],{},"The serializer ",[357,1129,1020],{}," must remain stable across app versions. A changed ",[357,1132,1020],{}," invalidates previously persisted entries for that type.",[441,1135],{},[448,1137,1139,1142],{"id":1138},"fromjson-crashes-on-startup-after-a-model-change",[357,1140,1141],{},"fromJson"," crashes on startup after a model change",[353,1144,1145,1147,1148,1150],{},[455,1146,466],{},": A required field was introduced between app versions. Persisted JSON from older versions does not include the field, and ",[357,1149,1141],{}," throws.",[353,1152,1153,1155,1156,1158],{},[357,1154,229],{}," catches ",[357,1157,1141],{}," exceptions during hydration, removes the invalid entry, and continues execution. The entry is lost and the next read triggers a network fetch.",[353,1160,1161],{},"Implement defensive parsing to reduce data loss:",[366,1163,1166],{"className":368,"code":1164,"filename":1165,"language":371,"meta":372,"style":372},"factory User.fromJson(dynamic json) {\n  final map = json as Map\u003CString, dynamic>;\n  return User(\n    id:   map['id'] as int,\n    name: map['name'] as String,\n    // Added in v2. Default for entries persisted by v1.\n    role: map['role'] as String? ?? 'viewer',\n  );\n}\n","models/user.dart",[357,1167,1168,1188,1220,1229,1252,1274,1279,1308,1314],{"__ignoreMap":372},[376,1169,1170,1173,1176,1178,1180,1182,1185],{"class":378,"line":379},[376,1171,1172],{"class":390},"factory",[376,1174,1175],{"class":394}," User",[376,1177,489],{"class":390},[376,1179,1141],{"class":492},[376,1181,594],{"class":386},[376,1183,1184],{"class":394},"dynamic",[376,1186,1187],{"class":386}," json) {\n",[376,1189,1190,1193,1196,1198,1201,1203,1206,1208,1211,1213,1215,1218],{"class":378,"line":405},[376,1191,1192],{"class":382},"  final",[376,1194,1195],{"class":386}," map ",[376,1197,391],{"class":390},[376,1199,1200],{"class":386}," json ",[376,1202,582],{"class":390},[376,1204,1205],{"class":394}," Map",[376,1207,496],{"class":386},[376,1209,1210],{"class":394},"String",[376,1212,1021],{"class":386},[376,1214,1184],{"class":394},[376,1216,1217],{"class":386},">",[376,1219,439],{"class":390},[376,1221,1222,1225,1227],{"class":378,"line":434},[376,1223,1224],{"class":644},"  return",[376,1226,1175],{"class":394},[376,1228,515],{"class":386},[376,1230,1231,1234,1236,1239,1242,1245,1247,1250],{"class":378,"line":518},[376,1232,1233],{"class":386},"    id",[376,1235,411],{"class":390},[376,1237,1238],{"class":386},"   map[",[376,1240,1241],{"class":628},"'id'",[376,1243,1244],{"class":386},"] ",[376,1246,582],{"class":390},[376,1248,1249],{"class":394}," int",[376,1251,431],{"class":390},[376,1253,1254,1257,1259,1262,1265,1267,1269,1272],{"class":378,"line":566},[376,1255,1256],{"class":386},"    name",[376,1258,411],{"class":390},[376,1260,1261],{"class":386}," map[",[376,1263,1264],{"class":628},"'name'",[376,1266,1244],{"class":386},[376,1268,582],{"class":390},[376,1270,1271],{"class":394}," String",[376,1273,431],{"class":390},[376,1275,1276],{"class":378,"line":612},[376,1277,1278],{"class":401},"    // Added in v2. Default for entries persisted by v1.\n",[376,1280,1281,1284,1286,1288,1291,1293,1295,1297,1300,1303,1306],{"class":378,"line":620},[376,1282,1283],{"class":386},"    role",[376,1285,411],{"class":390},[376,1287,1261],{"class":386},[376,1289,1290],{"class":628},"'role'",[376,1292,1244],{"class":386},[376,1294,582],{"class":390},[376,1296,1271],{"class":394},[376,1298,1299],{"class":390},"?",[376,1301,1302],{"class":390}," ??",[376,1304,1305],{"class":628}," 'viewer'",[376,1307,431],{"class":390},[376,1309,1310,1312],{"class":378,"line":634},[376,1311,615],{"class":386},[376,1313,439],{"class":390},[376,1315,1316],{"class":378,"line":641},[376,1317,888],{"class":386},[353,1319,1320,1321,1323,1324,1327,1328,1331],{},"For breaking changes such as field type changes or field removal without a safe default, bump the serializer ",[357,1322,1020],{}," from ",[357,1325,1326],{},"'User'"," to ",[357,1329,1330],{},"'User_v2'",". Qora skips old entries and rewrites fresh data after the next successful fetch.",[441,1333],{},[348,1335,1337],{"id":1336},"query-state","Query State",[448,1339,1341,1342,1345],{"id":1340},"query-is-stuck-in-initial-and-never-fetches","Query is stuck in ",[357,1343,1344],{},"Initial"," and never fetches",[353,1347,1348,458,1351,1354,1355,1357,1358,1360],{},[455,1349,1350],{},"Cause A",[357,1352,1353],{},"enabled: false"," is configured on ",[357,1356,108],{}," or ",[357,1359,215],{},". The widget observes state but does not trigger fetching.",[366,1362,1364],{"className":368,"code":1363,"language":371,"meta":372,"style":372},"// Verify this configuration:\nQoraBuilder\u003CUser>(\n  enabled: someVariable, // false keeps state at Initial\n  ...\n)\n",[357,1365,1366,1371,1382,1397,1402],{"__ignoreMap":372},[376,1367,1368],{"class":378,"line":379},[376,1369,1370],{"class":401},"// Verify this configuration:\n",[376,1372,1373,1375,1377,1379],{"class":378,"line":405},[376,1374,108],{"class":394},[376,1376,496],{"class":386},[376,1378,724],{"class":394},[376,1380,1381],{"class":386},">(\n",[376,1383,1384,1387,1389,1392,1394],{"class":378,"line":434},[376,1385,1386],{"class":386},"  enabled",[376,1388,411],{"class":390},[376,1390,1391],{"class":386}," someVariable",[376,1393,868],{"class":390},[376,1395,1396],{"class":401}," // false keeps state at Initial\n",[376,1398,1399],{"class":378,"line":518},[376,1400,1401],{"class":390},"  ...\n",[376,1403,1404],{"class":378,"line":566},[376,1405,1406],{"class":386},")\n",[353,1408,1409,458,1412,1415,1416,1418,1419,1421,1422,489],{},[455,1410,1411],{},"Cause B",[357,1413,1414],{},"QoraStateBuilder"," is used instead of ",[357,1417,108],{},". ",[357,1420,1414],{}," is observation-only and never calls ",[357,1423,1424],{},"fetchQuery",[441,1426],{},[448,1428,1341,1430,1433],{"id":1429},"query-is-stuck-in-loading-indefinitely",[357,1431,1432],{},"Loading"," indefinitely",[353,1435,1436,458,1438,1441,1442,1418,1445,1448],{},[455,1437,1350],{},[357,1439,1440],{},"dependsOn"," is configured, and the dependency query does not reach ",[357,1443,1444],{},"Success",[357,1446,1447],{},"watchQuery"," waits until dependency resolution before executing the dependent fetch.",[366,1450,1452],{"className":368,"code":1451,"language":371,"meta":372,"style":372},"// Validate dependency and key declarations.\nclient.watchQuery\u003CProfile>(\n  key: ['profile'],\n  fetcher: () {\n    final auth = client.getQueryData\u003CAuth>(['auth'])!;\n    return api.getProfile(auth.userId);\n  },\n  options: const QoraOptions(dependsOn: ['auth']),\n);\n",[357,1453,1454,1459,1474,1492,1502,1536,1559,1566,1591],{"__ignoreMap":372},[376,1455,1456],{"class":378,"line":379},[376,1457,1458],{"class":401},"// Validate dependency and key declarations.\n",[376,1460,1461,1463,1465,1467,1469,1472],{"class":378,"line":405},[376,1462,486],{"class":386},[376,1464,489],{"class":390},[376,1466,1447],{"class":492},[376,1468,496],{"class":386},[376,1470,1471],{"class":394},"Profile",[376,1473,1381],{"class":386},[376,1475,1476,1479,1481,1484,1487,1490],{"class":378,"line":434},[376,1477,1478],{"class":386},"  key",[376,1480,411],{"class":390},[376,1482,1483],{"class":386}," [",[376,1485,1486],{"class":628},"'profile'",[376,1488,1489],{"class":386},"]",[376,1491,431],{"class":390},[376,1493,1494,1497,1499],{"class":378,"line":518},[376,1495,1496],{"class":386},"  fetcher",[376,1498,411],{"class":390},[376,1500,1501],{"class":386}," () {\n",[376,1503,1504,1507,1510,1512,1514,1516,1519,1521,1524,1527,1530,1533],{"class":378,"line":566},[376,1505,1506],{"class":382},"    final",[376,1508,1509],{"class":386}," auth ",[376,1511,391],{"class":390},[376,1513,648],{"class":386},[376,1515,489],{"class":390},[376,1517,1518],{"class":492},"getQueryData",[376,1520,496],{"class":386},[376,1522,1523],{"class":394},"Auth",[376,1525,1526],{"class":386},">([",[376,1528,1529],{"class":628},"'auth'",[376,1531,1532],{"class":386},"])",[376,1534,1535],{"class":390},"!;\n",[376,1537,1538,1541,1544,1546,1549,1552,1554,1557],{"class":378,"line":612},[376,1539,1540],{"class":644},"    return",[376,1542,1543],{"class":386}," api",[376,1545,489],{"class":390},[376,1547,1548],{"class":492},"getProfile",[376,1550,1551],{"class":386},"(auth",[376,1553,489],{"class":390},[376,1555,1556],{"class":386},"userId)",[376,1558,439],{"class":390},[376,1560,1561,1564],{"class":378,"line":620},[376,1562,1563],{"class":386},"  }",[376,1565,431],{"class":390},[376,1567,1568,1571,1573,1575,1578,1581,1583,1585,1587,1589],{"class":378,"line":634},[376,1569,1570],{"class":386},"  options",[376,1572,411],{"class":390},[376,1574,414],{"class":382},[376,1576,1577],{"class":394}," QoraOptions",[376,1579,1580],{"class":386},"(dependsOn",[376,1582,411],{"class":390},[376,1584,1483],{"class":386},[376,1586,1529],{"class":628},[376,1588,1532],{"class":386},[376,1590,431],{"class":390},[376,1592,1593,1595],{"class":378,"line":641},[376,1594,428],{"class":386},[376,1596,439],{"class":390},[353,1598,1599,458,1601,1603,1604,1418,1606,1608,1609,1612,1613,1615],{},[455,1600,1411],{},[357,1602,1424],{}," is used with ",[357,1605,1440],{},[357,1607,1424],{}," throws ",[357,1610,1611],{},"StateError"," when dependencies are unresolved. Use ",[357,1614,1447],{}," for reactive dependency handling.",[353,1617,1618,458,1621,1624,1625,1628,1629,1632,1633,1636,1637,1640],{},[455,1619,1620],{},"Cause C",[357,1622,1623],{},"NetworkMode.online"," is active without a ",[357,1626,1627],{},"ConnectivityManager",". In this configuration, fetches always run. With ",[357,1630,1631],{},"FlutterConnectivityManager"," and no connectivity, queries transition to ",[357,1634,1635],{},"Loading(previousData: null)"," with ",[357,1638,1639],{},"FetchStatus.paused"," and resume automatically after reconnection.",[441,1642],{},[448,1644,1646],{"id":1645},"query-does-not-refetch-when-the-app-comes-back-to-foreground","Query does not refetch when the app comes back to foreground",[353,1648,1649,458,1651,1654,1655,489],{},[455,1650,466],{},[357,1652,1653],{},"FlutterLifecycleManager"," is not provided to ",[357,1656,103],{},[366,1658,1660],{"className":368,"code":1659,"filename":370,"language":371,"meta":372,"style":372},"// Bad: Missing lifecycleManager\nQoraScope(client: client, child: const MyApp())\n\n// Good\nQoraScope(\n  client: client,\n  lifecycleManager: FlutterLifecycleManager(qoraClient: client),\n  child: const MyApp(),\n)\n",[357,1661,1662,1667,1690,1694,1699,1705,1715,1735,1750],{"__ignoreMap":372},[376,1663,1664],{"class":378,"line":379},[376,1665,1666],{"class":401},"// Bad: Missing lifecycleManager\n",[376,1668,1669,1671,1673,1675,1677,1679,1681,1683,1685,1687],{"class":378,"line":405},[376,1670,103],{"class":394},[376,1672,861],{"class":386},[376,1674,411],{"class":390},[376,1676,648],{"class":386},[376,1678,868],{"class":390},[376,1680,871],{"class":386},[376,1682,411],{"class":390},[376,1684,414],{"class":382},[376,1686,878],{"class":394},[376,1688,1689],{"class":386},"())\n",[376,1691,1692],{"class":378,"line":434},[376,1693,744],{"emptyLinePlaceholder":743},[376,1695,1696],{"class":378,"line":518},[376,1697,1698],{"class":401},"// Good\n",[376,1700,1701,1703],{"class":378,"line":566},[376,1702,103],{"class":394},[376,1704,515],{"class":386},[376,1706,1707,1709,1711,1713],{"class":378,"line":612},[376,1708,838],{"class":386},[376,1710,411],{"class":390},[376,1712,648],{"class":386},[376,1714,431],{"class":390},[376,1716,1717,1720,1722,1725,1728,1730,1733],{"class":378,"line":620},[376,1718,1719],{"class":386},"  lifecycleManager",[376,1721,411],{"class":390},[376,1723,1724],{"class":394}," FlutterLifecycleManager",[376,1726,1727],{"class":386},"(qoraClient",[376,1729,411],{"class":390},[376,1731,1732],{"class":386}," client)",[376,1734,431],{"class":390},[376,1736,1737,1740,1742,1744,1746,1748],{"class":378,"line":634},[376,1738,1739],{"class":386},"  child",[376,1741,411],{"class":390},[376,1743,414],{"class":382},[376,1745,878],{"class":394},[376,1747,561],{"class":386},[376,1749,431],{"class":390},[376,1751,1752],{"class":378,"line":641},[376,1753,1406],{"class":386},[353,1755,1756,1757,1760,1761,489],{},"Also verify that ",[357,1758,1759],{},"refetchOnWindowFocus: true"," remains enabled in ",[357,1762,1763],{},"QoraClientConfig.defaultOptions",[441,1765],{},[448,1767,1769],{"id":1768},"query-does-not-refetch-when-connectivity-is-restored","Query does not refetch when connectivity is restored",[353,1771,1772,458,1774,1654,1776,489],{},[455,1773,466],{},[357,1775,1631],{},[357,1777,103],{},[366,1779,1781],{"className":368,"code":1780,"filename":370,"language":371,"meta":372,"style":372},"// Good\nQoraScope(\n  client: client,\n  connectivityManager: FlutterConnectivityManager(),\n  child: const MyApp(),\n)\n",[357,1782,1783,1787,1793,1803,1817,1831],{"__ignoreMap":372},[376,1784,1785],{"class":378,"line":379},[376,1786,1698],{"class":401},[376,1788,1789,1791],{"class":378,"line":405},[376,1790,103],{"class":394},[376,1792,515],{"class":386},[376,1794,1795,1797,1799,1801],{"class":378,"line":434},[376,1796,838],{"class":386},[376,1798,411],{"class":390},[376,1800,648],{"class":386},[376,1802,431],{"class":390},[376,1804,1805,1808,1810,1813,1815],{"class":378,"line":518},[376,1806,1807],{"class":386},"  connectivityManager",[376,1809,411],{"class":390},[376,1811,1812],{"class":394}," FlutterConnectivityManager",[376,1814,561],{"class":386},[376,1816,431],{"class":390},[376,1818,1819,1821,1823,1825,1827,1829],{"class":378,"line":566},[376,1820,1739],{"class":386},[376,1822,411],{"class":390},[376,1824,414],{"class":382},[376,1826,878],{"class":394},[376,1828,561],{"class":386},[376,1830,431],{"class":390},[376,1832,1833],{"class":378,"line":612},[376,1834,1406],{"class":386},[353,1836,1837,1839,1840,1843,1844,1847],{},[357,1838,1631],{}," requires ",[357,1841,1842],{},"connectivity_plus"," in ",[357,1845,1846],{},"pubspec.yaml",". Missing the dependency causes a compile-time import error.",[441,1849],{},[348,1851,1853],{"id":1852},"cache-keys","Cache & Keys",[448,1855,1857],{"id":1856},"different-widgets-see-different-data-for-the-same-query","Different widgets see different data for the \"same\" query",[353,1859,1860,1862,1863,1866],{},[455,1861,466],{},": Query keys are not structurally equivalent across call sites. Qora uses deep structural equality (",[357,1864,1865],{},"KeyEquality","). Different runtime types inside key segments produce distinct cache entries.",[366,1868,1870],{"className":368,"code":1869,"language":371,"meta":372,"style":372},"// Bad: Inconsistent key types\nfetchQuery(key: ['users', 42], ...);    // int\nwatchQuery(key: ['users', '42'], ...);  // String. Different key.\n\n// Good: Consistent\nfetchQuery(key: ['users', 42], ...);\nwatchQuery(key: ['users', 42], ...);\n",[357,1871,1872,1877,1911,1941,1945,1950,1976],{"__ignoreMap":372},[376,1873,1874],{"class":378,"line":379},[376,1875,1876],{"class":401},"// Bad: Inconsistent key types\n",[376,1878,1879,1881,1884,1886,1888,1891,1893,1897,1899,1901,1904,1906,1908],{"class":378,"line":405},[376,1880,1424],{"class":492},[376,1882,1883],{"class":386},"(key",[376,1885,411],{"class":390},[376,1887,1483],{"class":386},[376,1889,1890],{"class":628},"'users'",[376,1892,868],{"class":390},[376,1894,1896],{"class":1895},"sbssI"," 42",[376,1898,1489],{"class":386},[376,1900,868],{"class":390},[376,1902,1903],{"class":390}," ...",[376,1905,428],{"class":386},[376,1907,735],{"class":390},[376,1909,1910],{"class":401},"    // int\n",[376,1912,1913,1915,1917,1919,1921,1923,1925,1928,1930,1932,1934,1936,1938],{"class":378,"line":434},[376,1914,1447],{"class":492},[376,1916,1883],{"class":386},[376,1918,411],{"class":390},[376,1920,1483],{"class":386},[376,1922,1890],{"class":628},[376,1924,868],{"class":390},[376,1926,1927],{"class":628}," '42'",[376,1929,1489],{"class":386},[376,1931,868],{"class":390},[376,1933,1903],{"class":390},[376,1935,428],{"class":386},[376,1937,735],{"class":390},[376,1939,1940],{"class":401},"  // String. Different key.\n",[376,1942,1943],{"class":378,"line":518},[376,1944,744],{"emptyLinePlaceholder":743},[376,1946,1947],{"class":378,"line":566},[376,1948,1949],{"class":401},"// Good: Consistent\n",[376,1951,1952,1954,1956,1958,1960,1962,1964,1966,1968,1970,1972,1974],{"class":378,"line":612},[376,1953,1424],{"class":492},[376,1955,1883],{"class":386},[376,1957,411],{"class":390},[376,1959,1483],{"class":386},[376,1961,1890],{"class":628},[376,1963,868],{"class":390},[376,1965,1896],{"class":1895},[376,1967,1489],{"class":386},[376,1969,868],{"class":390},[376,1971,1903],{"class":390},[376,1973,428],{"class":386},[376,1975,439],{"class":390},[376,1977,1978,1980,1982,1984,1986,1988,1990,1992,1994,1996,1998,2000],{"class":378,"line":620},[376,1979,1447],{"class":492},[376,1981,1883],{"class":386},[376,1983,411],{"class":390},[376,1985,1483],{"class":386},[376,1987,1890],{"class":628},[376,1989,868],{"class":390},[376,1991,1896],{"class":1895},[376,1993,1489],{"class":386},[376,1995,868],{"class":390},[376,1997,1903],{"class":390},[376,1999,428],{"class":386},[376,2001,439],{"class":390},[441,2003],{},[448,2005,2007,2009],{"id":2006},"qorabuilder-re-subscribes-on-every-rebuild-performance-issue",[357,2008,108],{}," re-subscribes on every rebuild (performance issue)",[353,2011,2012,458,2014,2017,2018,2021,2022,2025],{},[455,2013,466],{},[357,2015,2016],{},"queryKey"," is created inline as a new non-",[357,2019,2020],{},"const"," list instance. ",[357,2023,2024],{},"QoraBuilder.didUpdateWidget"," compares references, so each rebuild appears as a new key and triggers re-subscription.",[366,2027,2029],{"className":368,"code":2028,"language":371,"meta":372,"style":372},"// Bad: New List instance on every build\nQoraBuilder\u003CList\u003CPost>>(\n  queryKey: ['posts', page], // new list instance each build\n  ...\n)\n\n// Good: Stable reference. Changes only when page changes.\nQoraBuilder\u003CList\u003CPost>>(\n  queryKey: const ['posts'],         // for static keys\n  // or\n  queryKey: ['posts', page],         // fine IF page is stable (not rebuilt every frame)\n  ...\n)\n",[357,2030,2031,2036,2050,2072,2076,2080,2084,2089,2103,2122,2127,2146,2150],{"__ignoreMap":372},[376,2032,2033],{"class":378,"line":379},[376,2034,2035],{"class":401},"// Bad: New List instance on every build\n",[376,2037,2038,2040,2042,2044,2046,2048],{"class":378,"line":405},[376,2039,108],{"class":394},[376,2041,496],{"class":386},[376,2043,499],{"class":394},[376,2045,496],{"class":386},[376,2047,504],{"class":394},[376,2049,507],{"class":386},[376,2051,2052,2055,2057,2059,2062,2064,2067,2069],{"class":378,"line":434},[376,2053,2054],{"class":386},"  queryKey",[376,2056,411],{"class":390},[376,2058,1483],{"class":386},[376,2060,2061],{"class":628},"'posts'",[376,2063,868],{"class":390},[376,2065,2066],{"class":386}," page]",[376,2068,868],{"class":390},[376,2070,2071],{"class":401}," // new list instance each build\n",[376,2073,2074],{"class":378,"line":518},[376,2075,1401],{"class":390},[376,2077,2078],{"class":378,"line":566},[376,2079,1406],{"class":386},[376,2081,2082],{"class":378,"line":612},[376,2083,744],{"emptyLinePlaceholder":743},[376,2085,2086],{"class":378,"line":620},[376,2087,2088],{"class":401},"// Good: Stable reference. Changes only when page changes.\n",[376,2090,2091,2093,2095,2097,2099,2101],{"class":378,"line":634},[376,2092,108],{"class":394},[376,2094,496],{"class":386},[376,2096,499],{"class":394},[376,2098,496],{"class":386},[376,2100,504],{"class":394},[376,2102,507],{"class":386},[376,2104,2105,2107,2109,2111,2113,2115,2117,2119],{"class":378,"line":641},[376,2106,2054],{"class":386},[376,2108,411],{"class":390},[376,2110,414],{"class":382},[376,2112,1483],{"class":386},[376,2114,2061],{"class":628},[376,2116,1489],{"class":386},[376,2118,868],{"class":390},[376,2120,2121],{"class":401},"         // for static keys\n",[376,2123,2124],{"class":378,"line":938},[376,2125,2126],{"class":401},"  // or\n",[376,2128,2129,2131,2133,2135,2137,2139,2141,2143],{"class":378,"line":956},[376,2130,2054],{"class":386},[376,2132,411],{"class":390},[376,2134,1483],{"class":386},[376,2136,2061],{"class":628},[376,2138,868],{"class":390},[376,2140,2066],{"class":386},[376,2142,868],{"class":390},[376,2144,2145],{"class":401},"         // fine IF page is stable (not rebuilt every frame)\n",[376,2147,2148],{"class":378,"line":971},[376,2149,1401],{"class":390},[376,2151,2152],{"class":378,"line":1000},[376,2153,1406],{"class":386},[353,2155,2156],{},"If the key includes variables, update those variables only when the requested dataset changes.",[441,2158],{},[448,2160,2162,2165,2166,2169],{"id":2161},"dataornull-returns-null-even-after-a-successful-fetch",[357,2163,2164],{},"dataOrNull"," returns ",[357,2167,2168],{},"null"," even after a successful fetch",[353,2171,2172,2174,2175,2178,2179,2182,2183,2186,2187,2190],{},[455,2173,466],{},": The type parameter on ",[357,2176,2177],{},"QoraBuilder\u003CT>"," does not match the fetched data type. The state stream is strongly typed. A ",[357,2180,2181],{},"Success\u003CUser>"," for key ",[357,2184,2185],{},"['users', 1]"," is not delivered to ",[357,2188,2189],{},"QoraBuilder\u003CProfile>"," on the same key.",[366,2192,2194],{"className":368,"code":2193,"language":371,"meta":372,"style":372},"// Bad: Type mismatch. State is Success\u003CUser> but builder expects Profile.\nQoraBuilder\u003CProfile>(queryKey: ['users', userId], ...)\n\n// Good\nQoraBuilder\u003CUser>(queryKey: ['users', userId], ...)\n",[357,2195,2196,2201,2229,2233,2237],{"__ignoreMap":372},[376,2197,2198],{"class":378,"line":379},[376,2199,2200],{"class":401},"// Bad: Type mismatch. State is Success\u003CUser> but builder expects Profile.\n",[376,2202,2203,2205,2207,2209,2212,2214,2216,2218,2220,2223,2225,2227],{"class":378,"line":405},[376,2204,108],{"class":394},[376,2206,496],{"class":386},[376,2208,1471],{"class":394},[376,2210,2211],{"class":386},">(queryKey",[376,2213,411],{"class":390},[376,2215,1483],{"class":386},[376,2217,1890],{"class":628},[376,2219,868],{"class":390},[376,2221,2222],{"class":386}," userId]",[376,2224,868],{"class":390},[376,2226,1903],{"class":390},[376,2228,1406],{"class":386},[376,2230,2231],{"class":378,"line":434},[376,2232,744],{"emptyLinePlaceholder":743},[376,2234,2235],{"class":378,"line":518},[376,2236,1698],{"class":401},[376,2238,2239,2241,2243,2245,2247,2249,2251,2253,2255,2257,2259,2261],{"class":378,"line":566},[376,2240,108],{"class":394},[376,2242,496],{"class":386},[376,2244,724],{"class":394},[376,2246,2211],{"class":386},[376,2248,411],{"class":390},[376,2250,1483],{"class":386},[376,2252,1890],{"class":628},[376,2254,868],{"class":390},[376,2256,2222],{"class":386},[376,2258,868],{"class":390},[376,2260,1903],{"class":390},[376,2262,1406],{"class":386},[441,2264],{},[348,2266,148],{"id":2267},"optimistic-updates",[448,2269,2271],{"id":2270},"rollback-does-not-work-and-ui-stays-in-optimistic-state-after-failure","Rollback does not work and UI stays in optimistic state after failure",[353,2273,2274,2276,2277,2280],{},[455,2275,466],{},": The snapshot was taken after ",[357,2278,2279],{},"setQueryData"," instead of before.",[366,2282,2284],{"className":368,"code":2283,"language":371,"meta":372,"style":372},"// Bad: Snapshot is taken after the optimistic write. It captures the wrong state.\nclient.setQueryData\u003CUser>(key, optimisticUser);\nfinal snapshot = client.getQueryData\u003CUser>(key); // already optimistic: wrong!\n\n// Good: Always snapshot first\nfinal snapshot = client.getQueryData\u003CUser>(key); // T?, null if no prior data\nclient.setQueryData\u003CUser>(key, optimisticUser);\ntry {\n  await api.updateUser(...);\n} catch (_) {\n  client.restoreQueryData\u003CUser>(key, snapshot); // null → removeQuery; else setQueryData\n}\n",[357,2285,2286,2291,2313,2340,2344,2349,2374,2394,2401,2420,2431,2456],{"__ignoreMap":372},[376,2287,2288],{"class":378,"line":379},[376,2289,2290],{"class":401},"// Bad: Snapshot is taken after the optimistic write. It captures the wrong state.\n",[376,2292,2293,2295,2297,2299,2301,2303,2306,2308,2311],{"class":378,"line":405},[376,2294,486],{"class":386},[376,2296,489],{"class":390},[376,2298,2279],{"class":492},[376,2300,496],{"class":386},[376,2302,724],{"class":394},[376,2304,2305],{"class":386},">(key",[376,2307,868],{"class":390},[376,2309,2310],{"class":386}," optimisticUser)",[376,2312,439],{"class":390},[376,2314,2315,2317,2320,2322,2324,2326,2328,2330,2332,2335,2337],{"class":378,"line":434},[376,2316,383],{"class":382},[376,2318,2319],{"class":386}," snapshot ",[376,2321,391],{"class":390},[376,2323,648],{"class":386},[376,2325,489],{"class":390},[376,2327,1518],{"class":492},[376,2329,496],{"class":386},[376,2331,724],{"class":394},[376,2333,2334],{"class":386},">(key)",[376,2336,735],{"class":390},[376,2338,2339],{"class":401}," // already optimistic: wrong!\n",[376,2341,2342],{"class":378,"line":518},[376,2343,744],{"emptyLinePlaceholder":743},[376,2345,2346],{"class":378,"line":566},[376,2347,2348],{"class":401},"// Good: Always snapshot first\n",[376,2350,2351,2353,2355,2357,2359,2361,2363,2365,2367,2369,2371],{"class":378,"line":612},[376,2352,383],{"class":382},[376,2354,2319],{"class":386},[376,2356,391],{"class":390},[376,2358,648],{"class":386},[376,2360,489],{"class":390},[376,2362,1518],{"class":492},[376,2364,496],{"class":386},[376,2366,724],{"class":394},[376,2368,2334],{"class":386},[376,2370,735],{"class":390},[376,2372,2373],{"class":401}," // T?, null if no prior data\n",[376,2375,2376,2378,2380,2382,2384,2386,2388,2390,2392],{"class":378,"line":620},[376,2377,486],{"class":386},[376,2379,489],{"class":390},[376,2381,2279],{"class":492},[376,2383,496],{"class":386},[376,2385,724],{"class":394},[376,2387,2305],{"class":386},[376,2389,868],{"class":390},[376,2391,2310],{"class":386},[376,2393,439],{"class":390},[376,2395,2396,2399],{"class":378,"line":634},[376,2397,2398],{"class":644},"try",[376,2400,921],{"class":386},[376,2402,2403,2405,2407,2409,2412,2414,2416,2418],{"class":378,"line":641},[376,2404,941],{"class":644},[376,2406,1543],{"class":386},[376,2408,489],{"class":390},[376,2410,2411],{"class":492},"updateUser",[376,2413,594],{"class":386},[376,2415,730],{"class":390},[376,2417,428],{"class":386},[376,2419,439],{"class":390},[376,2421,2422,2425,2428],{"class":378,"line":938},[376,2423,2424],{"class":386},"} ",[376,2426,2427],{"class":644},"catch",[376,2429,2430],{"class":386}," (_) {\n",[376,2432,2433,2435,2437,2440,2442,2444,2446,2448,2451,2453],{"class":378,"line":956},[376,2434,838],{"class":386},[376,2436,489],{"class":390},[376,2438,2439],{"class":492},"restoreQueryData",[376,2441,496],{"class":386},[376,2443,724],{"class":394},[376,2445,2305],{"class":386},[376,2447,868],{"class":390},[376,2449,2450],{"class":386}," snapshot)",[376,2452,735],{"class":390},[376,2454,2455],{"class":401}," // null → removeQuery; else setQueryData\n",[376,2457,2458],{"class":378,"line":971},[376,2459,888],{"class":386},[441,2461],{},[448,2463,2465,2466,2468,2469],{"id":2464},"using-setquerydata-for-rollback-instead-of-restorequerydata","Using ",[357,2467,2279],{}," for rollback instead of ",[357,2470,2439],{},[353,2472,2473,458,2475,2478,2479,2482,2483,2485,2486,2488,2489,2491,2492,2494,2495,2497],{},[455,2474,466],{},[357,2476,2477],{},"setQueryData\u003CT>(key, data)"," requires a non-null ",[357,2480,2481],{},"T",". It always produces a ",[357,2484,1444],{}," state. When the pre-mutation state held no data (",[357,2487,1344],{},"), there is no ",[357,2490,2481],{}," to pass, and calling ",[357,2493,2279],{}," leaves an incorrect ",[357,2496,1444],{}," state in cache.",[353,2499,2500,2503,2504,2507,2508,2511,2512,2515,2516,2518,2519,2522,2523,2511,2525,2527,2528,2530],{},[357,2501,2502],{},"restoreQueryData\u003CT>(key, T? data)"," accepts the ",[357,2505,2506],{},"T?"," value returned by ",[357,2509,2510],{},"getQueryData\u003CT>",". When ",[357,2513,2514],{},"data"," is ",[357,2517,2168],{},", it calls ",[357,2520,2521],{},"removeQuery(key)",", restoring ",[357,2524,1344],{},[357,2526,2514],{}," is non-null, it calls ",[357,2529,2477],{},". This handles both the \"had data\" and \"had no data\" cases with one call.",[366,2532,2534],{"className":368,"code":2533,"language":371,"meta":372,"style":372},"final snapshot = client.getQueryData\u003CUser>(key); // T?, null if entry was empty\n\nclient.setQueryData\u003CUser>(key, optimisticUser);\ntry {\n  await api.updateUser(...);\n} catch (_) {\n  // Bad: Compile error when snapshot is null; wrong when prior state was Initial.\n  // client.setQueryData\u003CUser>(key, snapshot!);\n\n  // Good: Handles null correctly: removes entry when there was no prior data.\n  client.restoreQueryData\u003CUser>(key, snapshot);\n}\n",[357,2535,2536,2561,2565,2585,2591,2609,2617,2622,2627,2631,2636,2656],{"__ignoreMap":372},[376,2537,2538,2540,2542,2544,2546,2548,2550,2552,2554,2556,2558],{"class":378,"line":379},[376,2539,383],{"class":382},[376,2541,2319],{"class":386},[376,2543,391],{"class":390},[376,2545,648],{"class":386},[376,2547,489],{"class":390},[376,2549,1518],{"class":492},[376,2551,496],{"class":386},[376,2553,724],{"class":394},[376,2555,2334],{"class":386},[376,2557,735],{"class":390},[376,2559,2560],{"class":401}," // T?, null if entry was empty\n",[376,2562,2563],{"class":378,"line":405},[376,2564,744],{"emptyLinePlaceholder":743},[376,2566,2567,2569,2571,2573,2575,2577,2579,2581,2583],{"class":378,"line":434},[376,2568,486],{"class":386},[376,2570,489],{"class":390},[376,2572,2279],{"class":492},[376,2574,496],{"class":386},[376,2576,724],{"class":394},[376,2578,2305],{"class":386},[376,2580,868],{"class":390},[376,2582,2310],{"class":386},[376,2584,439],{"class":390},[376,2586,2587,2589],{"class":378,"line":518},[376,2588,2398],{"class":644},[376,2590,921],{"class":386},[376,2592,2593,2595,2597,2599,2601,2603,2605,2607],{"class":378,"line":566},[376,2594,941],{"class":644},[376,2596,1543],{"class":386},[376,2598,489],{"class":390},[376,2600,2411],{"class":492},[376,2602,594],{"class":386},[376,2604,730],{"class":390},[376,2606,428],{"class":386},[376,2608,439],{"class":390},[376,2610,2611,2613,2615],{"class":378,"line":612},[376,2612,2424],{"class":386},[376,2614,2427],{"class":644},[376,2616,2430],{"class":386},[376,2618,2619],{"class":378,"line":620},[376,2620,2621],{"class":401},"  // Bad: Compile error when snapshot is null; wrong when prior state was Initial.\n",[376,2623,2624],{"class":378,"line":634},[376,2625,2626],{"class":401},"  // client.setQueryData\u003CUser>(key, snapshot!);\n",[376,2628,2629],{"class":378,"line":641},[376,2630,744],{"emptyLinePlaceholder":743},[376,2632,2633],{"class":378,"line":938},[376,2634,2635],{"class":401},"  // Good: Handles null correctly: removes entry when there was no prior data.\n",[376,2637,2638,2640,2642,2644,2646,2648,2650,2652,2654],{"class":378,"line":956},[376,2639,838],{"class":386},[376,2641,489],{"class":390},[376,2643,2439],{"class":492},[376,2645,496],{"class":386},[376,2647,724],{"class":394},[376,2649,2305],{"class":386},[376,2651,868],{"class":390},[376,2653,2450],{"class":386},[376,2655,439],{"class":390},[376,2657,2658],{"class":378,"line":971},[376,2659,888],{"class":386},[441,2661],{},[348,2663,92],{"id":2664},"flutter-integration",[448,2666,2668,1608,2671],{"id":2667},"contextqora-throws-fluttererror-qorascope-not-found",[357,2669,2670],{},"context.qora",[357,2672,2673],{},"FlutterError: QoraScope not found",[353,2675,2676,467,2678,2680,2681,2683,2684,2687],{},[455,2677,466],{},[357,2679,103],{}," ancestor exists above the widget that calls ",[357,2682,2670],{}," (or ",[357,2685,2686],{},"QoraScope.of(context)",").",[366,2689,2691],{"className":368,"code":2690,"filename":370,"language":371,"meta":372,"style":372},"// Good: QoraScope must be above the widget tree\nrunApp(\n  QoraScope(\n    client: client,\n    child: const MyApp(), // context.qora works anywhere inside MyApp\n  ),\n);\n",[357,2692,2693,2698,2704,2711,2722,2740,2746],{"__ignoreMap":372},[376,2694,2695],{"class":378,"line":379},[376,2696,2697],{"class":401},"// Good: QoraScope must be above the widget tree\n",[376,2699,2700,2702],{"class":378,"line":405},[376,2701,788],{"class":492},[376,2703,515],{"class":386},[376,2705,2706,2709],{"class":378,"line":434},[376,2707,2708],{"class":394},"  QoraScope",[376,2710,515],{"class":386},[376,2712,2713,2716,2718,2720],{"class":378,"line":518},[376,2714,2715],{"class":386},"    client",[376,2717,411],{"class":390},[376,2719,648],{"class":386},[376,2721,431],{"class":390},[376,2723,2724,2727,2729,2731,2733,2735,2737],{"class":378,"line":566},[376,2725,2726],{"class":386},"    child",[376,2728,411],{"class":390},[376,2730,414],{"class":382},[376,2732,878],{"class":394},[376,2734,561],{"class":386},[376,2736,868],{"class":390},[376,2738,2739],{"class":401}," // context.qora works anywhere inside MyApp\n",[376,2741,2742,2744],{"class":378,"line":612},[376,2743,615],{"class":386},[376,2745,431],{"class":390},[376,2747,2748,2750],{"class":378,"line":620},[376,2749,428],{"class":386},[376,2751,439],{"class":390},[353,2753,1756,2754,2756,2757,2759,2760,489],{},[357,2755,2670],{}," is not called from callbacks executed after widget disposal. ",[357,2758,2670],{}," must be resolved inside the subtree owned by ",[357,2761,103],{},[441,2763],{},[348,2765,2767],{"id":2766},"offline-mutation-queue","Offline Mutation Queue",[448,2769,2771],{"id":2770},"mutations-are-not-replayed-after-reconnect","Mutations are not replayed after reconnect",[353,2773,2774,458,2776,2778,2779,2781],{},[455,2775,1350],{},[357,2777,1631],{}," is not passed to ",[357,2780,103],{},". Qora does not receive reconnect events.",[353,2783,2784,458,2786,2789,2790,2793],{},[455,2785,1411],{},[357,2787,2788],{},"offlineQueue: true"," is not set in ",[357,2791,2792],{},"MutationOptions",". Offline queueing is opt-in per mutation.",[366,2795,2797],{"className":368,"code":2796,"language":371,"meta":372,"style":372},"QoraMutationBuilder\u003Cvoid, Todo, void>(\n  mutator: api.createTodo,\n  options: MutationOptions(\n    offlineQueue: true, // required to enqueue when offline\n  ),\n  ...\n)\n",[357,2798,2799,2818,2834,2845,2858,2864,2868],{"__ignoreMap":372},[376,2800,2801,2803,2805,2807,2809,2812,2814,2816],{"class":378,"line":379},[376,2802,113],{"class":394},[376,2804,496],{"class":386},[376,2806,827],{"class":382},[376,2808,1021],{"class":386},[376,2810,2811],{"class":394},"Todo",[376,2813,1021],{"class":386},[376,2815,827],{"class":382},[376,2817,1381],{"class":386},[376,2819,2820,2823,2825,2827,2829,2832],{"class":378,"line":405},[376,2821,2822],{"class":386},"  mutator",[376,2824,411],{"class":390},[376,2826,1543],{"class":386},[376,2828,489],{"class":390},[376,2830,2831],{"class":386},"createTodo",[376,2833,431],{"class":390},[376,2835,2836,2838,2840,2843],{"class":378,"line":434},[376,2837,1570],{"class":386},[376,2839,411],{"class":390},[376,2841,2842],{"class":394}," MutationOptions",[376,2844,515],{"class":386},[376,2846,2847,2850,2852,2855],{"class":378,"line":518},[376,2848,2849],{"class":386},"    offlineQueue",[376,2851,411],{"class":390},[376,2853,2854],{"class":390}," true,",[376,2856,2857],{"class":401}," // required to enqueue when offline\n",[376,2859,2860,2862],{"class":378,"line":566},[376,2861,615],{"class":386},[376,2863,431],{"class":390},[376,2865,2866],{"class":378,"line":612},[376,2867,1401],{"class":390},[376,2869,2870],{"class":378,"line":620},[376,2871,1406],{"class":386},[353,2873,2874,2876,2877,1636,2880,2883],{},[455,2875,1620],{},": the mutation comes from ",[357,2878,2879],{},"useMutation",[357,2881,2882],{},"qora_hooks","  1.3.1, which does not wire the offline queue. Upgrade to 1.3.1 or later.",[441,2885],{},[448,2887,2889],{"id":2888},"a-queued-mutation-disappeared-after-reconnect","A queued mutation disappeared after reconnect",[353,2891,2892,2894],{},[455,2893,466],{},": the server rejected it during replay. A queued mutation is sent once; a failed replay is not re-enqueued, and replay continues with the next one.",[353,2896,2897,2898,2901,2902,2905],{},"Resolution: roll back in ",[357,2899,2900],{},"onError"," (it receives the ",[357,2903,2904],{},"onMutate"," context, even for queued mutations) and tell the user there, for example with a snackbar and a retry action.",[441,2907],{},[348,2909,163],{"id":2910},"infinite-queries",[448,2912,2914,2917],{"id":2913},"fetchnextpage-is-called-but-no-new-data-loads",[357,2915,2916],{},"fetchNextPage()"," is called but no new data loads",[353,2919,2920,458,2922,2165,2925,2927,2928,2931,2932,2935],{},[455,2921,466],{},[357,2923,2924],{},"getNextPageParam",[357,2926,2168],{}," on the last page, so ",[357,2929,2930],{},"hasNextPage"," becomes ",[357,2933,2934],{},"false",". Qora does not fetch additional pages when pagination is complete.",[366,2937,2939],{"className":368,"code":2938,"language":371,"meta":372,"style":372},"// Integer pages. Common issue: returns null too early.\ngetNextPageParam: (lastPage, allPages) =>\n    lastPage.items.isEmpty ? null : allPages.length + 1,\n// Correct behavior: return null only when the dataset is complete.\n\n// Cursor-based pagination. Common issue: wrong cursor field.\ngetNextPageParam: (lastPage, _) => lastPage.nextCursor,\n// If nextCursor is \"\" instead of null, hasNextPage remains true.\n// Fix: lastPage.nextCursor?.isNotEmpty == true ? lastPage.nextCursor : null\n",[357,2940,2941,2946,2963,3002,3007,3011,3016,3041,3046],{"__ignoreMap":372},[376,2942,2943],{"class":378,"line":379},[376,2944,2945],{"class":401},"// Integer pages. Common issue: returns null too early.\n",[376,2947,2948,2950,2952,2955,2957,2960],{"class":378,"line":405},[376,2949,2924],{"class":386},[376,2951,411],{"class":390},[376,2953,2954],{"class":386}," (lastPage",[376,2956,868],{"class":390},[376,2958,2959],{"class":386}," allPages) ",[376,2961,2962],{"class":390},"=>\n",[376,2964,2965,2968,2970,2973,2975,2978,2980,2983,2986,2989,2991,2994,2997,3000],{"class":378,"line":434},[376,2966,2967],{"class":386},"    lastPage",[376,2969,489],{"class":390},[376,2971,2972],{"class":386},"items",[376,2974,489],{"class":390},[376,2976,2977],{"class":386},"isEmpty ",[376,2979,1299],{"class":390},[376,2981,2982],{"class":390}," null",[376,2984,2985],{"class":390}," :",[376,2987,2988],{"class":386}," allPages",[376,2990,489],{"class":390},[376,2992,2993],{"class":386},"length ",[376,2995,2996],{"class":390},"+",[376,2998,2999],{"class":1895}," 1",[376,3001,431],{"class":390},[376,3003,3004],{"class":378,"line":518},[376,3005,3006],{"class":401},"// Correct behavior: return null only when the dataset is complete.\n",[376,3008,3009],{"class":378,"line":566},[376,3010,744],{"emptyLinePlaceholder":743},[376,3012,3013],{"class":378,"line":612},[376,3014,3015],{"class":401},"// Cursor-based pagination. Common issue: wrong cursor field.\n",[376,3017,3018,3020,3022,3024,3026,3029,3031,3034,3036,3039],{"class":378,"line":620},[376,3019,2924],{"class":386},[376,3021,411],{"class":390},[376,3023,2954],{"class":386},[376,3025,868],{"class":390},[376,3027,3028],{"class":386}," _) ",[376,3030,529],{"class":390},[376,3032,3033],{"class":386}," lastPage",[376,3035,489],{"class":390},[376,3037,3038],{"class":386},"nextCursor",[376,3040,431],{"class":390},[376,3042,3043],{"class":378,"line":634},[376,3044,3045],{"class":401},"// If nextCursor is \"\" instead of null, hasNextPage remains true.\n",[376,3047,3048],{"class":378,"line":641},[376,3049,3050],{"class":401},"// Fix: lastPage.nextCursor?.isNotEmpty == true ? lastPage.nextCursor : null\n",[441,3052],{},[448,3054,3056,3057],{"id":3055},"feed-shows-duplicate-items-after-refetch","Feed shows duplicate items after ",[357,3058,3059],{},"refetch()",[353,3061,3062,3064,3065,3068,3069,3072,3073,3075],{},[455,3063,466],{},": Integer page-number pagination combined with server-side insertions. When new posts are added between ",[357,3066,3067],{},"page=1"," and ",[357,3070,3071],{},"page=2",", re-fetching ",[357,3074,3067],{}," returns different items than the first load, causing overlap.",[353,3077,3078,3081],{},[455,3079,3080],{},"Fix",": Use cursor-based pagination. Cursor positions remain stable when new records are inserted.",[366,3083,3085],{"className":368,"code":3084,"language":371,"meta":372,"style":372},"// Bad: Integer pages. Unstable with server-side insertions.\nInfiniteQueryOptions(\n  initialPageParam: 1,\n  getNextPageParam: (_, pages) => pages.length + 1,\n)\n\n// Good: Cursor-based paging. Stable across insertions.\nInfiniteQueryOptions\u003CFeedPage, String?>(\n  initialPageParam: null,\n  getNextPageParam: (last, _) => last.nextCursor,\n)\n",[357,3086,3087,3092,3099,3110,3140,3144,3148,3153,3169,3178,3202],{"__ignoreMap":372},[376,3088,3089],{"class":378,"line":379},[376,3090,3091],{"class":401},"// Bad: Integer pages. Unstable with server-side insertions.\n",[376,3093,3094,3097],{"class":378,"line":405},[376,3095,3096],{"class":394},"InfiniteQueryOptions",[376,3098,515],{"class":386},[376,3100,3101,3104,3106,3108],{"class":378,"line":434},[376,3102,3103],{"class":386},"  initialPageParam",[376,3105,411],{"class":390},[376,3107,2999],{"class":1895},[376,3109,431],{"class":390},[376,3111,3112,3115,3117,3120,3122,3125,3127,3130,3132,3134,3136,3138],{"class":378,"line":518},[376,3113,3114],{"class":386},"  getNextPageParam",[376,3116,411],{"class":390},[376,3118,3119],{"class":386}," (_",[376,3121,868],{"class":390},[376,3123,3124],{"class":386}," pages) ",[376,3126,529],{"class":390},[376,3128,3129],{"class":386}," pages",[376,3131,489],{"class":390},[376,3133,2993],{"class":386},[376,3135,2996],{"class":390},[376,3137,2999],{"class":1895},[376,3139,431],{"class":390},[376,3141,3142],{"class":378,"line":566},[376,3143,1406],{"class":386},[376,3145,3146],{"class":378,"line":612},[376,3147,744],{"emptyLinePlaceholder":743},[376,3149,3150],{"class":378,"line":620},[376,3151,3152],{"class":401},"// Good: Cursor-based paging. Stable across insertions.\n",[376,3154,3155,3157,3159,3162,3164,3166],{"class":378,"line":634},[376,3156,3096],{"class":394},[376,3158,496],{"class":386},[376,3160,3161],{"class":394},"FeedPage",[376,3163,1021],{"class":386},[376,3165,1210],{"class":394},[376,3167,3168],{"class":386},"?>(\n",[376,3170,3171,3173,3175],{"class":378,"line":641},[376,3172,3103],{"class":386},[376,3174,411],{"class":390},[376,3176,3177],{"class":390}," null,\n",[376,3179,3180,3182,3184,3187,3189,3191,3193,3196,3198,3200],{"class":378,"line":938},[376,3181,3114],{"class":386},[376,3183,411],{"class":390},[376,3185,3186],{"class":386}," (last",[376,3188,868],{"class":390},[376,3190,3028],{"class":386},[376,3192,529],{"class":390},[376,3194,3195],{"class":386}," last",[376,3197,489],{"class":390},[376,3199,3038],{"class":386},[376,3201,431],{"class":390},[376,3203,3204],{"class":378,"line":956},[376,3205,1406],{"class":386},[3207,3208,3209],"style",{},"html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .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 .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 .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":372,"searchDepth":405,"depth":405,"links":3211},[3212,3213,3223,3231,3238,3243,3247,3251],{"id":350,"depth":405,"text":351},{"id":445,"depth":405,"text":446,"children":3214},[3215,3216,3218,3219,3221],{"id":450,"depth":434,"text":451},{"id":669,"depth":434,"text":3217},"hydrate() runs but the cache is still empty",{"id":801,"depth":434,"text":802},{"id":1007,"depth":434,"text":3220},"Hydration breaks after a Flutter Web or --obfuscate build",{"id":1138,"depth":434,"text":3222},"fromJson crashes on startup after a model change",{"id":1336,"depth":405,"text":1337,"children":3224},[3225,3227,3229,3230],{"id":1340,"depth":434,"text":3226},"Query is stuck in Initial and never fetches",{"id":1429,"depth":434,"text":3228},"Query is stuck in Loading indefinitely",{"id":1645,"depth":434,"text":1646},{"id":1768,"depth":434,"text":1769},{"id":1852,"depth":405,"text":1853,"children":3232},[3233,3234,3236],{"id":1856,"depth":434,"text":1857},{"id":2006,"depth":434,"text":3235},"QoraBuilder re-subscribes on every rebuild (performance issue)",{"id":2161,"depth":434,"text":3237},"dataOrNull returns null even after a successful fetch",{"id":2267,"depth":405,"text":148,"children":3239},[3240,3241],{"id":2270,"depth":434,"text":2271},{"id":2464,"depth":434,"text":3242},"Using setQueryData for rollback instead of restoreQueryData",{"id":2664,"depth":405,"text":92,"children":3244},[3245],{"id":2667,"depth":434,"text":3246},"context.qora throws FlutterError: QoraScope not found",{"id":2766,"depth":405,"text":2767,"children":3248},[3249,3250],{"id":2770,"depth":434,"text":2771},{"id":2888,"depth":434,"text":2889},{"id":2910,"depth":405,"text":163,"children":3252},[3253,3255],{"id":2913,"depth":434,"text":3254},"fetchNextPage() is called but no new data loads",{"id":3055,"depth":434,"text":3256},"Feed shows duplicate items after refetch()","Diagnose and resolve common Qora issues, including persistence failures, blocked queries, missing refetches, and repeated widget subscriptions.","md",null,{},{"icon":101},{"title":339,"description":3257},"fxngiNi3_F_EfKipidXS7AzP1MYOqS_A9v8o-eywxpw",[3265,3259],{"title":334,"path":335,"stem":336,"description":3266,"icon":337,"children":-1},"Answers to common questions about Qora's API, cache semantics, and Flutter integration.",1794040403075]