[{"data":1,"prerenderedAt":1295},["ShallowReactive",2],{"navigation_docs_en":3,"-en-getting-started-what-is-qora":342,"-en-getting-started-what-is-qora-surround":1292},[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":11,"body":344,"description":1283,"extension":1284,"links":1285,"meta":1286,"navigation":1287,"path":12,"seo":1288,"stem":13,"__hash__":1291},"docs_en/en/01.getting-started/2.what-is-qora.md",{"type":345,"value":346,"toc":1274},"minimark",[347,355,366,371,374,707,710,961,972,976,981,997,1002,1019,1024,1043,1048,1053,1057,1161,1165,1181,1185,1207,1222,1226,1246,1250,1270],[348,349,350,354],"p",{},[351,352,353],"strong",{},"Qora"," is a server-state library for Flutter and Dart. It fetches, caches and synchronizes the data your app loads from an API, and keeps the app usable when the network is not.",[348,356,357,358,365],{},"If you know ",[359,360,364],"a",{"href":361,"rel":362},"https://tanstack.com/query",[363],"nofollow","TanStack Query",", you already know the model: server data is a cache with a lifecycle, not global UI state. Qora brings that model to Dart 3 with sealed classes and pattern matching, and no code generation.",[367,368,370],"h2",{"id":369},"the-problem-it-solves","The problem it solves",[348,372,373],{},"Data that comes from a server is not like a counter or a form field. It can be stale, it is shared between screens, it changes when someone writes to it, and it disappears when the network does. Handled by hand, every screen ends up with the same code:",[375,376,382],"pre",{"className":377,"code":378,"filename":379,"language":380,"meta":381,"style":381},"language-dart shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","class _UserScreenState extends State\u003CUserScreen> {\n  User? _user;\n  Object? _error;\n  bool _loading = false;\n\n  @override\n  void initState() {\n    super.initState();\n    _load();\n  }\n\n  Future\u003Cvoid> _load() async {\n    setState(() => _loading = true);\n    try {\n      _user = await api.getUser(widget.userId); // fetched again on every visit\n      _error = null;\n    } catch (e) {\n      _error = e; // and the previous user is lost on error\n    } finally {\n      setState(() => _loading = false);\n    }\n  }\n  // ...and nothing refreshes this screen when another one edits the user.\n}\n","without_qora.dart","dart","",[383,384,385,414,429,442,457,464,471,484,501,511,517,522,549,573,581,615,626,638,653,663,684,690,695,701],"code",{"__ignoreMap":381},[386,387,390,394,398,401,404,408,411],"span",{"class":388,"line":389},"line",1,[386,391,393],{"class":392},"sMK4o","class",[386,395,397],{"class":396},"sBMFI"," _UserScreenState",[386,399,400],{"class":392}," extends",[386,402,403],{"class":396}," State",[386,405,407],{"class":406},"sTEyZ","\u003C",[386,409,410],{"class":396},"UserScreen",[386,412,413],{"class":406},"> {\n",[386,415,417,420,423,426],{"class":388,"line":416},2,[386,418,419],{"class":396},"  User",[386,421,422],{"class":392},"?",[386,424,425],{"class":406}," _user",[386,427,428],{"class":392},";\n",[386,430,432,435,437,440],{"class":388,"line":431},3,[386,433,434],{"class":396},"  Object",[386,436,422],{"class":392},[386,438,439],{"class":406}," _error",[386,441,428],{"class":392},[386,443,445,448,451,454],{"class":388,"line":444},4,[386,446,447],{"class":396},"  bool",[386,449,450],{"class":406}," _loading ",[386,452,453],{"class":392},"=",[386,455,456],{"class":392}," false;\n",[386,458,460],{"class":388,"line":459},5,[386,461,463],{"emptyLinePlaceholder":462},true,"\n",[386,465,467],{"class":388,"line":466},6,[386,468,470],{"class":469},"spNyl","  @override\n",[386,472,474,477,481],{"class":388,"line":473},7,[386,475,476],{"class":469},"  void",[386,478,480],{"class":479},"s2Zo4"," initState",[386,482,483],{"class":406},"() {\n",[386,485,487,490,493,496,499],{"class":388,"line":486},8,[386,488,489],{"class":406},"    super",[386,491,492],{"class":392},".",[386,494,495],{"class":479},"initState",[386,497,498],{"class":406},"()",[386,500,428],{"class":392},[386,502,504,507,509],{"class":388,"line":503},9,[386,505,506],{"class":479},"    _load",[386,508,498],{"class":406},[386,510,428],{"class":392},[386,512,514],{"class":388,"line":513},10,[386,515,516],{"class":406},"  }\n",[386,518,520],{"class":388,"line":519},11,[386,521,463],{"emptyLinePlaceholder":462},[386,523,525,528,530,533,536,539,542,546],{"class":388,"line":524},12,[386,526,527],{"class":396},"  Future",[386,529,407],{"class":406},[386,531,532],{"class":469},"void",[386,534,535],{"class":406},"> ",[386,537,538],{"class":479},"_load",[386,540,541],{"class":406},"() ",[386,543,545],{"class":544},"s7zQu","async",[386,547,548],{"class":406}," {\n",[386,550,552,555,558,561,563,565,568,571],{"class":388,"line":551},13,[386,553,554],{"class":479},"    setState",[386,556,557],{"class":406},"(() ",[386,559,560],{"class":392},"=>",[386,562,450],{"class":406},[386,564,453],{"class":392},[386,566,567],{"class":392}," true",[386,569,570],{"class":406},")",[386,572,428],{"class":392},[386,574,576,579],{"class":388,"line":575},14,[386,577,578],{"class":544},"    try",[386,580,548],{"class":406},[386,582,584,587,589,592,595,597,600,603,605,608,611],{"class":388,"line":583},15,[386,585,586],{"class":406},"      _user ",[386,588,453],{"class":392},[386,590,591],{"class":544}," await",[386,593,594],{"class":406}," api",[386,596,492],{"class":392},[386,598,599],{"class":479},"getUser",[386,601,602],{"class":406},"(widget",[386,604,492],{"class":392},[386,606,607],{"class":406},"userId)",[386,609,610],{"class":392},";",[386,612,614],{"class":613},"sHwdD"," // fetched again on every visit\n",[386,616,618,621,623],{"class":388,"line":617},16,[386,619,620],{"class":406},"      _error ",[386,622,453],{"class":392},[386,624,625],{"class":392}," null;\n",[386,627,629,632,635],{"class":388,"line":628},17,[386,630,631],{"class":406},"    } ",[386,633,634],{"class":544},"catch",[386,636,637],{"class":406}," (e) {\n",[386,639,641,643,645,648,650],{"class":388,"line":640},18,[386,642,620],{"class":406},[386,644,453],{"class":392},[386,646,647],{"class":406}," e",[386,649,610],{"class":392},[386,651,652],{"class":613}," // and the previous user is lost on error\n",[386,654,656,658,661],{"class":388,"line":655},19,[386,657,631],{"class":406},[386,659,660],{"class":544},"finally",[386,662,548],{"class":406},[386,664,666,669,671,673,675,677,680,682],{"class":388,"line":665},20,[386,667,668],{"class":479},"      setState",[386,670,557],{"class":406},[386,672,560],{"class":392},[386,674,450],{"class":406},[386,676,453],{"class":392},[386,678,679],{"class":392}," false",[386,681,570],{"class":406},[386,683,428],{"class":392},[386,685,687],{"class":388,"line":686},21,[386,688,689],{"class":406},"    }\n",[386,691,693],{"class":388,"line":692},22,[386,694,516],{"class":406},[386,696,698],{"class":388,"line":697},23,[386,699,700],{"class":613},"  // ...and nothing refreshes this screen when another one edits the user.\n",[386,702,704],{"class":388,"line":703},24,[386,705,706],{"class":406},"}\n",[348,708,709],{},"With Qora, the screen declares which data it needs and how to render each state:",[375,711,714],{"className":377,"code":712,"filename":713,"language":380,"meta":381,"style":381},"QoraBuilder\u003CUser>(\n  queryKey: ['users', userId],\n  fetcher: () => api.getUser(userId),\n  builder: (context, state, fetchStatus) => switch (state) {\n    Success(:final data) => UserCard(data),\n    Failure(:final error, :final previousData) =>\n      previousData != null ? UserCard(previousData) : ErrorView(error),\n    Loading(:final previousData) =>\n      previousData != null ? UserCard(previousData) : const LoadingView(),\n    Initial() => const SizedBox.shrink(),\n  },\n)\n","user_screen.dart",[383,715,716,728,752,775,803,829,856,885,900,926,949,956],{"__ignoreMap":381},[386,717,718,720,722,725],{"class":388,"line":389},[386,719,108],{"class":396},[386,721,407],{"class":406},[386,723,724],{"class":396},"User",[386,726,727],{"class":406},">(\n",[386,729,730,733,736,739,743,746,749],{"class":388,"line":416},[386,731,732],{"class":406},"  queryKey",[386,734,735],{"class":392},":",[386,737,738],{"class":406}," [",[386,740,742],{"class":741},"sfazB","'users'",[386,744,745],{"class":392},",",[386,747,748],{"class":406}," userId]",[386,750,751],{"class":392},",\n",[386,753,754,757,759,762,764,766,768,770,773],{"class":388,"line":431},[386,755,756],{"class":406},"  fetcher",[386,758,735],{"class":392},[386,760,761],{"class":406}," () ",[386,763,560],{"class":392},[386,765,594],{"class":406},[386,767,492],{"class":392},[386,769,599],{"class":479},[386,771,772],{"class":406},"(userId)",[386,774,751],{"class":392},[386,776,777,780,782,785,787,790,792,795,797,800],{"class":388,"line":444},[386,778,779],{"class":406},"  builder",[386,781,735],{"class":392},[386,783,784],{"class":406}," (context",[386,786,745],{"class":392},[386,788,789],{"class":406}," state",[386,791,745],{"class":392},[386,793,794],{"class":406}," fetchStatus) ",[386,796,560],{"class":392},[386,798,799],{"class":544}," switch",[386,801,802],{"class":406}," (state) {\n",[386,804,805,808,811,813,816,819,821,824,827],{"class":388,"line":459},[386,806,807],{"class":396},"    Success",[386,809,810],{"class":406},"(",[386,812,735],{"class":392},[386,814,815],{"class":469},"final",[386,817,818],{"class":406}," data) ",[386,820,560],{"class":392},[386,822,823],{"class":396}," UserCard",[386,825,826],{"class":406},"(data)",[386,828,751],{"class":392},[386,830,831,834,836,838,840,843,845,848,850,853],{"class":388,"line":466},[386,832,833],{"class":396},"    Failure",[386,835,810],{"class":406},[386,837,735],{"class":392},[386,839,815],{"class":469},[386,841,842],{"class":406}," error",[386,844,745],{"class":392},[386,846,847],{"class":392}," :",[386,849,815],{"class":469},[386,851,852],{"class":406}," previousData) ",[386,854,855],{"class":392},"=>\n",[386,857,858,861,864,867,870,872,875,877,880,883],{"class":388,"line":473},[386,859,860],{"class":406},"      previousData ",[386,862,863],{"class":392},"!=",[386,865,866],{"class":392}," null",[386,868,869],{"class":392}," ?",[386,871,823],{"class":396},[386,873,874],{"class":406},"(previousData) ",[386,876,735],{"class":392},[386,878,879],{"class":396}," ErrorView",[386,881,882],{"class":406},"(error)",[386,884,751],{"class":392},[386,886,887,890,892,894,896,898],{"class":388,"line":486},[386,888,889],{"class":396},"    Loading",[386,891,810],{"class":406},[386,893,735],{"class":392},[386,895,815],{"class":469},[386,897,852],{"class":406},[386,899,855],{"class":392},[386,901,902,904,906,908,910,912,914,916,919,922,924],{"class":388,"line":503},[386,903,860],{"class":406},[386,905,863],{"class":392},[386,907,866],{"class":392},[386,909,869],{"class":392},[386,911,823],{"class":396},[386,913,874],{"class":406},[386,915,735],{"class":392},[386,917,918],{"class":469}," const",[386,920,921],{"class":396}," LoadingView",[386,923,498],{"class":406},[386,925,751],{"class":392},[386,927,928,931,933,935,937,940,942,945,947],{"class":388,"line":513},[386,929,930],{"class":396},"    Initial",[386,932,541],{"class":406},[386,934,560],{"class":392},[386,936,918],{"class":469},[386,938,939],{"class":396}," SizedBox",[386,941,492],{"class":392},[386,943,944],{"class":479},"shrink",[386,946,498],{"class":406},[386,948,751],{"class":392},[386,950,951,954],{"class":388,"line":519},[386,952,953],{"class":406},"  }",[386,955,751],{"class":392},[386,957,958],{"class":388,"line":524},[386,959,960],{"class":406},")\n",[348,962,963,964,967,968,971],{},"The second visit renders the cached user on the first frame and refreshes it in the background. Two widgets asking for ",[383,965,966],{},"['users', userId]"," share one request. After ",[383,969,970],{},"client.invalidate(['users', userId])",", every screen showing that user refetches. The compiler checks that every state is handled.",[367,973,975],{"id":974},"what-you-get","What you get",[348,977,978],{},[351,979,980],{},"Fetching and caching",[982,983,984,988,991,994],"ul",{},[985,986,987],"li",{},"Stale-while-revalidate: cached data first, fresh data in the background",[985,989,990],{},"Request deduplication and automatic retries with exponential backoff",[985,992,993],{},"Invalidation by exact key, key prefix, predicate or tag",[985,995,996],{},"Infinite queries, dependent queries, polling, prefetching",[348,998,999],{},[351,1000,1001],{},"Offline",[982,1003,1004,1009,1016],{},[985,1005,1006,1008],{},[383,1007,229],{},": cached data saved to storage and restored before the first frame",[985,1010,1011,1012,1015],{},"Queries that pause while offline, report it through ",[383,1013,1014],{},"FetchStatus.paused",", and resume on reconnect",[985,1017,1018],{},"An offline mutation queue that replays writes in order when the network returns (held in memory; persisted across restarts in 1.4)",[348,1020,1021],{},[351,1022,1023],{},"Writes",[982,1025,1026,1040],{},[985,1027,1028,1029,1032,1033,1032,1036,1039],{},"Mutations with ",[383,1030,1031],{},"onMutate"," / ",[383,1034,1035],{},"onError",[383,1037,1038],{},"onSuccess"," for optimistic updates and rollback",[985,1041,1042],{},"Automatic invalidation after a successful mutation",[348,1044,1045],{},[351,1046,1047],{},"Tooling",[982,1049,1050],{},[985,1051,1052],{},"An in-app DevTools overlay showing every query and mutation in debug builds",[367,1054,1056],{"id":1055},"packages","Packages",[1058,1059,1060,1073],"table",{},[1061,1062,1063],"thead",{},[1064,1065,1066,1070],"tr",{},[1067,1068,1069],"th",{},"Package",[1067,1071,1072],{},"Use it for",[1074,1075,1076,1104,1134,1147],"tbody",{},[1064,1077,1078,1088],{},[1079,1080,1081],"td",{},[359,1082,1085],{"href":1083,"rel":1084},"https://pub.dev/packages/qora_flutter",[363],[383,1086,1087],{},"qora_flutter",[1079,1089,1090,1091,1093,1094,1093,1096,1093,1098,1100,1101,492],{},"Flutter apps. Widgets (",[383,1092,103],{},", ",[383,1095,108],{},[383,1097,113],{},[383,1099,118],{},"), lifecycle and connectivity managers. Includes ",[383,1102,1103],{},"qora",[1064,1105,1106,1115],{},[1079,1107,1108],{},[359,1109,1112],{"href":1110,"rel":1111},"https://pub.dev/packages/qora_hooks",[363],[383,1113,1114],{},"qora_hooks",[1079,1116,1117,1118,1121,1122,1093,1125,1093,1128,1093,1131,492],{},"Apps using ",[383,1119,1120],{},"flutter_hooks",": ",[383,1123,1124],{},"useQuery",[383,1126,1127],{},"useMutation",[383,1129,1130],{},"useInfiniteQuery",[383,1132,1133],{},"useFetchStatus",[1064,1135,1136,1144],{},[1079,1137,1138],{},[359,1139,1142],{"href":1140,"rel":1141},"https://pub.dev/packages/qora",[363],[383,1143,1103],{},[1079,1145,1146],{},"Pure Dart: CLIs, servers, shared packages, tests. No Flutter dependency.",[1064,1148,1149,1158],{},[1079,1150,1151],{},[359,1152,1155],{"href":1153,"rel":1154},"https://pub.dev/packages/qora_devtools_overlay",[363],[383,1156,1157],{},"qora_devtools_overlay",[1079,1159,1160],{},"The in-app debug panel, as a dev dependency.",[367,1162,1164],{"id":1163},"server-state-and-client-state","Server state and client state",[348,1166,1167,1168,1171,1172,1175,1176,1180],{},"Qora manages ",[351,1169,1170],{},"server state",": data that lives on a server and is fetched, cached and re-synchronized. It does not replace your state management for ",[351,1173,1174],{},"client state",": the selected tab, form input, the current theme. Keep Riverpod, BLoC or Provider for those; the ",[359,1177,1179],{"href":1178},"../third-party/with-riverpod","integration guides"," show how they fit together.",[367,1182,1184],{"id":1183},"when-not-to-use-qora","When not to use Qora",[982,1186,1187,1197],{},[985,1188,1189,1192,1193,1196],{},[351,1190,1191],{},"A read-only app that is always online and never shows the same data twice."," A ",[383,1194,1195],{},"FutureBuilder"," is enough.",[985,1198,1199,1202,1203,1206],{},[351,1200,1201],{},"Real-time data pushed over a socket."," You can write socket events into the cache with ",[383,1204,1205],{},"setQueryData",", but the stream itself is not Qora's job.",[348,1208,1209,1210,1213,1214,1217,1218,492],{},"For a side-by-side look at ",[383,1211,1212],{},"cached_query"," and ",[383,1215,1216],{},"flutter_query",", see the ",[359,1219,1221],{"href":1220},"./comparison","comparison",[367,1223,1225],{"id":1224},"requirements","Requirements",[982,1227,1228,1235],{},[985,1229,1230,1231,1234],{},"Dart ",[351,1232,1233],{},"3.5"," or later",[985,1236,1237,1238,1241,1242,1213,1244,570],{},"Flutter ",[351,1239,1240],{},"3.24"," or later (for ",[383,1243,1087],{},[383,1245,1114],{},[367,1247,1249],{"id":1248},"next-steps","Next steps",[982,1251,1252,1258,1264],{},[985,1253,1254,1257],{},[359,1255,16],{"href":1256},"./installation",": add Qora and wrap your app",[985,1259,1260,1263],{},[359,1261,21],{"href":1262},"./quick-start",": a list and a detail screen, then take them offline",[985,1265,1266,1269],{},[359,1267,30],{"href":1268},"./coming-from-tanstack-query",": the API mapped option by option",[1271,1272,1273],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .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 .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":381,"searchDepth":416,"depth":416,"links":1275},[1276,1277,1278,1279,1280,1281,1282],{"id":369,"depth":416,"text":370},{"id":974,"depth":416,"text":975},{"id":1055,"depth":416,"text":1056},{"id":1163,"depth":416,"text":1164},{"id":1183,"depth":416,"text":1184},{"id":1224,"depth":416,"text":1225},{"id":1248,"depth":416,"text":1249},"Qora fetches, caches and synchronizes server data in Flutter and Dart, and keeps your app usable when the network is not.","md",null,{},{"icon":14},{"title":1289,"description":1290},"What is Qora? Server state for Flutter apps that keep working offline","Qora fetches, caches and synchronizes server data in Flutter and Dart. Cached data on the first frame, queries that pause offline, writes queued and replayed on reconnect.","0t-YMBtNFlXaZHwC1z0HzRkd9RBXuArJeJaOCCgzfmk",[1285,1293],{"title":16,"path":17,"stem":18,"description":1294,"icon":19,"children":-1},"Add Qora to a Flutter app or a pure Dart project, and wire it in one widget.",1794040396327]