[{"data":1,"prerenderedAt":3032},["ShallowReactive",2],{"page-\u002Fvue\u002F10-state-management-pinia":3},{"id":4,"title":5,"body":6,"description":3025,"extension":3026,"meta":3027,"navigation":62,"path":3028,"seo":3029,"stem":3030,"__hash__":3031},"content\u002Fvue\u002F10-state-management-pinia.md","Vue 3 Engineering Reference — State Management with Pinia",{"type":7,"value":8,"toc":3014},"minimark",[9,14,19,619,623,1304,1308,1520,1524,1817,1821,3010],[10,11,13],"h1",{"id":12},"_10-state-management-with-pinia","10 — State Management with Pinia",[15,16,18],"h2",{"id":17},"setup-store-composition-api-style","Setup Store — Composition API Style",[20,21,24],"code-wrapper",{"filename":22,"language":23},"stores\u002Fuser.ts","typescript",[25,26,30],"pre",{"className":27,"code":28,"language":23,"meta":29,"style":29},"language-typescript shiki shiki-themes github-light github-dark","import { defineStore, ref, computed } from '#imports'  \u002F\u002F Nuxt auto-import; else from 'pinia'\n\n\u002F\u002F ── defineStore with setup function (Composition API style) ──\n\u002F\u002F More flexible than Options API stores: can use any composable, watcher, etc.\nexport const useUserStore = defineStore('user', () => {\n  \u002F\u002F ── State: refs ────────────────────────────────────────\n  const user = ref\u003C{ id: number; name: string; email: string } | null>(null)\n  const token = ref\u003Cstring | null>(null)\n  const loading = ref(false)\n\n  \u002F\u002F ── Getters: computed ───────────────────────────────────\n  const isAuthenticated = computed(() => !!token.value && !!user.value)\n  const displayName = computed(() => user.value?.name ?? 'Guest')\n\n  \u002F\u002F ── Actions: plain functions (can be async) ─────────────\n  async function login(credentials: { email: string; password: string }) {\n    loading.value = true\n    try {\n      const res = await fetch('\u002Fapi\u002Fauth\u002Flogin', {\n        method: 'POST',\n        body: JSON.stringify(credentials),\n      })\n      const data = await res.json()\n      user.value = data.user\n      token.value = data.token\n      localStorage.setItem('token', data.token)  \u002F\u002F persistence\n    } finally {\n      loading.value = false\n    }\n  }\n\n  function logout() {\n    user.value = null\n    token.value = null\n    localStorage.removeItem('token')\n  }\n\n  \u002F\u002F ── Everything returned is part of the store's public API ──\n  \u002F\u002F State (refs), getters (computed), and actions (functions) all exposed.\n  return { user, token, loading, isAuthenticated, displayName, login, logout }\n})\n","",[31,32,33,57,64,70,76,111,117,182,211,230,235,241,273,300,305,311,351,363,371,396,408,426,432,453,464,475,495,506,517,523,529,534,546,557,567,582,587,592,598,604,613],"code",{"__ignoreMap":29},[34,35,38,42,46,49,53],"span",{"class":36,"line":37},"line",1,[34,39,41],{"class":40},"svdQ7","import",[34,43,45],{"class":44},"ssxIu"," { defineStore, ref, computed } ",[34,47,48],{"class":40},"from",[34,50,52],{"class":51},"sJ6F3"," '#imports'",[34,54,56],{"class":55},"sdCPZ","  \u002F\u002F Nuxt auto-import; else from 'pinia'\n",[34,58,60],{"class":36,"line":59},2,[34,61,63],{"emptyLinePlaceholder":62},true,"\n",[34,65,67],{"class":36,"line":66},3,[34,68,69],{"class":55},"\u002F\u002F ── defineStore with setup function (Composition API style) ──\n",[34,71,73],{"class":36,"line":72},4,[34,74,75],{"class":55},"\u002F\u002F More flexible than Options API stores: can use any composable, watcher, etc.\n",[34,77,79,82,85,89,92,96,99,102,105,108],{"class":36,"line":78},5,[34,80,81],{"class":40},"export",[34,83,84],{"class":40}," const",[34,86,88],{"class":87},"snvgF"," useUserStore",[34,90,91],{"class":40}," =",[34,93,95],{"class":94},"sIsaT"," defineStore",[34,97,98],{"class":44},"(",[34,100,101],{"class":51},"'user'",[34,103,104],{"class":44},", () ",[34,106,107],{"class":40},"=>",[34,109,110],{"class":44}," {\n",[34,112,114],{"class":36,"line":113},6,[34,115,116],{"class":55},"  \u002F\u002F ── State: refs ────────────────────────────────────────\n",[34,118,120,123,126,128,131,134,138,141,144,147,150,152,155,157,160,162,164,167,170,173,176,179],{"class":36,"line":119},7,[34,121,122],{"class":40},"  const",[34,124,125],{"class":87}," user",[34,127,91],{"class":40},[34,129,130],{"class":94}," ref",[34,132,133],{"class":44},"\u003C{ ",[34,135,137],{"class":136},"sCrzJ","id",[34,139,140],{"class":40},":",[34,142,143],{"class":87}," number",[34,145,146],{"class":44},"; ",[34,148,149],{"class":136},"name",[34,151,140],{"class":40},[34,153,154],{"class":87}," string",[34,156,146],{"class":44},[34,158,159],{"class":136},"email",[34,161,140],{"class":40},[34,163,154],{"class":87},[34,165,166],{"class":44}," } ",[34,168,169],{"class":40},"|",[34,171,172],{"class":87}," null",[34,174,175],{"class":44},">(",[34,177,178],{"class":87},"null",[34,180,181],{"class":44},")\n",[34,183,185,187,190,192,194,197,200,203,205,207,209],{"class":36,"line":184},8,[34,186,122],{"class":40},[34,188,189],{"class":87}," token",[34,191,91],{"class":40},[34,193,130],{"class":94},[34,195,196],{"class":44},"\u003C",[34,198,199],{"class":87},"string",[34,201,202],{"class":40}," |",[34,204,172],{"class":87},[34,206,175],{"class":44},[34,208,178],{"class":87},[34,210,181],{"class":44},[34,212,214,216,219,221,223,225,228],{"class":36,"line":213},9,[34,215,122],{"class":40},[34,217,218],{"class":87}," loading",[34,220,91],{"class":40},[34,222,130],{"class":94},[34,224,98],{"class":44},[34,226,227],{"class":87},"false",[34,229,181],{"class":44},[34,231,233],{"class":36,"line":232},10,[34,234,63],{"emptyLinePlaceholder":62},[34,236,238],{"class":36,"line":237},11,[34,239,240],{"class":55},"  \u002F\u002F ── Getters: computed ───────────────────────────────────\n",[34,242,244,246,249,251,254,257,259,262,265,268,270],{"class":36,"line":243},12,[34,245,122],{"class":40},[34,247,248],{"class":87}," isAuthenticated",[34,250,91],{"class":40},[34,252,253],{"class":94}," computed",[34,255,256],{"class":44},"(() ",[34,258,107],{"class":40},[34,260,261],{"class":40}," !!",[34,263,264],{"class":44},"token.value ",[34,266,267],{"class":40},"&&",[34,269,261],{"class":40},[34,271,272],{"class":44},"user.value)\n",[34,274,276,278,281,283,285,287,289,292,295,298],{"class":36,"line":275},13,[34,277,122],{"class":40},[34,279,280],{"class":87}," displayName",[34,282,91],{"class":40},[34,284,253],{"class":94},[34,286,256],{"class":44},[34,288,107],{"class":40},[34,290,291],{"class":44}," user.value?.name ",[34,293,294],{"class":40},"??",[34,296,297],{"class":51}," 'Guest'",[34,299,181],{"class":44},[34,301,303],{"class":36,"line":302},14,[34,304,63],{"emptyLinePlaceholder":62},[34,306,308],{"class":36,"line":307},15,[34,309,310],{"class":55},"  \u002F\u002F ── Actions: plain functions (can be async) ─────────────\n",[34,312,314,317,320,323,325,328,330,333,335,337,339,341,344,346,348],{"class":36,"line":313},16,[34,315,316],{"class":40},"  async",[34,318,319],{"class":40}," function",[34,321,322],{"class":94}," login",[34,324,98],{"class":44},[34,326,327],{"class":136},"credentials",[34,329,140],{"class":40},[34,331,332],{"class":44}," { ",[34,334,159],{"class":136},[34,336,140],{"class":40},[34,338,154],{"class":87},[34,340,146],{"class":44},[34,342,343],{"class":136},"password",[34,345,140],{"class":40},[34,347,154],{"class":87},[34,349,350],{"class":44}," }) {\n",[34,352,354,357,360],{"class":36,"line":353},17,[34,355,356],{"class":44},"    loading.value ",[34,358,359],{"class":40},"=",[34,361,362],{"class":87}," true\n",[34,364,366,369],{"class":36,"line":365},18,[34,367,368],{"class":40},"    try",[34,370,110],{"class":44},[34,372,374,377,380,382,385,388,390,393],{"class":36,"line":373},19,[34,375,376],{"class":40},"      const",[34,378,379],{"class":87}," res",[34,381,91],{"class":40},[34,383,384],{"class":40}," await",[34,386,387],{"class":94}," fetch",[34,389,98],{"class":44},[34,391,392],{"class":51},"'\u002Fapi\u002Fauth\u002Flogin'",[34,394,395],{"class":44},", {\n",[34,397,399,402,405],{"class":36,"line":398},20,[34,400,401],{"class":44},"        method: ",[34,403,404],{"class":51},"'POST'",[34,406,407],{"class":44},",\n",[34,409,411,414,417,420,423],{"class":36,"line":410},21,[34,412,413],{"class":44},"        body: ",[34,415,416],{"class":87},"JSON",[34,418,419],{"class":44},".",[34,421,422],{"class":94},"stringify",[34,424,425],{"class":44},"(credentials),\n",[34,427,429],{"class":36,"line":428},22,[34,430,431],{"class":44},"      })\n",[34,433,435,437,440,442,444,447,450],{"class":36,"line":434},23,[34,436,376],{"class":40},[34,438,439],{"class":87}," data",[34,441,91],{"class":40},[34,443,384],{"class":40},[34,445,446],{"class":44}," res.",[34,448,449],{"class":94},"json",[34,451,452],{"class":44},"()\n",[34,454,456,459,461],{"class":36,"line":455},24,[34,457,458],{"class":44},"      user.value ",[34,460,359],{"class":40},[34,462,463],{"class":44}," data.user\n",[34,465,467,470,472],{"class":36,"line":466},25,[34,468,469],{"class":44},"      token.value ",[34,471,359],{"class":40},[34,473,474],{"class":44}," data.token\n",[34,476,478,481,484,486,489,492],{"class":36,"line":477},26,[34,479,480],{"class":44},"      localStorage.",[34,482,483],{"class":94},"setItem",[34,485,98],{"class":44},[34,487,488],{"class":51},"'token'",[34,490,491],{"class":44},", data.token)  ",[34,493,494],{"class":55},"\u002F\u002F persistence\n",[34,496,498,501,504],{"class":36,"line":497},27,[34,499,500],{"class":44},"    } ",[34,502,503],{"class":40},"finally",[34,505,110],{"class":44},[34,507,509,512,514],{"class":36,"line":508},28,[34,510,511],{"class":44},"      loading.value ",[34,513,359],{"class":40},[34,515,516],{"class":87}," false\n",[34,518,520],{"class":36,"line":519},29,[34,521,522],{"class":44},"    }\n",[34,524,526],{"class":36,"line":525},30,[34,527,528],{"class":44},"  }\n",[34,530,532],{"class":36,"line":531},31,[34,533,63],{"emptyLinePlaceholder":62},[34,535,537,540,543],{"class":36,"line":536},32,[34,538,539],{"class":40},"  function",[34,541,542],{"class":94}," logout",[34,544,545],{"class":44},"() {\n",[34,547,549,552,554],{"class":36,"line":548},33,[34,550,551],{"class":44},"    user.value ",[34,553,359],{"class":40},[34,555,556],{"class":87}," null\n",[34,558,560,563,565],{"class":36,"line":559},34,[34,561,562],{"class":44},"    token.value ",[34,564,359],{"class":40},[34,566,556],{"class":87},[34,568,570,573,576,578,580],{"class":36,"line":569},35,[34,571,572],{"class":44},"    localStorage.",[34,574,575],{"class":94},"removeItem",[34,577,98],{"class":44},[34,579,488],{"class":51},[34,581,181],{"class":44},[34,583,585],{"class":36,"line":584},36,[34,586,528],{"class":44},[34,588,590],{"class":36,"line":589},37,[34,591,63],{"emptyLinePlaceholder":62},[34,593,595],{"class":36,"line":594},38,[34,596,597],{"class":55},"  \u002F\u002F ── Everything returned is part of the store's public API ──\n",[34,599,601],{"class":36,"line":600},39,[34,602,603],{"class":55},"  \u002F\u002F State (refs), getters (computed), and actions (functions) all exposed.\n",[34,605,607,610],{"class":36,"line":606},40,[34,608,609],{"class":40},"  return",[34,611,612],{"class":44}," { user, token, loading, isAuthenticated, displayName, login, logout }\n",[34,614,616],{"class":36,"line":615},41,[34,617,618],{"class":44},"})\n",[15,620,622],{"id":621},"options-store-the-alternative","Options Store — The Alternative",[20,624,626],{"filename":625,"language":23},"stores\u002Fcart.ts",[25,627,629],{"className":27,"code":628,"language":23,"meta":29,"style":29},"import { defineStore } from 'pinia'\n\n\u002F\u002F ── Options API style store: state\u002Fgetters\u002Factions separated ──\n\u002F\u002F More structured, less flexible. Similar to Vue's Options API.\nexport const useCartStore = defineStore('cart', {\n  \u002F\u002F ── State: a function returning the initial state (like data()) ──\n  \u002F\u002F MUST be a function (not a plain object) — fresh copy per store instance.\n  state: () => ({\n    items: [] as Array\u003C{ id: number; name: string; price: number; qty: number }>,\n    couponCode: null as string | null,\n  }),\n\n  \u002F\u002F ── Getters: like computed, access state via `this` ──\n  getters: {\n    count: (state) => state.items.reduce((sum, i) => sum + i.qty, 0),\n\n    \u002F\u002F ── Getter with parameter: return a function from a getter ──\n    itemPrice: (state) => (id: number) =>\n      state.items.find(i => i.id === id)?.price ?? 0,\n\n    \u002F\u002F ── Getter using another getter: access via `this` ──\n    total: (state) => {\n      return state.items.reduce((sum, i) => sum + i.price * i.qty, 0)\n    },\n    \u002F\u002F For getters referencing other getters, use `this`:\n    \u002F\u002F totalWithTax() { return this.total * 1.08 }\n  },\n\n  \u002F\u002F ── Actions: methods, mutate state via `this` ──\n  actions: {\n    addItem(item: { id: number; name: string; price: number }) {\n      const existing = this.items.find(i => i.id === item.id)\n      if (existing) {\n        existing.qty++  \u002F\u002F direct mutation — Pinia allows it\n      } else {\n        this.items.push({ ...item, qty: 1 })\n      }\n    },\n\n    removeItem(id: number) {\n      this.items = this.items.filter(i => i.id !== id)\n    },\n\n    \u002F\u002F ── Actions can be async ──\n    async checkout() {\n      const res = await fetch('\u002Fapi\u002Fcheckout', {\n        method: 'POST',\n        body: JSON.stringify({ items: this.items, coupon: this.couponCode }),\n      })\n      if (res.ok) this.$reset()  \u002F\u002F reset to initial state\n    },\n  },\n})\n",[31,630,631,643,647,652,657,677,682,687,700,748,766,771,775,780,785,838,842,847,874,905,909,914,929,966,971,976,981,986,990,995,1000,1038,1068,1076,1087,1097,1122,1127,1131,1135,1151,1182,1187,1192,1198,1209,1229,1238,1263,1268,1289,1294,1299],{"__ignoreMap":29},[34,632,633,635,638,640],{"class":36,"line":37},[34,634,41],{"class":40},[34,636,637],{"class":44}," { defineStore } ",[34,639,48],{"class":40},[34,641,642],{"class":51}," 'pinia'\n",[34,644,645],{"class":36,"line":59},[34,646,63],{"emptyLinePlaceholder":62},[34,648,649],{"class":36,"line":66},[34,650,651],{"class":55},"\u002F\u002F ── Options API style store: state\u002Fgetters\u002Factions separated ──\n",[34,653,654],{"class":36,"line":72},[34,655,656],{"class":55},"\u002F\u002F More structured, less flexible. Similar to Vue's Options API.\n",[34,658,659,661,663,666,668,670,672,675],{"class":36,"line":78},[34,660,81],{"class":40},[34,662,84],{"class":40},[34,664,665],{"class":87}," useCartStore",[34,667,91],{"class":40},[34,669,95],{"class":94},[34,671,98],{"class":44},[34,673,674],{"class":51},"'cart'",[34,676,395],{"class":44},[34,678,679],{"class":36,"line":113},[34,680,681],{"class":55},"  \u002F\u002F ── State: a function returning the initial state (like data()) ──\n",[34,683,684],{"class":36,"line":119},[34,685,686],{"class":55},"  \u002F\u002F MUST be a function (not a plain object) — fresh copy per store instance.\n",[34,688,689,692,695,697],{"class":36,"line":184},[34,690,691],{"class":94},"  state",[34,693,694],{"class":44},": () ",[34,696,107],{"class":40},[34,698,699],{"class":44}," ({\n",[34,701,702,705,708,711,713,715,717,719,721,723,725,727,729,732,734,736,738,741,743,745],{"class":36,"line":213},[34,703,704],{"class":44},"    items: [] ",[34,706,707],{"class":40},"as",[34,709,710],{"class":94}," Array",[34,712,133],{"class":44},[34,714,137],{"class":136},[34,716,140],{"class":40},[34,718,143],{"class":87},[34,720,146],{"class":44},[34,722,149],{"class":136},[34,724,140],{"class":40},[34,726,154],{"class":87},[34,728,146],{"class":44},[34,730,731],{"class":136},"price",[34,733,140],{"class":40},[34,735,143],{"class":87},[34,737,146],{"class":44},[34,739,740],{"class":136},"qty",[34,742,140],{"class":40},[34,744,143],{"class":87},[34,746,747],{"class":44}," }>,\n",[34,749,750,753,755,758,760,762,764],{"class":36,"line":232},[34,751,752],{"class":44},"    couponCode: ",[34,754,178],{"class":87},[34,756,757],{"class":40}," as",[34,759,154],{"class":87},[34,761,202],{"class":40},[34,763,172],{"class":87},[34,765,407],{"class":44},[34,767,768],{"class":36,"line":237},[34,769,770],{"class":44},"  }),\n",[34,772,773],{"class":36,"line":243},[34,774,63],{"emptyLinePlaceholder":62},[34,776,777],{"class":36,"line":275},[34,778,779],{"class":55},"  \u002F\u002F ── Getters: like computed, access state via `this` ──\n",[34,781,782],{"class":36,"line":302},[34,783,784],{"class":44},"  getters: {\n",[34,786,787,790,793,796,799,801,804,807,810,813,816,819,821,823,826,829,832,835],{"class":36,"line":307},[34,788,789],{"class":94},"    count",[34,791,792],{"class":44},": (",[34,794,795],{"class":136},"state",[34,797,798],{"class":44},") ",[34,800,107],{"class":40},[34,802,803],{"class":44}," state.items.",[34,805,806],{"class":94},"reduce",[34,808,809],{"class":44},"((",[34,811,812],{"class":136},"sum",[34,814,815],{"class":44},", ",[34,817,818],{"class":136},"i",[34,820,798],{"class":44},[34,822,107],{"class":40},[34,824,825],{"class":44}," sum ",[34,827,828],{"class":40},"+",[34,830,831],{"class":44}," i.qty, ",[34,833,834],{"class":87},"0",[34,836,837],{"class":44},"),\n",[34,839,840],{"class":36,"line":313},[34,841,63],{"emptyLinePlaceholder":62},[34,843,844],{"class":36,"line":353},[34,845,846],{"class":55},"    \u002F\u002F ── Getter with parameter: return a function from a getter ──\n",[34,848,849,852,854,856,858,860,863,865,867,869,871],{"class":36,"line":365},[34,850,851],{"class":94},"    itemPrice",[34,853,792],{"class":44},[34,855,795],{"class":136},[34,857,798],{"class":44},[34,859,107],{"class":40},[34,861,862],{"class":44}," (",[34,864,137],{"class":136},[34,866,140],{"class":40},[34,868,143],{"class":87},[34,870,798],{"class":44},[34,872,873],{"class":40},"=>\n",[34,875,876,879,882,884,886,889,892,895,898,900,903],{"class":36,"line":373},[34,877,878],{"class":44},"      state.items.",[34,880,881],{"class":94},"find",[34,883,98],{"class":44},[34,885,818],{"class":136},[34,887,888],{"class":40}," =>",[34,890,891],{"class":44}," i.id ",[34,893,894],{"class":40},"===",[34,896,897],{"class":44}," id)?.price ",[34,899,294],{"class":40},[34,901,902],{"class":87}," 0",[34,904,407],{"class":44},[34,906,907],{"class":36,"line":398},[34,908,63],{"emptyLinePlaceholder":62},[34,910,911],{"class":36,"line":410},[34,912,913],{"class":55},"    \u002F\u002F ── Getter using another getter: access via `this` ──\n",[34,915,916,919,921,923,925,927],{"class":36,"line":428},[34,917,918],{"class":94},"    total",[34,920,792],{"class":44},[34,922,795],{"class":136},[34,924,798],{"class":44},[34,926,107],{"class":40},[34,928,110],{"class":44},[34,930,931,934,936,938,940,942,944,946,948,950,952,954,957,960,962,964],{"class":36,"line":434},[34,932,933],{"class":40},"      return",[34,935,803],{"class":44},[34,937,806],{"class":94},[34,939,809],{"class":44},[34,941,812],{"class":136},[34,943,815],{"class":44},[34,945,818],{"class":136},[34,947,798],{"class":44},[34,949,107],{"class":40},[34,951,825],{"class":44},[34,953,828],{"class":40},[34,955,956],{"class":44}," i.price ",[34,958,959],{"class":40},"*",[34,961,831],{"class":44},[34,963,834],{"class":87},[34,965,181],{"class":44},[34,967,968],{"class":36,"line":455},[34,969,970],{"class":44},"    },\n",[34,972,973],{"class":36,"line":466},[34,974,975],{"class":55},"    \u002F\u002F For getters referencing other getters, use `this`:\n",[34,977,978],{"class":36,"line":477},[34,979,980],{"class":55},"    \u002F\u002F totalWithTax() { return this.total * 1.08 }\n",[34,982,983],{"class":36,"line":497},[34,984,985],{"class":44},"  },\n",[34,987,988],{"class":36,"line":508},[34,989,63],{"emptyLinePlaceholder":62},[34,991,992],{"class":36,"line":519},[34,993,994],{"class":55},"  \u002F\u002F ── Actions: methods, mutate state via `this` ──\n",[34,996,997],{"class":36,"line":525},[34,998,999],{"class":44},"  actions: {\n",[34,1001,1002,1005,1007,1010,1012,1014,1016,1018,1020,1022,1024,1026,1028,1030,1032,1034,1036],{"class":36,"line":531},[34,1003,1004],{"class":94},"    addItem",[34,1006,98],{"class":44},[34,1008,1009],{"class":136},"item",[34,1011,140],{"class":40},[34,1013,332],{"class":44},[34,1015,137],{"class":136},[34,1017,140],{"class":40},[34,1019,143],{"class":87},[34,1021,146],{"class":44},[34,1023,149],{"class":136},[34,1025,140],{"class":40},[34,1027,154],{"class":87},[34,1029,146],{"class":44},[34,1031,731],{"class":136},[34,1033,140],{"class":40},[34,1035,143],{"class":87},[34,1037,350],{"class":44},[34,1039,1040,1042,1045,1047,1050,1053,1055,1057,1059,1061,1063,1065],{"class":36,"line":536},[34,1041,376],{"class":40},[34,1043,1044],{"class":87}," existing",[34,1046,91],{"class":40},[34,1048,1049],{"class":87}," this",[34,1051,1052],{"class":44},".items.",[34,1054,881],{"class":94},[34,1056,98],{"class":44},[34,1058,818],{"class":136},[34,1060,888],{"class":40},[34,1062,891],{"class":44},[34,1064,894],{"class":40},[34,1066,1067],{"class":44}," item.id)\n",[34,1069,1070,1073],{"class":36,"line":548},[34,1071,1072],{"class":40},"      if",[34,1074,1075],{"class":44}," (existing) {\n",[34,1077,1078,1081,1084],{"class":36,"line":559},[34,1079,1080],{"class":44},"        existing.qty",[34,1082,1083],{"class":40},"++",[34,1085,1086],{"class":55},"  \u002F\u002F direct mutation — Pinia allows it\n",[34,1088,1089,1092,1095],{"class":36,"line":569},[34,1090,1091],{"class":44},"      } ",[34,1093,1094],{"class":40},"else",[34,1096,110],{"class":44},[34,1098,1099,1102,1104,1107,1110,1113,1116,1119],{"class":36,"line":584},[34,1100,1101],{"class":87},"        this",[34,1103,1052],{"class":44},[34,1105,1106],{"class":94},"push",[34,1108,1109],{"class":44},"({ ",[34,1111,1112],{"class":40},"...",[34,1114,1115],{"class":44},"item, qty: ",[34,1117,1118],{"class":87},"1",[34,1120,1121],{"class":44}," })\n",[34,1123,1124],{"class":36,"line":589},[34,1125,1126],{"class":44},"      }\n",[34,1128,1129],{"class":36,"line":594},[34,1130,970],{"class":44},[34,1132,1133],{"class":36,"line":600},[34,1134,63],{"emptyLinePlaceholder":62},[34,1136,1137,1140,1142,1144,1146,1148],{"class":36,"line":606},[34,1138,1139],{"class":94},"    removeItem",[34,1141,98],{"class":44},[34,1143,137],{"class":136},[34,1145,140],{"class":40},[34,1147,143],{"class":87},[34,1149,1150],{"class":44},") {\n",[34,1152,1153,1156,1159,1161,1163,1165,1168,1170,1172,1174,1176,1179],{"class":36,"line":615},[34,1154,1155],{"class":87},"      this",[34,1157,1158],{"class":44},".items ",[34,1160,359],{"class":40},[34,1162,1049],{"class":87},[34,1164,1052],{"class":44},[34,1166,1167],{"class":94},"filter",[34,1169,98],{"class":44},[34,1171,818],{"class":136},[34,1173,888],{"class":40},[34,1175,891],{"class":44},[34,1177,1178],{"class":40},"!==",[34,1180,1181],{"class":44}," id)\n",[34,1183,1185],{"class":36,"line":1184},42,[34,1186,970],{"class":44},[34,1188,1190],{"class":36,"line":1189},43,[34,1191,63],{"emptyLinePlaceholder":62},[34,1193,1195],{"class":36,"line":1194},44,[34,1196,1197],{"class":55},"    \u002F\u002F ── Actions can be async ──\n",[34,1199,1201,1204,1207],{"class":36,"line":1200},45,[34,1202,1203],{"class":40},"    async",[34,1205,1206],{"class":94}," checkout",[34,1208,545],{"class":44},[34,1210,1212,1214,1216,1218,1220,1222,1224,1227],{"class":36,"line":1211},46,[34,1213,376],{"class":40},[34,1215,379],{"class":87},[34,1217,91],{"class":40},[34,1219,384],{"class":40},[34,1221,387],{"class":94},[34,1223,98],{"class":44},[34,1225,1226],{"class":51},"'\u002Fapi\u002Fcheckout'",[34,1228,395],{"class":44},[34,1230,1232,1234,1236],{"class":36,"line":1231},47,[34,1233,401],{"class":44},[34,1235,404],{"class":51},[34,1237,407],{"class":44},[34,1239,1241,1243,1245,1247,1249,1252,1255,1258,1260],{"class":36,"line":1240},48,[34,1242,413],{"class":44},[34,1244,416],{"class":87},[34,1246,419],{"class":44},[34,1248,422],{"class":94},[34,1250,1251],{"class":44},"({ items: ",[34,1253,1254],{"class":87},"this",[34,1256,1257],{"class":44},".items, coupon: ",[34,1259,1254],{"class":87},[34,1261,1262],{"class":44},".couponCode }),\n",[34,1264,1266],{"class":36,"line":1265},49,[34,1267,431],{"class":44},[34,1269,1271,1273,1276,1278,1280,1283,1286],{"class":36,"line":1270},50,[34,1272,1072],{"class":40},[34,1274,1275],{"class":44}," (res.ok) ",[34,1277,1254],{"class":87},[34,1279,419],{"class":44},[34,1281,1282],{"class":94},"$reset",[34,1284,1285],{"class":44},"()  ",[34,1287,1288],{"class":55},"\u002F\u002F reset to initial state\n",[34,1290,1292],{"class":36,"line":1291},51,[34,1293,970],{"class":44},[34,1295,1297],{"class":36,"line":1296},52,[34,1298,985],{"class":44},[34,1300,1302],{"class":36,"line":1301},53,[34,1303,618],{"class":44},[15,1305,1307],{"id":1306},"patch-batch-mutations-for-performance","$patch — Batch Mutations for Performance",[20,1309,1311],{"filename":1310,"language":23},"patch-mutations.ts",[25,1312,1314],{"className":27,"code":1313,"language":23,"meta":29,"style":29},"import { useUserStore } from '.\u002Fstores\u002Fuser'\n\nconst store = useUserStore()\n\n\u002F\u002F ── $patch with object: batch multiple state changes into one mutation ──\n\u002F\u002F Triggers ONE re-render for all changes, not one per property.\nstore.$patch({\n  user: { id: 1, name: 'Ada', email: 'ada@example.com' },\n  token: 'xyz',\n  loading: false,\n})\n\n\u002F\u002F ── $patch with function: for complex mutations (arrays, nested objects) ──\n\u002F\u002F The function receives `state` and can mutate it freely.\n\u002F\u002F Pinia batches all mutations inside the function into one update.\nstore.$patch((state) => {\n  state.user.name = 'Grace'\n  state.user.email = 'grace@example.com'\n  \u002F\u002F Multiple mutations, single re-render batch.\n})\n\n\u002F\u002F ── Direct mutation: also valid, triggers per-property ──\nstore.user.name = 'Ada'       \u002F\u002F one update\nstore.token = 'abc'            \u002F\u002F another update → two re-renders\n\u002F\u002F Use $patch to batch when updating multiple properties simultaneously.\n",[31,1315,1316,1328,1332,1346,1350,1355,1360,1371,1393,1403,1412,1416,1420,1425,1430,1435,1451,1461,1471,1476,1480,1484,1489,1502,1515],{"__ignoreMap":29},[34,1317,1318,1320,1323,1325],{"class":36,"line":37},[34,1319,41],{"class":40},[34,1321,1322],{"class":44}," { useUserStore } ",[34,1324,48],{"class":40},[34,1326,1327],{"class":51}," '.\u002Fstores\u002Fuser'\n",[34,1329,1330],{"class":36,"line":59},[34,1331,63],{"emptyLinePlaceholder":62},[34,1333,1334,1337,1340,1342,1344],{"class":36,"line":66},[34,1335,1336],{"class":40},"const",[34,1338,1339],{"class":87}," store",[34,1341,91],{"class":40},[34,1343,88],{"class":94},[34,1345,452],{"class":44},[34,1347,1348],{"class":36,"line":72},[34,1349,63],{"emptyLinePlaceholder":62},[34,1351,1352],{"class":36,"line":78},[34,1353,1354],{"class":55},"\u002F\u002F ── $patch with object: batch multiple state changes into one mutation ──\n",[34,1356,1357],{"class":36,"line":113},[34,1358,1359],{"class":55},"\u002F\u002F Triggers ONE re-render for all changes, not one per property.\n",[34,1361,1362,1365,1368],{"class":36,"line":119},[34,1363,1364],{"class":44},"store.",[34,1366,1367],{"class":94},"$patch",[34,1369,1370],{"class":44},"({\n",[34,1372,1373,1376,1378,1381,1384,1387,1390],{"class":36,"line":184},[34,1374,1375],{"class":44},"  user: { id: ",[34,1377,1118],{"class":87},[34,1379,1380],{"class":44},", name: ",[34,1382,1383],{"class":51},"'Ada'",[34,1385,1386],{"class":44},", email: ",[34,1388,1389],{"class":51},"'ada@example.com'",[34,1391,1392],{"class":44}," },\n",[34,1394,1395,1398,1401],{"class":36,"line":213},[34,1396,1397],{"class":44},"  token: ",[34,1399,1400],{"class":51},"'xyz'",[34,1402,407],{"class":44},[34,1404,1405,1408,1410],{"class":36,"line":232},[34,1406,1407],{"class":44},"  loading: ",[34,1409,227],{"class":87},[34,1411,407],{"class":44},[34,1413,1414],{"class":36,"line":237},[34,1415,618],{"class":44},[34,1417,1418],{"class":36,"line":243},[34,1419,63],{"emptyLinePlaceholder":62},[34,1421,1422],{"class":36,"line":275},[34,1423,1424],{"class":55},"\u002F\u002F ── $patch with function: for complex mutations (arrays, nested objects) ──\n",[34,1426,1427],{"class":36,"line":302},[34,1428,1429],{"class":55},"\u002F\u002F The function receives `state` and can mutate it freely.\n",[34,1431,1432],{"class":36,"line":307},[34,1433,1434],{"class":55},"\u002F\u002F Pinia batches all mutations inside the function into one update.\n",[34,1436,1437,1439,1441,1443,1445,1447,1449],{"class":36,"line":313},[34,1438,1364],{"class":44},[34,1440,1367],{"class":94},[34,1442,809],{"class":44},[34,1444,795],{"class":136},[34,1446,798],{"class":44},[34,1448,107],{"class":40},[34,1450,110],{"class":44},[34,1452,1453,1456,1458],{"class":36,"line":353},[34,1454,1455],{"class":44},"  state.user.name ",[34,1457,359],{"class":40},[34,1459,1460],{"class":51}," 'Grace'\n",[34,1462,1463,1466,1468],{"class":36,"line":365},[34,1464,1465],{"class":44},"  state.user.email ",[34,1467,359],{"class":40},[34,1469,1470],{"class":51}," 'grace@example.com'\n",[34,1472,1473],{"class":36,"line":373},[34,1474,1475],{"class":55},"  \u002F\u002F Multiple mutations, single re-render batch.\n",[34,1477,1478],{"class":36,"line":398},[34,1479,618],{"class":44},[34,1481,1482],{"class":36,"line":410},[34,1483,63],{"emptyLinePlaceholder":62},[34,1485,1486],{"class":36,"line":428},[34,1487,1488],{"class":55},"\u002F\u002F ── Direct mutation: also valid, triggers per-property ──\n",[34,1490,1491,1494,1496,1499],{"class":36,"line":434},[34,1492,1493],{"class":44},"store.user.name ",[34,1495,359],{"class":40},[34,1497,1498],{"class":51}," 'Ada'",[34,1500,1501],{"class":55},"       \u002F\u002F one update\n",[34,1503,1504,1507,1509,1512],{"class":36,"line":455},[34,1505,1506],{"class":44},"store.token ",[34,1508,359],{"class":40},[34,1510,1511],{"class":51}," 'abc'",[34,1513,1514],{"class":55},"            \u002F\u002F another update → two re-renders\n",[34,1516,1517],{"class":36,"line":466},[34,1518,1519],{"class":55},"\u002F\u002F Use $patch to batch when updating multiple properties simultaneously.\n",[15,1521,1523],{"id":1522},"cross-store-dependencies-composing-stores","Cross-Store Dependencies — Composing Stores",[20,1525,1527],{"filename":1526,"language":23},"stores\u002Fcheckout.ts",[25,1528,1530],{"className":27,"code":1529,"language":23,"meta":29,"style":29},"import { defineStore } from 'pinia'\nimport { useCartStore } from '.\u002Fcart'\nimport { useUserStore } from '.\u002Fuser'\n\n\u002F\u002F ── One store can use another — call useXxxStore() inside actions ──\n\u002F\u002F Don't call at store definition time (circular dependency risk).\n\u002F\u002F Call inside actions or setup function body.\nexport const useCheckoutStore = defineStore('checkout', () => {\n  const cart = useCartStore()\n  const user = useUserStore()\n\n  async function processPayment(paymentMethod: string) {\n    if (!user.isAuthenticated) throw new Error('Must be logged in')\n\n    const res = await fetch('\u002Fapi\u002Fcheckout', {\n      method: 'POST',\n      body: JSON.stringify({\n        items: cart.items,\n        userId: user.user?.id,\n        paymentMethod,\n      }),\n    })\n\n    if (res.ok) {\n      cart.$reset()  \u002F\u002F clear cart after successful checkout\n    }\n\n    return res.json()\n  }\n\n  return { processPayment }\n})\n",[31,1531,1532,1542,1554,1565,1569,1574,1579,1584,1608,1621,1633,1637,1657,1686,1690,1709,1718,1731,1736,1741,1746,1751,1756,1760,1767,1779,1783,1787,1798,1802,1806,1813],{"__ignoreMap":29},[34,1533,1534,1536,1538,1540],{"class":36,"line":37},[34,1535,41],{"class":40},[34,1537,637],{"class":44},[34,1539,48],{"class":40},[34,1541,642],{"class":51},[34,1543,1544,1546,1549,1551],{"class":36,"line":59},[34,1545,41],{"class":40},[34,1547,1548],{"class":44}," { useCartStore } ",[34,1550,48],{"class":40},[34,1552,1553],{"class":51}," '.\u002Fcart'\n",[34,1555,1556,1558,1560,1562],{"class":36,"line":66},[34,1557,41],{"class":40},[34,1559,1322],{"class":44},[34,1561,48],{"class":40},[34,1563,1564],{"class":51}," '.\u002Fuser'\n",[34,1566,1567],{"class":36,"line":72},[34,1568,63],{"emptyLinePlaceholder":62},[34,1570,1571],{"class":36,"line":78},[34,1572,1573],{"class":55},"\u002F\u002F ── One store can use another — call useXxxStore() inside actions ──\n",[34,1575,1576],{"class":36,"line":113},[34,1577,1578],{"class":55},"\u002F\u002F Don't call at store definition time (circular dependency risk).\n",[34,1580,1581],{"class":36,"line":119},[34,1582,1583],{"class":55},"\u002F\u002F Call inside actions or setup function body.\n",[34,1585,1586,1588,1590,1593,1595,1597,1599,1602,1604,1606],{"class":36,"line":184},[34,1587,81],{"class":40},[34,1589,84],{"class":40},[34,1591,1592],{"class":87}," useCheckoutStore",[34,1594,91],{"class":40},[34,1596,95],{"class":94},[34,1598,98],{"class":44},[34,1600,1601],{"class":51},"'checkout'",[34,1603,104],{"class":44},[34,1605,107],{"class":40},[34,1607,110],{"class":44},[34,1609,1610,1612,1615,1617,1619],{"class":36,"line":213},[34,1611,122],{"class":40},[34,1613,1614],{"class":87}," cart",[34,1616,91],{"class":40},[34,1618,665],{"class":94},[34,1620,452],{"class":44},[34,1622,1623,1625,1627,1629,1631],{"class":36,"line":232},[34,1624,122],{"class":40},[34,1626,125],{"class":87},[34,1628,91],{"class":40},[34,1630,88],{"class":94},[34,1632,452],{"class":44},[34,1634,1635],{"class":36,"line":237},[34,1636,63],{"emptyLinePlaceholder":62},[34,1638,1639,1641,1643,1646,1648,1651,1653,1655],{"class":36,"line":243},[34,1640,316],{"class":40},[34,1642,319],{"class":40},[34,1644,1645],{"class":94}," processPayment",[34,1647,98],{"class":44},[34,1649,1650],{"class":136},"paymentMethod",[34,1652,140],{"class":40},[34,1654,154],{"class":87},[34,1656,1150],{"class":44},[34,1658,1659,1662,1664,1667,1670,1673,1676,1679,1681,1684],{"class":36,"line":275},[34,1660,1661],{"class":40},"    if",[34,1663,862],{"class":44},[34,1665,1666],{"class":40},"!",[34,1668,1669],{"class":44},"user.isAuthenticated) ",[34,1671,1672],{"class":40},"throw",[34,1674,1675],{"class":40}," new",[34,1677,1678],{"class":94}," Error",[34,1680,98],{"class":44},[34,1682,1683],{"class":51},"'Must be logged in'",[34,1685,181],{"class":44},[34,1687,1688],{"class":36,"line":302},[34,1689,63],{"emptyLinePlaceholder":62},[34,1691,1692,1695,1697,1699,1701,1703,1705,1707],{"class":36,"line":307},[34,1693,1694],{"class":40},"    const",[34,1696,379],{"class":87},[34,1698,91],{"class":40},[34,1700,384],{"class":40},[34,1702,387],{"class":94},[34,1704,98],{"class":44},[34,1706,1226],{"class":51},[34,1708,395],{"class":44},[34,1710,1711,1714,1716],{"class":36,"line":313},[34,1712,1713],{"class":44},"      method: ",[34,1715,404],{"class":51},[34,1717,407],{"class":44},[34,1719,1720,1723,1725,1727,1729],{"class":36,"line":353},[34,1721,1722],{"class":44},"      body: ",[34,1724,416],{"class":87},[34,1726,419],{"class":44},[34,1728,422],{"class":94},[34,1730,1370],{"class":44},[34,1732,1733],{"class":36,"line":365},[34,1734,1735],{"class":44},"        items: cart.items,\n",[34,1737,1738],{"class":36,"line":373},[34,1739,1740],{"class":44},"        userId: user.user?.id,\n",[34,1742,1743],{"class":36,"line":398},[34,1744,1745],{"class":44},"        paymentMethod,\n",[34,1747,1748],{"class":36,"line":410},[34,1749,1750],{"class":44},"      }),\n",[34,1752,1753],{"class":36,"line":428},[34,1754,1755],{"class":44},"    })\n",[34,1757,1758],{"class":36,"line":434},[34,1759,63],{"emptyLinePlaceholder":62},[34,1761,1762,1764],{"class":36,"line":455},[34,1763,1661],{"class":40},[34,1765,1766],{"class":44}," (res.ok) {\n",[34,1768,1769,1772,1774,1776],{"class":36,"line":466},[34,1770,1771],{"class":44},"      cart.",[34,1773,1282],{"class":94},[34,1775,1285],{"class":44},[34,1777,1778],{"class":55},"\u002F\u002F clear cart after successful checkout\n",[34,1780,1781],{"class":36,"line":477},[34,1782,522],{"class":44},[34,1784,1785],{"class":36,"line":497},[34,1786,63],{"emptyLinePlaceholder":62},[34,1788,1789,1792,1794,1796],{"class":36,"line":508},[34,1790,1791],{"class":40},"    return",[34,1793,446],{"class":44},[34,1795,449],{"class":94},[34,1797,452],{"class":44},[34,1799,1800],{"class":36,"line":519},[34,1801,528],{"class":44},[34,1803,1804],{"class":36,"line":525},[34,1805,63],{"emptyLinePlaceholder":62},[34,1807,1808,1810],{"class":36,"line":531},[34,1809,609],{"class":40},[34,1811,1812],{"class":44}," { processPayment }\n",[34,1814,1815],{"class":36,"line":536},[34,1816,618],{"class":44},[15,1818,1820],{"id":1819},"store-persistence-plugin-pattern","Store Persistence — Plugin Pattern",[20,1822,1824,2085,2162,2166,2327,2331,2670,2674,2792,2796,2800,2888],{"filename":1823,"language":23},"plugins\u002Fpersist.ts",[25,1825,1827],{"className":27,"code":1826,"language":23,"meta":29,"style":29},"import type { PiniaPluginContext } from 'pinia'\n\n\u002F\u002F ── Pinia plugin: runs for every store, persists state to localStorage ──\nexport function persistPlugin({ store, options }: PiniaPluginContext) {\n  \u002F\u002F ── Opt-in: only persist stores with `persist: true` in options ──\n  if (!options.persist) return\n\n  const key = `pinia:${store.$id}`\n\n  \u002F\u002F ── Hydrate from storage on store creation ──\n  const saved = localStorage.getItem(key)\n  if (saved) {\n    store.$patch(JSON.parse(saved))  \u002F\u002F restore saved state\n  }\n\n  \u002F\u002F ── Subscribe to state changes — save on every mutation ──\n  store.$subscribe((mutation, state) => {\n    \u002F\u002F Debounce localStorage writes in production (mutations can be frequent)\n    localStorage.setItem(key, JSON.stringify(state))\n  }, { detached: true })  \u002F\u002F detached: keep subscription even after store disposed\n\n  \u002F\u002F ── Alternative: use $onAction to persist only after specific actions ──\n  \u002F\u002F store.$onAction(({ name, after }) => {\n  \u002F\u002F   if (name === 'addToCart') after(() => localStorage.setItem(key, JSON.stringify(store.$state)))\n  \u002F\u002F })\n}\n",[31,1828,1829,1843,1847,1852,1881,1886,1901,1905,1927,1931,1936,1954,1961,1983,1987,1991,1996,2019,2024,2042,2056,2060,2065,2070,2075,2080],{"__ignoreMap":29},[34,1830,1831,1833,1836,1839,1841],{"class":36,"line":37},[34,1832,41],{"class":40},[34,1834,1835],{"class":40}," type",[34,1837,1838],{"class":44}," { PiniaPluginContext } ",[34,1840,48],{"class":40},[34,1842,642],{"class":51},[34,1844,1845],{"class":36,"line":59},[34,1846,63],{"emptyLinePlaceholder":62},[34,1848,1849],{"class":36,"line":66},[34,1850,1851],{"class":55},"\u002F\u002F ── Pinia plugin: runs for every store, persists state to localStorage ──\n",[34,1853,1854,1856,1858,1861,1863,1866,1868,1871,1874,1876,1879],{"class":36,"line":72},[34,1855,81],{"class":40},[34,1857,319],{"class":40},[34,1859,1860],{"class":94}," persistPlugin",[34,1862,1109],{"class":44},[34,1864,1865],{"class":136},"store",[34,1867,815],{"class":44},[34,1869,1870],{"class":136},"options",[34,1872,1873],{"class":44}," }",[34,1875,140],{"class":40},[34,1877,1878],{"class":94}," PiniaPluginContext",[34,1880,1150],{"class":44},[34,1882,1883],{"class":36,"line":78},[34,1884,1885],{"class":55},"  \u002F\u002F ── Opt-in: only persist stores with `persist: true` in options ──\n",[34,1887,1888,1891,1893,1895,1898],{"class":36,"line":113},[34,1889,1890],{"class":40},"  if",[34,1892,862],{"class":44},[34,1894,1666],{"class":40},[34,1896,1897],{"class":44},"options.persist) ",[34,1899,1900],{"class":40},"return\n",[34,1902,1903],{"class":36,"line":119},[34,1904,63],{"emptyLinePlaceholder":62},[34,1906,1907,1909,1912,1914,1917,1919,1921,1924],{"class":36,"line":184},[34,1908,122],{"class":40},[34,1910,1911],{"class":87}," key",[34,1913,91],{"class":40},[34,1915,1916],{"class":51}," `pinia:${",[34,1918,1865],{"class":44},[34,1920,419],{"class":51},[34,1922,1923],{"class":44},"$id",[34,1925,1926],{"class":51},"}`\n",[34,1928,1929],{"class":36,"line":213},[34,1930,63],{"emptyLinePlaceholder":62},[34,1932,1933],{"class":36,"line":232},[34,1934,1935],{"class":55},"  \u002F\u002F ── Hydrate from storage on store creation ──\n",[34,1937,1938,1940,1943,1945,1948,1951],{"class":36,"line":237},[34,1939,122],{"class":40},[34,1941,1942],{"class":87}," saved",[34,1944,91],{"class":40},[34,1946,1947],{"class":44}," localStorage.",[34,1949,1950],{"class":94},"getItem",[34,1952,1953],{"class":44},"(key)\n",[34,1955,1956,1958],{"class":36,"line":243},[34,1957,1890],{"class":40},[34,1959,1960],{"class":44}," (saved) {\n",[34,1962,1963,1966,1968,1970,1972,1974,1977,1980],{"class":36,"line":275},[34,1964,1965],{"class":44},"    store.",[34,1967,1367],{"class":94},[34,1969,98],{"class":44},[34,1971,416],{"class":87},[34,1973,419],{"class":44},[34,1975,1976],{"class":94},"parse",[34,1978,1979],{"class":44},"(saved))  ",[34,1981,1982],{"class":55},"\u002F\u002F restore saved state\n",[34,1984,1985],{"class":36,"line":302},[34,1986,528],{"class":44},[34,1988,1989],{"class":36,"line":307},[34,1990,63],{"emptyLinePlaceholder":62},[34,1992,1993],{"class":36,"line":313},[34,1994,1995],{"class":55},"  \u002F\u002F ── Subscribe to state changes — save on every mutation ──\n",[34,1997,1998,2001,2004,2006,2009,2011,2013,2015,2017],{"class":36,"line":353},[34,1999,2000],{"class":44},"  store.",[34,2002,2003],{"class":94},"$subscribe",[34,2005,809],{"class":44},[34,2007,2008],{"class":136},"mutation",[34,2010,815],{"class":44},[34,2012,795],{"class":136},[34,2014,798],{"class":44},[34,2016,107],{"class":40},[34,2018,110],{"class":44},[34,2020,2021],{"class":36,"line":365},[34,2022,2023],{"class":55},"    \u002F\u002F Debounce localStorage writes in production (mutations can be frequent)\n",[34,2025,2026,2028,2030,2033,2035,2037,2039],{"class":36,"line":373},[34,2027,572],{"class":44},[34,2029,483],{"class":94},[34,2031,2032],{"class":44},"(key, ",[34,2034,416],{"class":87},[34,2036,419],{"class":44},[34,2038,422],{"class":94},[34,2040,2041],{"class":44},"(state))\n",[34,2043,2044,2047,2050,2053],{"class":36,"line":398},[34,2045,2046],{"class":44},"  }, { detached: ",[34,2048,2049],{"class":87},"true",[34,2051,2052],{"class":44}," })  ",[34,2054,2055],{"class":55},"\u002F\u002F detached: keep subscription even after store disposed\n",[34,2057,2058],{"class":36,"line":410},[34,2059,63],{"emptyLinePlaceholder":62},[34,2061,2062],{"class":36,"line":428},[34,2063,2064],{"class":55},"  \u002F\u002F ── Alternative: use $onAction to persist only after specific actions ──\n",[34,2066,2067],{"class":36,"line":434},[34,2068,2069],{"class":55},"  \u002F\u002F store.$onAction(({ name, after }) => {\n",[34,2071,2072],{"class":36,"line":455},[34,2073,2074],{"class":55},"  \u002F\u002F   if (name === 'addToCart') after(() => localStorage.setItem(key, JSON.stringify(store.$state)))\n",[34,2076,2077],{"class":36,"line":466},[34,2078,2079],{"class":55},"  \u002F\u002F })\n",[34,2081,2082],{"class":36,"line":477},[34,2083,2084],{"class":44},"}\n",[20,2086,2088],{"filename":2087,"language":23},"main.ts",[25,2089,2091],{"className":27,"code":2090,"language":23,"meta":29,"style":29},"import { createPinia } from 'pinia'\nimport { persistPlugin } from '.\u002Fplugins\u002Fpersist'\n\nconst pinia = createPinia()\npinia.use(persistPlugin)  \u002F\u002F register plugin — applies to all stores\n\napp.use(pinia)\n",[31,2092,2093,2104,2116,2120,2134,2148,2152],{"__ignoreMap":29},[34,2094,2095,2097,2100,2102],{"class":36,"line":37},[34,2096,41],{"class":40},[34,2098,2099],{"class":44}," { createPinia } ",[34,2101,48],{"class":40},[34,2103,642],{"class":51},[34,2105,2106,2108,2111,2113],{"class":36,"line":59},[34,2107,41],{"class":40},[34,2109,2110],{"class":44}," { persistPlugin } ",[34,2112,48],{"class":40},[34,2114,2115],{"class":51}," '.\u002Fplugins\u002Fpersist'\n",[34,2117,2118],{"class":36,"line":66},[34,2119,63],{"emptyLinePlaceholder":62},[34,2121,2122,2124,2127,2129,2132],{"class":36,"line":72},[34,2123,1336],{"class":40},[34,2125,2126],{"class":87}," pinia",[34,2128,91],{"class":40},[34,2130,2131],{"class":94}," createPinia",[34,2133,452],{"class":44},[34,2135,2136,2139,2142,2145],{"class":36,"line":78},[34,2137,2138],{"class":44},"pinia.",[34,2140,2141],{"class":94},"use",[34,2143,2144],{"class":44},"(persistPlugin)  ",[34,2146,2147],{"class":55},"\u002F\u002F register plugin — applies to all stores\n",[34,2149,2150],{"class":36,"line":113},[34,2151,63],{"emptyLinePlaceholder":62},[34,2153,2154,2157,2159],{"class":36,"line":119},[34,2155,2156],{"class":44},"app.",[34,2158,2141],{"class":94},[34,2160,2161],{"class":44},"(pinia)\n",[15,2163,2165],{"id":2164},"ssr-hydration-request-scoped-state","SSR Hydration — Request-Scoped State",[20,2167,2169],{"filename":2168,"language":23},"ssr-hydration.ts",[25,2170,2172],{"className":27,"code":2171,"language":23,"meta":29,"style":29},"import { createPinia } from 'pinia'\n\n\u002F\u002F ── SSR: create a FRESH Pinia instance per request ──────\n\u002F\u002F Module-scoped Pinia leaks state across requests (security bug).\n\u002F\u002F Each request gets its own Pinia → stores are request-scoped.\nexport function createApp() {\n  const pinia = createPinia()  \u002F\u002F fresh per request\n\n  \u002F\u002F ── On server: serialize state into HTML for client hydration ──\n  \u002F\u002F After all onServerPrefetch hooks resolve:\n  const state = pinia.state.value  \u002F\u002F all store states\n  \u002F\u002F Inject into HTML: \u003Cscript>window.__PINIA__ = ${JSON.stringify(state)}\u003C\u002Fscript>\n\n  \u002F\u002F ── On client: hydrate from serialized state ──\n  if (typeof window !== 'undefined' && window.__PINIA__) {\n    pinia.state.value = window.__PINIA__  \u002F\u002F replace initial state with server state\n  }\n\n  return { pinia }\n}\n",[31,2173,2174,2184,2188,2193,2198,2203,2214,2229,2233,2238,2243,2258,2263,2267,2272,2295,2308,2312,2316,2323],{"__ignoreMap":29},[34,2175,2176,2178,2180,2182],{"class":36,"line":37},[34,2177,41],{"class":40},[34,2179,2099],{"class":44},[34,2181,48],{"class":40},[34,2183,642],{"class":51},[34,2185,2186],{"class":36,"line":59},[34,2187,63],{"emptyLinePlaceholder":62},[34,2189,2190],{"class":36,"line":66},[34,2191,2192],{"class":55},"\u002F\u002F ── SSR: create a FRESH Pinia instance per request ──────\n",[34,2194,2195],{"class":36,"line":72},[34,2196,2197],{"class":55},"\u002F\u002F Module-scoped Pinia leaks state across requests (security bug).\n",[34,2199,2200],{"class":36,"line":78},[34,2201,2202],{"class":55},"\u002F\u002F Each request gets its own Pinia → stores are request-scoped.\n",[34,2204,2205,2207,2209,2212],{"class":36,"line":113},[34,2206,81],{"class":40},[34,2208,319],{"class":40},[34,2210,2211],{"class":94}," createApp",[34,2213,545],{"class":44},[34,2215,2216,2218,2220,2222,2224,2226],{"class":36,"line":119},[34,2217,122],{"class":40},[34,2219,2126],{"class":87},[34,2221,91],{"class":40},[34,2223,2131],{"class":94},[34,2225,1285],{"class":44},[34,2227,2228],{"class":55},"\u002F\u002F fresh per request\n",[34,2230,2231],{"class":36,"line":184},[34,2232,63],{"emptyLinePlaceholder":62},[34,2234,2235],{"class":36,"line":213},[34,2236,2237],{"class":55},"  \u002F\u002F ── On server: serialize state into HTML for client hydration ──\n",[34,2239,2240],{"class":36,"line":232},[34,2241,2242],{"class":55},"  \u002F\u002F After all onServerPrefetch hooks resolve:\n",[34,2244,2245,2247,2250,2252,2255],{"class":36,"line":237},[34,2246,122],{"class":40},[34,2248,2249],{"class":87}," state",[34,2251,91],{"class":40},[34,2253,2254],{"class":44}," pinia.state.value  ",[34,2256,2257],{"class":55},"\u002F\u002F all store states\n",[34,2259,2260],{"class":36,"line":243},[34,2261,2262],{"class":55},"  \u002F\u002F Inject into HTML: \u003Cscript>window.__PINIA__ = ${JSON.stringify(state)}\u003C\u002Fscript>\n",[34,2264,2265],{"class":36,"line":275},[34,2266,63],{"emptyLinePlaceholder":62},[34,2268,2269],{"class":36,"line":302},[34,2270,2271],{"class":55},"  \u002F\u002F ── On client: hydrate from serialized state ──\n",[34,2273,2274,2276,2278,2281,2284,2286,2289,2292],{"class":36,"line":307},[34,2275,1890],{"class":40},[34,2277,862],{"class":44},[34,2279,2280],{"class":40},"typeof",[34,2282,2283],{"class":44}," window ",[34,2285,1178],{"class":40},[34,2287,2288],{"class":51}," 'undefined'",[34,2290,2291],{"class":40}," &&",[34,2293,2294],{"class":44}," window.__PINIA__) {\n",[34,2296,2297,2300,2302,2305],{"class":36,"line":313},[34,2298,2299],{"class":44},"    pinia.state.value ",[34,2301,359],{"class":40},[34,2303,2304],{"class":44}," window.__PINIA__  ",[34,2306,2307],{"class":55},"\u002F\u002F replace initial state with server state\n",[34,2309,2310],{"class":36,"line":353},[34,2311,528],{"class":44},[34,2313,2314],{"class":36,"line":365},[34,2315,63],{"emptyLinePlaceholder":62},[34,2317,2318,2320],{"class":36,"line":373},[34,2319,609],{"class":40},[34,2321,2322],{"class":44}," { pinia }\n",[34,2324,2325],{"class":36,"line":398},[34,2326,2084],{"class":44},[15,2328,2330],{"id":2329},"tips-tricks","💡 Tips & Tricks",[20,2332,2334],{"filename":2333,"language":23},"tips.ts",[25,2335,2337],{"className":27,"code":2336,"language":23,"meta":29,"style":29},"import { storeToRefs } from 'pinia'\nimport { useUserStore } from '.\u002Fstores\u002Fuser'\n\n\u002F\u002F ── 1. storeToRefs — destructure store without losing reactivity ──\n\u002F\u002F Direct destructuring breaks reactivity (same as reactive() destructuring).\nconst store = useUserStore()\nconst { user, isAuthenticated } = storeToRefs(store)  \u002F\u002F ✅ refs, reactive\nconst { login, logout } = store                      \u002F\u002F ✅ actions are stable, no ref needed\n\n\u002F\u002F ── 2. $reset — restore to initial state (Options API stores only) ──\n\u002F\u002F Setup stores don't have $reset by default — implement manually:\nfunction reset() {\n  user.value = null\n  token.value = null\n  loading.value = false\n}\n\n\u002F\u002F ── 3. $subscribe — watch all state changes ──\nstore.$subscribe((mutation, state) => {\n  \u002F\u002F mutation.type: 'direct' | 'patch object' | 'patch function'\n  console.log(mutation.type, state)\n})\n\n\u002F\u002F ── 4. $onAction — hook into actions (before\u002Fafter\u002Ferror) ──\nstore.$onAction(({ name, args, after, onError }) => {\n  console.log(`action ${name} started`, args)\n  after((result) => console.log(`${name} succeeded`, result))\n  onError((err) => console.error(`${name} failed`, err))\n})\n",[31,2338,2339,2350,2360,2364,2369,2374,2386,2413,2437,2441,2446,2451,2461,2470,2479,2488,2492,2496,2501,2521,2526,2537,2541,2545,2550,2584,2603,2635,2666],{"__ignoreMap":29},[34,2340,2341,2343,2346,2348],{"class":36,"line":37},[34,2342,41],{"class":40},[34,2344,2345],{"class":44}," { storeToRefs } ",[34,2347,48],{"class":40},[34,2349,642],{"class":51},[34,2351,2352,2354,2356,2358],{"class":36,"line":59},[34,2353,41],{"class":40},[34,2355,1322],{"class":44},[34,2357,48],{"class":40},[34,2359,1327],{"class":51},[34,2361,2362],{"class":36,"line":66},[34,2363,63],{"emptyLinePlaceholder":62},[34,2365,2366],{"class":36,"line":72},[34,2367,2368],{"class":55},"\u002F\u002F ── 1. storeToRefs — destructure store without losing reactivity ──\n",[34,2370,2371],{"class":36,"line":78},[34,2372,2373],{"class":55},"\u002F\u002F Direct destructuring breaks reactivity (same as reactive() destructuring).\n",[34,2375,2376,2378,2380,2382,2384],{"class":36,"line":113},[34,2377,1336],{"class":40},[34,2379,1339],{"class":87},[34,2381,91],{"class":40},[34,2383,88],{"class":94},[34,2385,452],{"class":44},[34,2387,2388,2390,2392,2395,2397,2400,2402,2404,2407,2410],{"class":36,"line":119},[34,2389,1336],{"class":40},[34,2391,332],{"class":44},[34,2393,2394],{"class":87},"user",[34,2396,815],{"class":44},[34,2398,2399],{"class":87},"isAuthenticated",[34,2401,166],{"class":44},[34,2403,359],{"class":40},[34,2405,2406],{"class":94}," storeToRefs",[34,2408,2409],{"class":44},"(store)  ",[34,2411,2412],{"class":55},"\u002F\u002F ✅ refs, reactive\n",[34,2414,2415,2417,2419,2422,2424,2427,2429,2431,2434],{"class":36,"line":184},[34,2416,1336],{"class":40},[34,2418,332],{"class":44},[34,2420,2421],{"class":87},"login",[34,2423,815],{"class":44},[34,2425,2426],{"class":87},"logout",[34,2428,166],{"class":44},[34,2430,359],{"class":40},[34,2432,2433],{"class":44}," store                      ",[34,2435,2436],{"class":55},"\u002F\u002F ✅ actions are stable, no ref needed\n",[34,2438,2439],{"class":36,"line":213},[34,2440,63],{"emptyLinePlaceholder":62},[34,2442,2443],{"class":36,"line":232},[34,2444,2445],{"class":55},"\u002F\u002F ── 2. $reset — restore to initial state (Options API stores only) ──\n",[34,2447,2448],{"class":36,"line":237},[34,2449,2450],{"class":55},"\u002F\u002F Setup stores don't have $reset by default — implement manually:\n",[34,2452,2453,2456,2459],{"class":36,"line":243},[34,2454,2455],{"class":40},"function",[34,2457,2458],{"class":94}," reset",[34,2460,545],{"class":44},[34,2462,2463,2466,2468],{"class":36,"line":275},[34,2464,2465],{"class":44},"  user.value ",[34,2467,359],{"class":40},[34,2469,556],{"class":87},[34,2471,2472,2475,2477],{"class":36,"line":302},[34,2473,2474],{"class":44},"  token.value ",[34,2476,359],{"class":40},[34,2478,556],{"class":87},[34,2480,2481,2484,2486],{"class":36,"line":307},[34,2482,2483],{"class":44},"  loading.value ",[34,2485,359],{"class":40},[34,2487,516],{"class":87},[34,2489,2490],{"class":36,"line":313},[34,2491,2084],{"class":44},[34,2493,2494],{"class":36,"line":353},[34,2495,63],{"emptyLinePlaceholder":62},[34,2497,2498],{"class":36,"line":365},[34,2499,2500],{"class":55},"\u002F\u002F ── 3. $subscribe — watch all state changes ──\n",[34,2502,2503,2505,2507,2509,2511,2513,2515,2517,2519],{"class":36,"line":373},[34,2504,1364],{"class":44},[34,2506,2003],{"class":94},[34,2508,809],{"class":44},[34,2510,2008],{"class":136},[34,2512,815],{"class":44},[34,2514,795],{"class":136},[34,2516,798],{"class":44},[34,2518,107],{"class":40},[34,2520,110],{"class":44},[34,2522,2523],{"class":36,"line":398},[34,2524,2525],{"class":55},"  \u002F\u002F mutation.type: 'direct' | 'patch object' | 'patch function'\n",[34,2527,2528,2531,2534],{"class":36,"line":410},[34,2529,2530],{"class":44},"  console.",[34,2532,2533],{"class":94},"log",[34,2535,2536],{"class":44},"(mutation.type, state)\n",[34,2538,2539],{"class":36,"line":428},[34,2540,618],{"class":44},[34,2542,2543],{"class":36,"line":434},[34,2544,63],{"emptyLinePlaceholder":62},[34,2546,2547],{"class":36,"line":455},[34,2548,2549],{"class":55},"\u002F\u002F ── 4. $onAction — hook into actions (before\u002Fafter\u002Ferror) ──\n",[34,2551,2552,2554,2557,2560,2562,2564,2567,2569,2572,2574,2577,2580,2582],{"class":36,"line":466},[34,2553,1364],{"class":44},[34,2555,2556],{"class":94},"$onAction",[34,2558,2559],{"class":44},"(({ ",[34,2561,149],{"class":136},[34,2563,815],{"class":44},[34,2565,2566],{"class":136},"args",[34,2568,815],{"class":44},[34,2570,2571],{"class":136},"after",[34,2573,815],{"class":44},[34,2575,2576],{"class":136},"onError",[34,2578,2579],{"class":44}," }) ",[34,2581,107],{"class":40},[34,2583,110],{"class":44},[34,2585,2586,2588,2590,2592,2595,2597,2600],{"class":36,"line":477},[34,2587,2530],{"class":44},[34,2589,2533],{"class":94},[34,2591,98],{"class":44},[34,2593,2594],{"class":51},"`action ${",[34,2596,149],{"class":44},[34,2598,2599],{"class":51},"} started`",[34,2601,2602],{"class":44},", args)\n",[34,2604,2605,2608,2610,2613,2615,2617,2620,2622,2624,2627,2629,2632],{"class":36,"line":497},[34,2606,2607],{"class":94},"  after",[34,2609,809],{"class":44},[34,2611,2612],{"class":136},"result",[34,2614,798],{"class":44},[34,2616,107],{"class":40},[34,2618,2619],{"class":44}," console.",[34,2621,2533],{"class":94},[34,2623,98],{"class":44},[34,2625,2626],{"class":51},"`${",[34,2628,149],{"class":44},[34,2630,2631],{"class":51},"} succeeded`",[34,2633,2634],{"class":44},", result))\n",[34,2636,2637,2640,2642,2645,2647,2649,2651,2654,2656,2658,2660,2663],{"class":36,"line":508},[34,2638,2639],{"class":94},"  onError",[34,2641,809],{"class":44},[34,2643,2644],{"class":136},"err",[34,2646,798],{"class":44},[34,2648,107],{"class":40},[34,2650,2619],{"class":44},[34,2652,2653],{"class":94},"error",[34,2655,98],{"class":44},[34,2657,2626],{"class":51},[34,2659,149],{"class":44},[34,2661,2662],{"class":51},"} failed`",[34,2664,2665],{"class":44},", err))\n",[34,2667,2668],{"class":36,"line":519},[34,2669,618],{"class":44},[15,2671,2673],{"id":2672},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[20,2675,2677],{"filename":2676,"language":23},"edge-cases.ts",[25,2678,2680],{"className":27,"code":2679,"language":23,"meta":29,"style":29},"\u002F\u002F ── 1. Destructuring a store breaks reactivity ──\n\u002F\u002F const { user } = useUserStore()  → user is a snapshot, not reactive\n\u002F\u002F Fix: const { user } = storeToRefs(store)\n\n\u002F\u002F ── 2. $reset only works on Options API stores ──\n\u002F\u002F Setup (function) stores don't have $reset — Pinia can't know initial state.\n\u002F\u002F Implement your own reset() action in setup stores.\n\n\u002F\u002F ── 3. State must be serializable for persistence ──\n\u002F\u002F localStorage stores strings — Date, Map, Set, class instances don't survive.\n\u002F\u002F Use a custom replacer\u002Freviver in JSON.stringify\u002Fparse, or avoid non-serializable state.\n\n\u002F\u002F ── 4. Cross-store calls inside setup() body risk circular deps ──\n\u002F\u002F Store A's setup calls useB(), Store B's setup calls useA() → infinite loop.\n\u002F\u002F Call useXxxStore() inside ACTIONS, not at store definition time.\n\n\u002F\u002F ── 5. SSR: module-scoped Pinia leaks state across requests ──\n\u002F\u002F createPinia() must be called per-request, not at module scope.\n\u002F\u002F Nuxt handles this automatically; custom SSR setups must do it manually.\n\n\u002F\u002F ── 6. Getters with parameters are NOT cached ──\n\u002F\u002F itemPrice(id) returns a function → recomputes every call.\n\u002F\u002F Only parameter-less getters are cached (like computed).\n",[31,2681,2682,2687,2692,2697,2701,2706,2711,2716,2720,2725,2730,2735,2739,2744,2749,2754,2758,2763,2768,2773,2777,2782,2787],{"__ignoreMap":29},[34,2683,2684],{"class":36,"line":37},[34,2685,2686],{"class":55},"\u002F\u002F ── 1. Destructuring a store breaks reactivity ──\n",[34,2688,2689],{"class":36,"line":59},[34,2690,2691],{"class":55},"\u002F\u002F const { user } = useUserStore()  → user is a snapshot, not reactive\n",[34,2693,2694],{"class":36,"line":66},[34,2695,2696],{"class":55},"\u002F\u002F Fix: const { user } = storeToRefs(store)\n",[34,2698,2699],{"class":36,"line":72},[34,2700,63],{"emptyLinePlaceholder":62},[34,2702,2703],{"class":36,"line":78},[34,2704,2705],{"class":55},"\u002F\u002F ── 2. $reset only works on Options API stores ──\n",[34,2707,2708],{"class":36,"line":113},[34,2709,2710],{"class":55},"\u002F\u002F Setup (function) stores don't have $reset — Pinia can't know initial state.\n",[34,2712,2713],{"class":36,"line":119},[34,2714,2715],{"class":55},"\u002F\u002F Implement your own reset() action in setup stores.\n",[34,2717,2718],{"class":36,"line":184},[34,2719,63],{"emptyLinePlaceholder":62},[34,2721,2722],{"class":36,"line":213},[34,2723,2724],{"class":55},"\u002F\u002F ── 3. State must be serializable for persistence ──\n",[34,2726,2727],{"class":36,"line":232},[34,2728,2729],{"class":55},"\u002F\u002F localStorage stores strings — Date, Map, Set, class instances don't survive.\n",[34,2731,2732],{"class":36,"line":237},[34,2733,2734],{"class":55},"\u002F\u002F Use a custom replacer\u002Freviver in JSON.stringify\u002Fparse, or avoid non-serializable state.\n",[34,2736,2737],{"class":36,"line":243},[34,2738,63],{"emptyLinePlaceholder":62},[34,2740,2741],{"class":36,"line":275},[34,2742,2743],{"class":55},"\u002F\u002F ── 4. Cross-store calls inside setup() body risk circular deps ──\n",[34,2745,2746],{"class":36,"line":302},[34,2747,2748],{"class":55},"\u002F\u002F Store A's setup calls useB(), Store B's setup calls useA() → infinite loop.\n",[34,2750,2751],{"class":36,"line":307},[34,2752,2753],{"class":55},"\u002F\u002F Call useXxxStore() inside ACTIONS, not at store definition time.\n",[34,2755,2756],{"class":36,"line":313},[34,2757,63],{"emptyLinePlaceholder":62},[34,2759,2760],{"class":36,"line":353},[34,2761,2762],{"class":55},"\u002F\u002F ── 5. SSR: module-scoped Pinia leaks state across requests ──\n",[34,2764,2765],{"class":36,"line":365},[34,2766,2767],{"class":55},"\u002F\u002F createPinia() must be called per-request, not at module scope.\n",[34,2769,2770],{"class":36,"line":373},[34,2771,2772],{"class":55},"\u002F\u002F Nuxt handles this automatically; custom SSR setups must do it manually.\n",[34,2774,2775],{"class":36,"line":398},[34,2776,63],{"emptyLinePlaceholder":62},[34,2778,2779],{"class":36,"line":410},[34,2780,2781],{"class":55},"\u002F\u002F ── 6. Getters with parameters are NOT cached ──\n",[34,2783,2784],{"class":36,"line":428},[34,2785,2786],{"class":55},"\u002F\u002F itemPrice(id) returns a function → recomputes every call.\n",[34,2788,2789],{"class":36,"line":434},[34,2790,2791],{"class":55},"\u002F\u002F Only parameter-less getters are cached (like computed).\n",[15,2793,2795],{"id":2794},"spot-the-bug","🧠 Spot the Bug",[2797,2798,2799],"p",{},"A component destructures a Pinia store and the UI stops updating when the store changes.",[20,2801,2803],{"filename":2802,"language":23},"StoreDestructureBug.ts",[25,2804,2806],{"className":27,"code":2805,"language":23,"meta":29,"style":29},"import { useUserStore } from '.\u002Fstores\u002Fuser'\n\nconst store = useUserStore()\nconst { user, isAuthenticated } = store  \u002F\u002F ← destructured: no longer reactive\nconst { login } = store                  \u002F\u002F ← actions are fine to destructure\n\n\u002F\u002F user is a plain object snapshot, not a ref.\n\u002F\u002F When store.user changes, this `user` variable doesn't update.\n",[31,2807,2808,2818,2822,2834,2856,2874,2878,2883],{"__ignoreMap":29},[34,2809,2810,2812,2814,2816],{"class":36,"line":37},[34,2811,41],{"class":40},[34,2813,1322],{"class":44},[34,2815,48],{"class":40},[34,2817,1327],{"class":51},[34,2819,2820],{"class":36,"line":59},[34,2821,63],{"emptyLinePlaceholder":62},[34,2823,2824,2826,2828,2830,2832],{"class":36,"line":66},[34,2825,1336],{"class":40},[34,2827,1339],{"class":87},[34,2829,91],{"class":40},[34,2831,88],{"class":94},[34,2833,452],{"class":44},[34,2835,2836,2838,2840,2842,2844,2846,2848,2850,2853],{"class":36,"line":72},[34,2837,1336],{"class":40},[34,2839,332],{"class":44},[34,2841,2394],{"class":87},[34,2843,815],{"class":44},[34,2845,2399],{"class":87},[34,2847,166],{"class":44},[34,2849,359],{"class":40},[34,2851,2852],{"class":44}," store  ",[34,2854,2855],{"class":55},"\u002F\u002F ← destructured: no longer reactive\n",[34,2857,2858,2860,2862,2864,2866,2868,2871],{"class":36,"line":78},[34,2859,1336],{"class":40},[34,2861,332],{"class":44},[34,2863,2421],{"class":87},[34,2865,166],{"class":44},[34,2867,359],{"class":40},[34,2869,2870],{"class":44}," store                  ",[34,2872,2873],{"class":55},"\u002F\u002F ← actions are fine to destructure\n",[34,2875,2876],{"class":36,"line":113},[34,2877,63],{"emptyLinePlaceholder":62},[34,2879,2880],{"class":36,"line":119},[34,2881,2882],{"class":55},"\u002F\u002F user is a plain object snapshot, not a ref.\n",[34,2884,2885],{"class":36,"line":184},[34,2886,2887],{"class":55},"\u002F\u002F When store.user changes, this `user` variable doesn't update.\n",[2889,2890,2891,2895,2902,2913,2997],"details",{},[2892,2893,2894],"summary",{},"Answer",[2797,2896,2897,2898,2901],{},"Destructuring a store copies the current values out of the reactive state. Like destructuring a ",[31,2899,2900],{},"reactive()"," object, the local variables are snapshots — they don't track future store changes.",[2797,2903,2904,2908,2909,2912],{},[2905,2906,2907],"strong",{},"Fix"," — use ",[31,2910,2911],{},"storeToRefs()"," for state\u002Fgetters, destructure actions directly:",[20,2914,2916],{"filename":2915,"language":23},"StoreDestructureFixed.ts",[25,2917,2919],{"className":27,"code":2918,"language":23,"meta":29,"style":29},"import { storeToRefs } from 'pinia'\nimport { useUserStore } from '.\u002Fstores\u002Fuser'\n\nconst store = useUserStore()\nconst { user, isAuthenticated } = storeToRefs(store)  \u002F\u002F refs — reactive\nconst { login } = store  \u002F\u002F actions are stable functions, safe to destructure\n",[31,2920,2921,2931,2941,2945,2957,2980],{"__ignoreMap":29},[34,2922,2923,2925,2927,2929],{"class":36,"line":37},[34,2924,41],{"class":40},[34,2926,2345],{"class":44},[34,2928,48],{"class":40},[34,2930,642],{"class":51},[34,2932,2933,2935,2937,2939],{"class":36,"line":59},[34,2934,41],{"class":40},[34,2936,1322],{"class":44},[34,2938,48],{"class":40},[34,2940,1327],{"class":51},[34,2942,2943],{"class":36,"line":66},[34,2944,63],{"emptyLinePlaceholder":62},[34,2946,2947,2949,2951,2953,2955],{"class":36,"line":72},[34,2948,1336],{"class":40},[34,2950,1339],{"class":87},[34,2952,91],{"class":40},[34,2954,88],{"class":94},[34,2956,452],{"class":44},[34,2958,2959,2961,2963,2965,2967,2969,2971,2973,2975,2977],{"class":36,"line":78},[34,2960,1336],{"class":40},[34,2962,332],{"class":44},[34,2964,2394],{"class":87},[34,2966,815],{"class":44},[34,2968,2399],{"class":87},[34,2970,166],{"class":44},[34,2972,359],{"class":40},[34,2974,2406],{"class":94},[34,2976,2409],{"class":44},[34,2978,2979],{"class":55},"\u002F\u002F refs — reactive\n",[34,2981,2982,2984,2986,2988,2990,2992,2994],{"class":36,"line":113},[34,2983,1336],{"class":40},[34,2985,332],{"class":44},[34,2987,2421],{"class":87},[34,2989,166],{"class":44},[34,2991,359],{"class":40},[34,2993,2852],{"class":44},[34,2995,2996],{"class":55},"\u002F\u002F actions are stable functions, safe to destructure\n",[2797,2998,2999,3002,3003,3005,3006,3009],{},[2905,3000,3001],{},"The lesson",": ",[31,3004,2911],{}," converts store state and getters to refs (like ",[31,3007,3008],{},"toRefs()"," for reactive objects). Actions are plain functions and don't need wrapping — destructure them directly.",[3011,3012,3013],"style",{},"html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}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 .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}",{"title":29,"searchDepth":59,"depth":59,"links":3015},[3016,3017,3018,3019,3020,3021,3022,3023,3024],{"id":17,"depth":59,"text":18},{"id":621,"depth":59,"text":622},{"id":1306,"depth":59,"text":1307},{"id":1522,"depth":59,"text":1523},{"id":1819,"depth":59,"text":1820},{"id":2164,"depth":59,"text":2165},{"id":2329,"depth":59,"text":2330},{"id":2672,"depth":59,"text":2673},{"id":2794,"depth":59,"text":2795},"Setup store vs options store, composition-based store patterns, cross-store dependencies, store persistence, SSR state hydration, and $reset\u002F$patch batch mutations for production apps.","md",{},"\u002Fvue\u002F10-state-management-pinia",{"title":5,"description":3025},"vue\u002F10-state-management-pinia","yB3_rYbW1yu45JYzeW4e_ZsySDLyhLdQ2lbZekjKqE0",1789924655535]