{"id":3599,"date":"2021-02-24T15:43:56","date_gmt":"2021-02-24T15:43:56","guid":{"rendered":"https:\/\/ionicframework.com\/blog\/?p=3599"},"modified":"2021-02-24T15:59:48","modified_gmt":"2021-02-24T15:59:48","slug":"managing-state-in-vue-with-vuex","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex","title":{"rendered":"Managing State in Vue with Vuex"},"content":{"rendered":"<p>Every app at some point will need to tackle one of the most contentious subjects in front end development: State Management. If you ask ten different developers how to manage state in an app, you&#8217;ll most likely get ten different answers, as everyone can have a slightly different approach if they were to build their own system. Thankfully, most frameworks provide some opinionated solutions for managing state in an app. For Vue, developers make use of the library <a href=\"https:\/\/next.vuex.vuejs.org\">Vuex<\/a>, which provides common patterns that makes managing state predictable and consistent across the entire app. Let&#8217;s look at how we can manage a simple TODO app using Vuex and as an added benefit, we&#8217;ll make it type safe using TypeScript.<\/p>\n<p><!--more--><\/p>\n<h2>The Shell<\/h2>\n<p>Before we dive into Vuex, let&#8217;s look at the shell of our app. What we have is basically a single route app that should load a list of &#8220;todos&#8221;. Users should be able to tap the &#8220;+&#8221; button in the header to open a modal and add a new item, or click the item itself to edit an existing todo. We can mark an item as completed in the modal or by swiping the item to to reveal some additional buttons. As far as complexity goes, this is your basic CRUD app. While basic, and a bit contrived, these kinds of apps perform the same type of actions we do in most situations. So this is a good chance to discover some best practices.<\/p>\n<div class=\"video-container\">\n          <video controls playsinline autoplay muted loop src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/Blog-Posts.mp4\"><\/video>\n        <\/div>\n<p>Now this setup isn&#8217;t overly complex, but it already is showing signs of overly coupled logic. With everything being declared in the component, if we need to change our architecture at all, or the format of our data, we basically have to change it in multiple places.<\/p>\n<h2>Making things predictable<\/h2>\n<p>To bring some structure to our app, let&#8217;s add Vuex.<\/p>\n<pre><code class=\"language-bash\">vue add vuex@next\n<\/code><\/pre>\n<p>This will install the deps we need and perform any changes to our file system. With this, we get a new <code>src\/store\/index.ts<\/code> file for us to work in. Now Vuex is based on a few concepts; A store, mutations, and actions.<\/p>\n<h3>Store<\/h3>\n<p>In Vuex, a Store is a global state that is available throughout our app. This is just a fancy way of saying we have an object that we can mutate and reflect these changes in our UI.<\/p>\n<p>In our app, we can create our store to hold our various &#8220;todos&#8221;<\/p>\n<pre><code class=\"language-typescript\">import { InjectionKey } from &#039;vue&#039;;\nimport { createStore, useStore as baseUseStore, Store } from &#039;vuex&#039;;\n\n\/\/ interfaces for our State and todos\nexport interface Todo {\n  id: number;\n  title: string;\n  note?: string;\n}\nexport interface State {\n  todos: Todo[];\n}\n\nexport const key: InjectionKey&lt;Store&lt;State&gt;&gt; = Symbol();\nconst state: State = {\n  todos: [\n    { title: &#039;Learn Vue&#039;, note: &#039;https:\/\/v3.vuejs.org\/guide\/introduction.html&#039;, id: 0, },\n    { title: &#039;Learn TypeScript&#039;, note: &#039;https:\/\/www.typescriptlang.org&#039;, id: 1, },\n    { title: &#039;Learn Vuex&#039;, note: &#039;https:\/\/next.vuex.vuejs.org&#039;, id: 2 },\n  ],\n};\n\nexport const store = createStore&lt;State&gt;({ state });\n\n\/\/ our own `useStore` composition function for types\nexport function useStore() {\n  return baseUseStore(key);\n}\n<\/code><\/pre>\n<p>With our todos setup and primed with some initial data, we can now think about how we modify that state, which is done through mutations.<\/p>\n<h3>Mutations<\/h3>\n<p>Mutations, as the name implies, are a way to mutate our state. This is very different compared to something like Redux which uses immutable state, but achieves the same effect. With Mutations, we essentially have a handler that gets called and is passed the current state, along with any payload.<\/p>\n<p>For our use case, we&#8217;re going to make sure we can type our Mutations and provide some auto completion in our editors. We&#8217;ll start off with an object that will have all our mutations declared for us<\/p>\n<pre><code class=\"language-typescript\">export const enum MUTATIONS {\n  ADD_TODO =  &#039;ADD_TODO&#039;,\n  DEL_TODO =  &#039;DEL_TODO&#039;\n};\n<\/code><\/pre>\n<p>Next, we&#8217;ll actually define our mutations:<\/p>\n<pre><code class=\"language-typescript\">import { createStore, useStore as baseUseStore, Store, MutationTree } from &#039;vuex&#039;;\n\n\/\/ ...\n\nconst mutations: MutationTree&lt;State&gt; = {\n  [MUTATIONS.ADD_TODO](state, newTodo: Todo){\n    state.todos.push({...newTodo});\n  },\n  [MUTATIONS.DEL_TODO](state, todo: Todo){\n    state.todos.splice(state.todos.indexOf(todo), 1);\n  }\n}\n<\/code><\/pre>\n<p>We have two mutations available; one to add a todo to our store and another to remove a todo. You may notice that we have a type on the <code>todo<\/code>, but not on state, why is that? Well thanks to the <code>MutationTree<\/code> type, the type information from <code>State<\/code> that is passed in will flow throughout our mutations. Now the only thing we need to type is the payload, which can change depending on what mutation we call.<\/p>\n<p>The last thing to note about mutations is that they only care about changing state. So to change state at all with Vuex, you must use Mutations.<\/p>\n<h2>Actions<\/h2>\n<p>Actions are like Mutations, but can perform asynchronous functions and call other mutations. This is a useful way to separate tasks in your app that depend on external resources and those that can be performed with the data at hand. Like mutations, we&#8217;ll split our actions up by a Type and then the actual implementation.<\/p>\n<pre><code class=\"language-typescript\">export const enum ACTIONS { ADD_RND_TODO = &#039;ADD_RND_TODO&#039;  };\n\nconst actions: ActionTree&lt;State, any&gt; = {\n  [ACTIONS.ADD_RND_TODO](store) {\n    fetch(&#039;https:\/\/fakerapi.it\/api\/v1\/texts?_quantity=1&#039;)\n      .then((res) =&gt; res.json())\n      .then(({ data }) =&gt; {\n        const newTodo: Todo = {\n          title: data[0].title,\n          id: Math.random(),\n          note: data[0].content,\n        };\n        store.commit(MUTATIONS.ADD_TODO, newTodo);\n      });\n  },\n};\n\n\n<\/code><\/pre>\n<p>Actions receive the context or actual store object as the first argument, followed by any payload that. With our action, we can make a request to some API, resolve that response, and kick off a mutation, all with the function. It doesn&#8217;t need to be a single mutation either, we could trigger one, two, or more mutations, or conditional trigger a mutation based on the resutl of a request (a side effect).<\/p>\n<h2>Putting it all together<\/h2>\n<p>With these pieces together, our overall store should look something like this.<\/p>\n<pre><code class=\"language-typescript\">import { InjectionKey } from &#039;vue&#039;;\nimport { createStore, useStore as baseUseStore, Store, MutationTree, ActionTree, } from &#039;vuex&#039;;\n\n\/\/ interfaces for our State and todos\nexport type Todo = { id: number; title: string; note?: string };\nexport type State = { todos: Todo[] };\n\nexport const key: InjectionKey&lt;Store&lt;State&gt;&gt; = Symbol();\nconst state: State = {\n  todos: [\n    {\n      title: &#039;Learn Vue&#039;,\n      note: &#039;https:\/\/v3.vuejs.org\/guide\/introduction.html&#039;,\n      id: 0,\n    },\n    {\n      title: &#039;Learn TypeScript&#039;,\n      note: &#039;https:\/\/www.typescriptlang.org&#039;,\n      id: 1,\n    },\n    { title: &#039;Learn Vuex&#039;, note: &#039;https:\/\/next.vuex.vuejs.org&#039;, id: 2 },\n  ],\n};\n\n\/*\n * Mutations\n * How we mutate our state.\n * Mutations must be synchronous\n *\/\nexport const enum MUTATIONS {\n  ADD_TODO =  &#039;ADD_TODO&#039;,\n  DEL_TODO =  &#039;DEL_TODO&#039;,\n  EDIT_TODO = &#039;EDIT_TODO&#039;\n};\nconst mutations: MutationTree&lt;State&gt; = {\n  [MUTATIONS.ADD_TODO](state, newTodo: Todo) {\n    state.todos.push({ ...newTodo });\n  },\n  [MUTATIONS.DEL_TODO](state, todo: Todo) {\n    state.todos.splice(state.todos.indexOf(todo), 1);\n  },\n  [MUTATIONS.EDIT_TODO](state, todo: Todo) {\n    const ogIndex = state.todos.findIndex(t =&gt; t.id === todo.id)\n    state.todos[ogIndex] = todo;\n  },\n};\n\n\/*\n * Actions\n * Perform async tasks, then mutate state\n *\/\n\nexport const enum ACTIONS { ADD_RND_TODO = &#039;ADD_RND_TODO&#039;, };\nconst actions: ActionTree&lt;State, any&gt; = {\n  [ACTIONS.ADD_RND_TODO](store) {\n    fetch(&#039;https:\/\/fakerapi.it\/api\/v1\/texts?_quantity=1&#039;)\n      .then((res) =&gt; res.json())\n      .then(({ data }) =&gt; {\n        const newTodo: Todo = {\n          title: data[0].title,\n          id: Math.random(),\n          note: data[0].content,\n        };\n        store.commit(MUTATIONS.ADD_TODO, newTodo);\n      });\n  },\n};\n\nexport const store = createStore&lt;State&gt;({ state, mutations, actions });\n\n\/\/ our own useStore function for types\nexport function useStore() {\n  return baseUseStore(key);\n}\n<\/code><\/pre>\n<h2>Parting Thoughts<\/h2>\n<p>As I stated early, State Management in an app is a bit of a personal preference. What I&#8217;ve shown here is simply one way that <strong>I<\/strong> would go about it. I&#8217;d encourage you all to find your own approaches, but keep a structure like this in your app for consistency. Cheers!<\/p>\n<ul>\n<li><a href=\"https:\/\/next.vuex.vuejs.org\">Vuex Docs<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/mhartington\/vuex-todo\">Sample Project<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Every app at some point will need to tackle one of the most contentious subjects in front end development: State Management. If you ask ten different developers how to manage state in an app, you&#8217;ll most likely get ten different answers, as everyone can have a slightly different approach if they were to build their [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":3601,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"1","publish_post_category":"29","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"498487","discourse_permalink":"https:\/\/forum.ionicframework.com\/t\/managing-state-in-vue-with-vuex\/205427","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[124],"tags":[202,147,203],"class_list":["post-3599","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-state-management","tag-vue","tag-vuex"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Managing State in Vue with Vuex - Ionic Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Managing State in Vue with Vuex\" \/>\n<meta property=\"og:description\" content=\"Every app at some point will need to tackle one of the most contentious subjects in front end development: State Management. If you ask ten different developers how to manage state in an app, you&#8217;ll most likely get ten different answers, as everyone can have a slightly different approach if they were to build their [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-24T15:43:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-02-24T15:59:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1600\" \/>\n\t<meta property=\"og:image:height\" content=\"880\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Mike Hartington\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mhartington\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mike Hartington\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex\"},\"author\":{\"name\":\"Mike Hartington\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b\"},\"headline\":\"Managing State in Vue with Vuex\",\"datePublished\":\"2021-02-24T15:43:56+00:00\",\"dateModified\":\"2021-02-24T15:59:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex\"},\"wordCount\":845,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png\",\"keywords\":[\"State Management\",\"Vue\",\"Vuex\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex\",\"url\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex\",\"name\":\"Managing State in Vue with Vuex - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png\",\"datePublished\":\"2021-02-24T15:43:56+00:00\",\"dateModified\":\"2021-02-24T15:59:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png\",\"width\":1600,\"height\":880},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Managing State in Vue with Vuex\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b\",\"name\":\"Mike Hartington\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png\",\"caption\":\"Mike Hartington\"},\"description\":\"Director of Developer Relations\",\"sameAs\":[\"https:\/\/twitter.com\/mhartington\",\"https:\/\/x.com\/mhartington\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/mike\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Managing State in Vue with Vuex - Ionic Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex","og_locale":"en_US","og_type":"article","og_title":"Managing State in Vue with Vuex","og_description":"Every app at some point will need to tackle one of the most contentious subjects in front end development: State Management. If you ask ten different developers how to manage state in an app, you&#8217;ll most likely get ten different answers, as everyone can have a slightly different approach if they were to build their [&hellip;]","og_url":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex","og_site_name":"Ionic Blog","article_published_time":"2021-02-24T15:43:56+00:00","article_modified_time":"2021-02-24T15:59:48+00:00","og_image":[{"width":1600,"height":880,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png","type":"image\/png"}],"author":"Mike Hartington","twitter_card":"summary_large_image","twitter_creator":"@mhartington","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Mike Hartington","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex"},"author":{"name":"Mike Hartington","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b"},"headline":"Managing State in Vue with Vuex","datePublished":"2021-02-24T15:43:56+00:00","dateModified":"2021-02-24T15:59:48+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex"},"wordCount":845,"commentCount":0,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png","keywords":["State Management","Vue","Vuex"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex","url":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex","name":"Managing State in Vue with Vuex - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png","datePublished":"2021-02-24T15:43:56+00:00","dateModified":"2021-02-24T15:59:48+00:00","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png","width":1600,"height":880},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/managing-state-in-vue-with-vuex#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Managing State in Vue with Vuex"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/c8c92b04d526adb925ea514c619a267b","name":"Mike Hartington","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2018\/08\/mike-headshot-2-smaller-150x150.png","caption":"Mike Hartington"},"description":"Director of Developer Relations","sameAs":["https:\/\/twitter.com\/mhartington","https:\/\/x.com\/mhartington"],"url":"https:\/\/ionic.io\/blog\/author\/mike"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/02\/state-management-vue-feature-image.png","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/3599","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=3599"}],"version-history":[{"count":0,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/3599\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/3601"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=3599"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=3599"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=3599"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}