[{"data":1,"prerenderedAt":2713},["ShallowReactive",2],{"writing-handling-different-component-states-with-a-status-class":3},{"id":4,"title":5,"body":6,"category":2699,"date":2700,"description":12,"excerpt":2701,"extension":2702,"image":2703,"keywords":2704,"meta":2705,"navigation":181,"path":2706,"readingTime":2707,"seo":2708,"slug":2709,"stem":2710,"tags":2711,"__hash__":2712},"blog\u002Fblog\u002Fhandling-different-component-states-with-a-status-class.md","Abstracting functionality to classes - Handling different component states",{"type":7,"value":8,"toc":2694},"minimark",[9,13,16,39,44,47,274,297,548,914,917,921,939,1118,1422,1431,1435,1438,2126,2135,2341,2660,2671,2674,2690],[10,11,12],"p",{},"(Part 1)",[10,14,15],{},"Web apps often require a loading state (things like loading spinners) to let a user know that an operation is taking place. These operations often take time, so it's best to let the user know something is loading, which helps improve UX, prevent form resubmissions, etc.",[10,17,18,19,23,24,27,28,27,31,34,35,38],{},"Beyond ",[20,21,22],"code",{},"loading",", our components can have other states too — ",[20,25,26],{},"completed",", ",[20,29,30],{},"rejected",[20,32,33],{},"idle",", etc. There are different ways of handling these states, so let's go through them. In the end, I am going to show you my way of handling these states by using a simple ",[20,36,37],{},"Status"," class that is very convenient to use.",[40,41,43],"h3",{"id":42},"handling-component-state-using-booleans","Handling component state using booleans",[10,45,46],{},"The most common example is a button that is disabled and maybe even has a loading spinner when we submit a form.",[48,49,54],"pre",{"className":50,"code":51,"language":52,"meta":53,"style":53},"language-vue shiki shiki-themes github-light github-dark","\u002F\u002F button-wrap.vue\n\u003Ctemplate>\n  \u003Cbutton v-bind=\"$attrs\" v-on=\"$listeners\" :disabled=\"isLoading\">\n    \u003Cspan v-if=\"isLoading\">Loading ...\u003C\u002Fspan>\n    \u003Cslot v-else>\u003C\u002Fslot>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\n  export default {\n    props: {\n      isLoading: {\n        required: false,\n        default: false,\n        type: Boolean,\n      }\n    }\n  }\n\u003C\u002Fscript>\n","vue","",[20,55,56,65,78,116,138,156,166,176,183,193,206,212,218,231,241,247,253,259,265],{"__ignoreMap":53},[57,58,61],"span",{"class":59,"line":60},"line",1,[57,62,64],{"class":63},"sVt8B","\u002F\u002F button-wrap.vue\n",[57,66,68,71,75],{"class":59,"line":67},2,[57,69,70],{"class":63},"\u003C",[57,72,74],{"class":73},"s9eBZ","template",[57,76,77],{"class":63},">\n",[57,79,81,84,87,91,94,98,101,103,106,109,111,114],{"class":59,"line":80},3,[57,82,83],{"class":63},"  \u003C",[57,85,86],{"class":73},"button",[57,88,90],{"class":89},"sScJk"," v-bind",[57,92,93],{"class":63},"=",[57,95,97],{"class":96},"sZZnC","\"$attrs\"",[57,99,100],{"class":89}," v-on",[57,102,93],{"class":63},[57,104,105],{"class":96},"\"$listeners\"",[57,107,108],{"class":89}," :disabled",[57,110,93],{"class":63},[57,112,113],{"class":96},"\"isLoading\"",[57,115,77],{"class":63},[57,117,119,122,124,127,129,131,134,136],{"class":59,"line":118},4,[57,120,121],{"class":63},"    \u003C",[57,123,57],{"class":73},[57,125,126],{"class":89}," v-if",[57,128,93],{"class":63},[57,130,113],{"class":96},[57,132,133],{"class":63},">Loading ...\u003C\u002F",[57,135,57],{"class":73},[57,137,77],{"class":63},[57,139,141,143,146,149,152,154],{"class":59,"line":140},5,[57,142,121],{"class":63},[57,144,145],{"class":73},"slot",[57,147,148],{"class":89}," v-else",[57,150,151],{"class":63},">\u003C\u002F",[57,153,145],{"class":73},[57,155,77],{"class":63},[57,157,159,162,164],{"class":59,"line":158},6,[57,160,161],{"class":63},"  \u003C\u002F",[57,163,86],{"class":73},[57,165,77],{"class":63},[57,167,169,172,174],{"class":59,"line":168},7,[57,170,171],{"class":63},"\u003C\u002F",[57,173,74],{"class":73},[57,175,77],{"class":63},[57,177,179],{"class":59,"line":178},8,[57,180,182],{"emptyLinePlaceholder":181},true,"\n",[57,184,186,188,191],{"class":59,"line":185},9,[57,187,70],{"class":63},[57,189,190],{"class":73},"script",[57,192,77],{"class":63},[57,194,196,200,203],{"class":59,"line":195},10,[57,197,199],{"class":198},"szBVR","  export",[57,201,202],{"class":198}," default",[57,204,205],{"class":63}," {\n",[57,207,209],{"class":59,"line":208},11,[57,210,211],{"class":63},"    props: {\n",[57,213,215],{"class":59,"line":214},12,[57,216,217],{"class":63},"      isLoading: {\n",[57,219,221,224,228],{"class":59,"line":220},13,[57,222,223],{"class":63},"        required: ",[57,225,227],{"class":226},"sj4cs","false",[57,229,230],{"class":63},",\n",[57,232,234,237,239],{"class":59,"line":233},14,[57,235,236],{"class":63},"        default: ",[57,238,227],{"class":226},[57,240,230],{"class":63},[57,242,244],{"class":59,"line":243},15,[57,245,246],{"class":63},"        type: Boolean,\n",[57,248,250],{"class":59,"line":249},16,[57,251,252],{"class":63},"      }\n",[57,254,256],{"class":59,"line":255},17,[57,257,258],{"class":63},"    }\n",[57,260,262],{"class":59,"line":261},18,[57,263,264],{"class":63},"  }\n",[57,266,268,270,272],{"class":59,"line":267},19,[57,269,171],{"class":63},[57,271,190],{"class":73},[57,273,77],{"class":63},[10,275,276,277,280,281,284,285,27,287,289,290,27,293,296],{},"This is a simple ",[20,278,279],{},"button-wrap"," component that we can use within our forms and pass a ",[20,282,283],{},"isLoading"," boolean prop whether the button should be disabled (the form is being submitted) and show a loading spinner instead of the button label. In most cases, this is probably the easiest way to handle the loading state. But, what if we need other states like ",[20,286,30],{},[20,288,26],{},", etc, do we pass ",[20,291,292],{},"isRejected",[20,294,295],{},"isCompleted"," booleans? Maybe for this case, it doesn't make sense, but be ensured that you will need these states somewhere along the line, and you will get cluttered with booleans just to cover all of the cases. This is with what you might end up eventually:",[48,298,300],{"className":50,"code":299,"language":52,"meta":53,"style":53},"\u002F\u002F button-wrap.vue\n\u003Ctemplate>\n  \u003Cbutton v-bind=\"$attrs\" v-on=\"$listeners\" :disabled=\"isLoading && !isCompleted && !isRejected\"\n    :class=\"{'is-valid': isCompleted, 'is-rejected': isRejected}\"\n  >\n    \u003Cspan v-if=\"isLoading && !isCompleted && !isRejected\">Loading ...\u003C\u002Fspan>\n    \u003Cslot v-else-if=\"!isLoading && !isCompleted && !isRejected\">\u003C\u002Fslot>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\n  export default {\n    props: {\n      isCompleted: {\n        required: false,\n        default: false,\n        type: Boolean,\n      },\n      isRejected: {\n        required: false,\n        default: false,\n        type: Boolean,\n      },\n      isLoading: {\n        required: false,\n        default: false,\n        type: Boolean,\n      }\n    }\n  }\n\u003C\u002Fscript>\n",[20,301,302,306,314,339,349,354,373,393,401,409,413,421,429,433,438,446,454,458,463,468,477,486,491,496,501,510,519,524,529,534,539],{"__ignoreMap":53},[57,303,304],{"class":59,"line":60},[57,305,64],{"class":63},[57,307,308,310,312],{"class":59,"line":67},[57,309,70],{"class":63},[57,311,74],{"class":73},[57,313,77],{"class":63},[57,315,316,318,320,322,324,326,328,330,332,334,336],{"class":59,"line":80},[57,317,83],{"class":63},[57,319,86],{"class":73},[57,321,90],{"class":89},[57,323,93],{"class":63},[57,325,97],{"class":96},[57,327,100],{"class":89},[57,329,93],{"class":63},[57,331,105],{"class":96},[57,333,108],{"class":89},[57,335,93],{"class":63},[57,337,338],{"class":96},"\"isLoading && !isCompleted && !isRejected\"\n",[57,340,341,344,346],{"class":59,"line":118},[57,342,343],{"class":89},"    :class",[57,345,93],{"class":63},[57,347,348],{"class":96},"\"{'is-valid': isCompleted, 'is-rejected': isRejected}\"\n",[57,350,351],{"class":59,"line":140},[57,352,353],{"class":63},"  >\n",[57,355,356,358,360,362,364,367,369,371],{"class":59,"line":158},[57,357,121],{"class":63},[57,359,57],{"class":73},[57,361,126],{"class":89},[57,363,93],{"class":63},[57,365,366],{"class":96},"\"isLoading && !isCompleted && !isRejected\"",[57,368,133],{"class":63},[57,370,57],{"class":73},[57,372,77],{"class":63},[57,374,375,377,379,382,384,387,389,391],{"class":59,"line":168},[57,376,121],{"class":63},[57,378,145],{"class":73},[57,380,381],{"class":89}," v-else-if",[57,383,93],{"class":63},[57,385,386],{"class":96},"\"!isLoading && !isCompleted && !isRejected\"",[57,388,151],{"class":63},[57,390,145],{"class":73},[57,392,77],{"class":63},[57,394,395,397,399],{"class":59,"line":178},[57,396,161],{"class":63},[57,398,86],{"class":73},[57,400,77],{"class":63},[57,402,403,405,407],{"class":59,"line":185},[57,404,171],{"class":63},[57,406,74],{"class":73},[57,408,77],{"class":63},[57,410,411],{"class":59,"line":195},[57,412,182],{"emptyLinePlaceholder":181},[57,414,415,417,419],{"class":59,"line":208},[57,416,70],{"class":63},[57,418,190],{"class":73},[57,420,77],{"class":63},[57,422,423,425,427],{"class":59,"line":214},[57,424,199],{"class":198},[57,426,202],{"class":198},[57,428,205],{"class":63},[57,430,431],{"class":59,"line":220},[57,432,211],{"class":63},[57,434,435],{"class":59,"line":233},[57,436,437],{"class":63},"      isCompleted: {\n",[57,439,440,442,444],{"class":59,"line":243},[57,441,223],{"class":63},[57,443,227],{"class":226},[57,445,230],{"class":63},[57,447,448,450,452],{"class":59,"line":249},[57,449,236],{"class":63},[57,451,227],{"class":226},[57,453,230],{"class":63},[57,455,456],{"class":59,"line":255},[57,457,246],{"class":63},[57,459,460],{"class":59,"line":261},[57,461,462],{"class":63},"      },\n",[57,464,465],{"class":59,"line":267},[57,466,467],{"class":63},"      isRejected: {\n",[57,469,471,473,475],{"class":59,"line":470},20,[57,472,223],{"class":63},[57,474,227],{"class":226},[57,476,230],{"class":63},[57,478,480,482,484],{"class":59,"line":479},21,[57,481,236],{"class":63},[57,483,227],{"class":226},[57,485,230],{"class":63},[57,487,489],{"class":59,"line":488},22,[57,490,246],{"class":63},[57,492,494],{"class":59,"line":493},23,[57,495,462],{"class":63},[57,497,499],{"class":59,"line":498},24,[57,500,217],{"class":63},[57,502,504,506,508],{"class":59,"line":503},25,[57,505,223],{"class":63},[57,507,227],{"class":226},[57,509,230],{"class":63},[57,511,513,515,517],{"class":59,"line":512},26,[57,514,236],{"class":63},[57,516,227],{"class":226},[57,518,230],{"class":63},[57,520,522],{"class":59,"line":521},27,[57,523,246],{"class":63},[57,525,527],{"class":59,"line":526},28,[57,528,252],{"class":63},[57,530,532],{"class":59,"line":531},29,[57,533,258],{"class":63},[57,535,537],{"class":59,"line":536},30,[57,538,264],{"class":63},[57,540,542,544,546],{"class":59,"line":541},31,[57,543,171],{"class":63},[57,545,190],{"class":73},[57,547,77],{"class":63},[48,549,551],{"className":50,"code":550,"language":52,"meta":53,"style":53},"\u002F\u002Fform.vue\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"onSubmit\">\n  \u002F\u002F\n  \u003Cbutton-wrap :isLoading=\"status.isLoading\"\n    :isCompleted=\"status.isCompleted\"\n    :isRejected=\"status.isRejected\">\n    Submit\n  \u003C\u002Fbutton-wrap>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\n  export default {\n    data: () => ({\n      status: {\n        isLoading: false,\n        isRejected: false,\n        isCompleted: false,\n      }\n    }),\n\n    methods: {\n      onSubmit() {\n        this.status.isLoading = true;\n\n        axios.post(url, data)\n          .then((response) => {\n            this.status.isCompleted = true;\n          })\n          .catch((error) => {\n            this.status.isRejected = true;\n          });\n          .finally(() => {\n            this.status.isLoading = false;\n          }\n      }\n    }\n  }\n\u003C\u002Fscript>\n",[20,552,553,558,566,583,588,602,612,624,629,637,645,653,657,665,673,687,692,701,710,719,723,728,732,737,745,761,765,776,798,812,817,835,849,855,870,884,890,895,900,905],{"__ignoreMap":53},[57,554,555],{"class":59,"line":60},[57,556,557],{"class":63},"\u002F\u002Fform.vue\n",[57,559,560,562,564],{"class":59,"line":67},[57,561,70],{"class":63},[57,563,74],{"class":73},[57,565,77],{"class":63},[57,567,568,570,573,576,578,581],{"class":59,"line":80},[57,569,83],{"class":63},[57,571,572],{"class":73},"form",[57,574,575],{"class":89}," @submit.prevent",[57,577,93],{"class":63},[57,579,580],{"class":96},"\"onSubmit\"",[57,582,77],{"class":63},[57,584,585],{"class":59,"line":118},[57,586,587],{"class":63},"  \u002F\u002F\n",[57,589,590,592,594,597,599],{"class":59,"line":140},[57,591,83],{"class":63},[57,593,279],{"class":73},[57,595,596],{"class":89}," :isLoading",[57,598,93],{"class":63},[57,600,601],{"class":96},"\"status.isLoading\"\n",[57,603,604,607,609],{"class":59,"line":158},[57,605,606],{"class":89},"    :isCompleted",[57,608,93],{"class":63},[57,610,611],{"class":96},"\"status.isCompleted\"\n",[57,613,614,617,619,622],{"class":59,"line":168},[57,615,616],{"class":89},"    :isRejected",[57,618,93],{"class":63},[57,620,621],{"class":96},"\"status.isRejected\"",[57,623,77],{"class":63},[57,625,626],{"class":59,"line":178},[57,627,628],{"class":63},"    Submit\n",[57,630,631,633,635],{"class":59,"line":185},[57,632,161],{"class":63},[57,634,279],{"class":73},[57,636,77],{"class":63},[57,638,639,641,643],{"class":59,"line":195},[57,640,161],{"class":63},[57,642,572],{"class":73},[57,644,77],{"class":63},[57,646,647,649,651],{"class":59,"line":208},[57,648,171],{"class":63},[57,650,74],{"class":73},[57,652,77],{"class":63},[57,654,655],{"class":59,"line":214},[57,656,182],{"emptyLinePlaceholder":181},[57,658,659,661,663],{"class":59,"line":220},[57,660,70],{"class":63},[57,662,190],{"class":73},[57,664,77],{"class":63},[57,666,667,669,671],{"class":59,"line":233},[57,668,199],{"class":198},[57,670,202],{"class":198},[57,672,205],{"class":63},[57,674,675,678,681,684],{"class":59,"line":243},[57,676,677],{"class":89},"    data",[57,679,680],{"class":63},": () ",[57,682,683],{"class":198},"=>",[57,685,686],{"class":63}," ({\n",[57,688,689],{"class":59,"line":249},[57,690,691],{"class":63},"      status: {\n",[57,693,694,697,699],{"class":59,"line":255},[57,695,696],{"class":63},"        isLoading: ",[57,698,227],{"class":226},[57,700,230],{"class":63},[57,702,703,706,708],{"class":59,"line":261},[57,704,705],{"class":63},"        isRejected: ",[57,707,227],{"class":226},[57,709,230],{"class":63},[57,711,712,715,717],{"class":59,"line":267},[57,713,714],{"class":63},"        isCompleted: ",[57,716,227],{"class":226},[57,718,230],{"class":63},[57,720,721],{"class":59,"line":470},[57,722,252],{"class":63},[57,724,725],{"class":59,"line":479},[57,726,727],{"class":63},"    }),\n",[57,729,730],{"class":59,"line":488},[57,731,182],{"emptyLinePlaceholder":181},[57,733,734],{"class":59,"line":493},[57,735,736],{"class":63},"    methods: {\n",[57,738,739,742],{"class":59,"line":498},[57,740,741],{"class":89},"      onSubmit",[57,743,744],{"class":63},"() {\n",[57,746,747,750,753,755,758],{"class":59,"line":503},[57,748,749],{"class":226},"        this",[57,751,752],{"class":63},".status.isLoading ",[57,754,93],{"class":198},[57,756,757],{"class":226}," true",[57,759,760],{"class":63},";\n",[57,762,763],{"class":59,"line":512},[57,764,182],{"emptyLinePlaceholder":181},[57,766,767,770,773],{"class":59,"line":521},[57,768,769],{"class":63},"        axios.",[57,771,772],{"class":89},"post",[57,774,775],{"class":63},"(url, data)\n",[57,777,778,781,784,787,791,794,796],{"class":59,"line":526},[57,779,780],{"class":63},"          .",[57,782,783],{"class":89},"then",[57,785,786],{"class":63},"((",[57,788,790],{"class":789},"s4XuR","response",[57,792,793],{"class":63},") ",[57,795,683],{"class":198},[57,797,205],{"class":63},[57,799,800,803,806,808,810],{"class":59,"line":531},[57,801,802],{"class":226},"            this",[57,804,805],{"class":63},".status.isCompleted ",[57,807,93],{"class":198},[57,809,757],{"class":226},[57,811,760],{"class":63},[57,813,814],{"class":59,"line":536},[57,815,816],{"class":63},"          })\n",[57,818,819,821,824,826,829,831,833],{"class":59,"line":541},[57,820,780],{"class":63},[57,822,823],{"class":89},"catch",[57,825,786],{"class":63},[57,827,828],{"class":789},"error",[57,830,793],{"class":63},[57,832,683],{"class":198},[57,834,205],{"class":63},[57,836,838,840,843,845,847],{"class":59,"line":837},32,[57,839,802],{"class":226},[57,841,842],{"class":63},".status.isRejected ",[57,844,93],{"class":198},[57,846,757],{"class":226},[57,848,760],{"class":63},[57,850,852],{"class":59,"line":851},33,[57,853,854],{"class":63},"          });\n",[57,856,858,860,863,866,868],{"class":59,"line":857},34,[57,859,780],{"class":63},[57,861,862],{"class":89},"finally",[57,864,865],{"class":63},"(() ",[57,867,683],{"class":198},[57,869,205],{"class":63},[57,871,873,875,877,879,882],{"class":59,"line":872},35,[57,874,802],{"class":226},[57,876,752],{"class":63},[57,878,93],{"class":198},[57,880,881],{"class":226}," false",[57,883,760],{"class":63},[57,885,887],{"class":59,"line":886},36,[57,888,889],{"class":63},"          }\n",[57,891,893],{"class":59,"line":892},37,[57,894,252],{"class":63},[57,896,898],{"class":59,"line":897},38,[57,899,258],{"class":63},[57,901,903],{"class":59,"line":902},39,[57,904,264],{"class":63},[57,906,908,910,912],{"class":59,"line":907},40,[57,909,171],{"class":198},[57,911,190],{"class":63},[57,913,77],{"class":198},[10,915,916],{},"Having three booleans for three different states feels a bit redundant when the button can have only one state at a time. Let's see a more convenient way to do this using classes.",[40,918,920],{"id":919},"handling-component-state-using-status-property","Handling component state using status property",[10,922,923,924,927,928,931,932,935,936,938],{},"Since a component can have only one state at a time, we can simplify by having one ",[20,925,926],{},"data"," property named ",[20,929,930],{},"status"," and use ",[20,933,934],{},"strings"," to represent the state that the component is currently in. Changing the value of the ",[20,937,930],{}," would be a notification to the component that its state changed. This implementation would look like this:",[48,940,942],{"className":50,"code":941,"language":52,"meta":53,"style":53},"\u002F\u002F button-wrap.vue\n\u003Ctemplate>\n  \u003Cbutton v-bind=\"$attrs\" v-on=\"$listeners\" :disabled=\"status === 'loading'\"\n    :class=\"{'is-valid': status === 'completed', 'is-rejected': status === 'rejected'}\"\n  >\n    \u003Cspan v-if=\"status === 'loading'\">Loading ...\u003C\u002Fspan>\n    \u003Cslot v-else-if=\"status !== 'rejected' && status !== 'loading'\">\u003C\u002Fslot>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\n  export default {\n    props: {\n      status: {\n        required: false,\n        default: 'idle',\n        type: String,\n      }\n    }\n  }\n\u003C\u002Fscript>\n",[20,943,944,948,956,981,990,994,1013,1032,1040,1048,1052,1060,1068,1072,1076,1084,1093,1098,1102,1106,1110],{"__ignoreMap":53},[57,945,946],{"class":59,"line":60},[57,947,64],{"class":63},[57,949,950,952,954],{"class":59,"line":67},[57,951,70],{"class":63},[57,953,74],{"class":73},[57,955,77],{"class":63},[57,957,958,960,962,964,966,968,970,972,974,976,978],{"class":59,"line":80},[57,959,83],{"class":63},[57,961,86],{"class":73},[57,963,90],{"class":89},[57,965,93],{"class":63},[57,967,97],{"class":96},[57,969,100],{"class":89},[57,971,93],{"class":63},[57,973,105],{"class":96},[57,975,108],{"class":89},[57,977,93],{"class":63},[57,979,980],{"class":96},"\"status === 'loading'\"\n",[57,982,983,985,987],{"class":59,"line":118},[57,984,343],{"class":89},[57,986,93],{"class":63},[57,988,989],{"class":96},"\"{'is-valid': status === 'completed', 'is-rejected': status === 'rejected'}\"\n",[57,991,992],{"class":59,"line":140},[57,993,353],{"class":63},[57,995,996,998,1000,1002,1004,1007,1009,1011],{"class":59,"line":158},[57,997,121],{"class":63},[57,999,57],{"class":73},[57,1001,126],{"class":89},[57,1003,93],{"class":63},[57,1005,1006],{"class":96},"\"status === 'loading'\"",[57,1008,133],{"class":63},[57,1010,57],{"class":73},[57,1012,77],{"class":63},[57,1014,1015,1017,1019,1021,1023,1026,1028,1030],{"class":59,"line":168},[57,1016,121],{"class":63},[57,1018,145],{"class":73},[57,1020,381],{"class":89},[57,1022,93],{"class":63},[57,1024,1025],{"class":96},"\"status !== 'rejected' && status !== 'loading'\"",[57,1027,151],{"class":63},[57,1029,145],{"class":73},[57,1031,77],{"class":63},[57,1033,1034,1036,1038],{"class":59,"line":178},[57,1035,161],{"class":63},[57,1037,86],{"class":73},[57,1039,77],{"class":63},[57,1041,1042,1044,1046],{"class":59,"line":185},[57,1043,171],{"class":63},[57,1045,74],{"class":73},[57,1047,77],{"class":63},[57,1049,1050],{"class":59,"line":195},[57,1051,182],{"emptyLinePlaceholder":181},[57,1053,1054,1056,1058],{"class":59,"line":208},[57,1055,70],{"class":63},[57,1057,190],{"class":73},[57,1059,77],{"class":63},[57,1061,1062,1064,1066],{"class":59,"line":214},[57,1063,199],{"class":198},[57,1065,202],{"class":198},[57,1067,205],{"class":63},[57,1069,1070],{"class":59,"line":220},[57,1071,211],{"class":63},[57,1073,1074],{"class":59,"line":233},[57,1075,691],{"class":63},[57,1077,1078,1080,1082],{"class":59,"line":243},[57,1079,223],{"class":63},[57,1081,227],{"class":226},[57,1083,230],{"class":63},[57,1085,1086,1088,1091],{"class":59,"line":249},[57,1087,236],{"class":63},[57,1089,1090],{"class":96},"'idle'",[57,1092,230],{"class":63},[57,1094,1095],{"class":59,"line":255},[57,1096,1097],{"class":63},"        type: String,\n",[57,1099,1100],{"class":59,"line":261},[57,1101,252],{"class":63},[57,1103,1104],{"class":59,"line":267},[57,1105,258],{"class":63},[57,1107,1108],{"class":59,"line":470},[57,1109,264],{"class":63},[57,1111,1112,1114,1116],{"class":59,"line":479},[57,1113,171],{"class":63},[57,1115,190],{"class":73},[57,1117,77],{"class":63},[48,1119,1121],{"className":50,"code":1120,"language":52,"meta":53,"style":53},"\u002F\u002Fform.vue\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"onSubmit\">\n  \u002F\u002F\n  \u003Cbutton-wrap :status=\"status\">\n    Submit\n  \u003C\u002Fbutton-wrap>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\n  export default {\n    data: () => ({\n      status: 'idle'\n    }),\n\n    methods: {\n      onSubmit() {\n        this.status = 'loading';\n\n        axios.post(url, data)\n          .then((response) => {\n            this.status = 'completed';\n          })\n          .catch((error) => {\n            this.status = 'rejected';\n          });\n          .finally(() => {\n            if(this.status !== 'rejected') {\n              this.status === 'idle';\n            }\n          }\n      }\n    }\n  }\n\u003C\u002Fscript>\n",[20,1122,1123,1127,1135,1149,1153,1169,1173,1181,1189,1197,1201,1209,1217,1227,1235,1239,1243,1247,1253,1267,1271,1279,1295,1308,1312,1328,1341,1345,1357,1378,1393,1398,1402,1406,1410,1414],{"__ignoreMap":53},[57,1124,1125],{"class":59,"line":60},[57,1126,557],{"class":63},[57,1128,1129,1131,1133],{"class":59,"line":67},[57,1130,70],{"class":63},[57,1132,74],{"class":73},[57,1134,77],{"class":63},[57,1136,1137,1139,1141,1143,1145,1147],{"class":59,"line":80},[57,1138,83],{"class":63},[57,1140,572],{"class":73},[57,1142,575],{"class":89},[57,1144,93],{"class":63},[57,1146,580],{"class":96},[57,1148,77],{"class":63},[57,1150,1151],{"class":59,"line":118},[57,1152,587],{"class":63},[57,1154,1155,1157,1159,1162,1164,1167],{"class":59,"line":140},[57,1156,83],{"class":63},[57,1158,279],{"class":73},[57,1160,1161],{"class":89}," :status",[57,1163,93],{"class":63},[57,1165,1166],{"class":96},"\"status\"",[57,1168,77],{"class":63},[57,1170,1171],{"class":59,"line":158},[57,1172,628],{"class":63},[57,1174,1175,1177,1179],{"class":59,"line":168},[57,1176,161],{"class":63},[57,1178,279],{"class":73},[57,1180,77],{"class":63},[57,1182,1183,1185,1187],{"class":59,"line":178},[57,1184,161],{"class":63},[57,1186,572],{"class":73},[57,1188,77],{"class":63},[57,1190,1191,1193,1195],{"class":59,"line":185},[57,1192,171],{"class":63},[57,1194,74],{"class":73},[57,1196,77],{"class":63},[57,1198,1199],{"class":59,"line":195},[57,1200,182],{"emptyLinePlaceholder":181},[57,1202,1203,1205,1207],{"class":59,"line":208},[57,1204,70],{"class":63},[57,1206,190],{"class":73},[57,1208,77],{"class":63},[57,1210,1211,1213,1215],{"class":59,"line":214},[57,1212,199],{"class":198},[57,1214,202],{"class":198},[57,1216,205],{"class":63},[57,1218,1219,1221,1223,1225],{"class":59,"line":220},[57,1220,677],{"class":89},[57,1222,680],{"class":63},[57,1224,683],{"class":198},[57,1226,686],{"class":63},[57,1228,1229,1232],{"class":59,"line":233},[57,1230,1231],{"class":63},"      status: ",[57,1233,1234],{"class":96},"'idle'\n",[57,1236,1237],{"class":59,"line":243},[57,1238,727],{"class":63},[57,1240,1241],{"class":59,"line":249},[57,1242,182],{"emptyLinePlaceholder":181},[57,1244,1245],{"class":59,"line":255},[57,1246,736],{"class":63},[57,1248,1249,1251],{"class":59,"line":261},[57,1250,741],{"class":89},[57,1252,744],{"class":63},[57,1254,1255,1257,1260,1262,1265],{"class":59,"line":267},[57,1256,749],{"class":226},[57,1258,1259],{"class":63},".status ",[57,1261,93],{"class":198},[57,1263,1264],{"class":96}," 'loading'",[57,1266,760],{"class":63},[57,1268,1269],{"class":59,"line":470},[57,1270,182],{"emptyLinePlaceholder":181},[57,1272,1273,1275,1277],{"class":59,"line":479},[57,1274,769],{"class":63},[57,1276,772],{"class":89},[57,1278,775],{"class":63},[57,1280,1281,1283,1285,1287,1289,1291,1293],{"class":59,"line":488},[57,1282,780],{"class":63},[57,1284,783],{"class":89},[57,1286,786],{"class":63},[57,1288,790],{"class":789},[57,1290,793],{"class":63},[57,1292,683],{"class":198},[57,1294,205],{"class":63},[57,1296,1297,1299,1301,1303,1306],{"class":59,"line":493},[57,1298,802],{"class":226},[57,1300,1259],{"class":63},[57,1302,93],{"class":198},[57,1304,1305],{"class":96}," 'completed'",[57,1307,760],{"class":63},[57,1309,1310],{"class":59,"line":498},[57,1311,816],{"class":63},[57,1313,1314,1316,1318,1320,1322,1324,1326],{"class":59,"line":503},[57,1315,780],{"class":63},[57,1317,823],{"class":89},[57,1319,786],{"class":63},[57,1321,828],{"class":789},[57,1323,793],{"class":63},[57,1325,683],{"class":198},[57,1327,205],{"class":63},[57,1329,1330,1332,1334,1336,1339],{"class":59,"line":512},[57,1331,802],{"class":226},[57,1333,1259],{"class":63},[57,1335,93],{"class":198},[57,1337,1338],{"class":96}," 'rejected'",[57,1340,760],{"class":63},[57,1342,1343],{"class":59,"line":521},[57,1344,854],{"class":63},[57,1346,1347,1349,1351,1353,1355],{"class":59,"line":526},[57,1348,780],{"class":63},[57,1350,862],{"class":89},[57,1352,865],{"class":63},[57,1354,683],{"class":198},[57,1356,205],{"class":63},[57,1358,1359,1362,1365,1368,1370,1373,1375],{"class":59,"line":531},[57,1360,1361],{"class":198},"            if",[57,1363,1364],{"class":63},"(",[57,1366,1367],{"class":226},"this",[57,1369,1259],{"class":63},[57,1371,1372],{"class":198},"!==",[57,1374,1338],{"class":96},[57,1376,1377],{"class":63},") {\n",[57,1379,1380,1383,1385,1388,1391],{"class":59,"line":536},[57,1381,1382],{"class":226},"              this",[57,1384,1259],{"class":63},[57,1386,1387],{"class":198},"===",[57,1389,1390],{"class":96}," 'idle'",[57,1392,760],{"class":63},[57,1394,1395],{"class":59,"line":541},[57,1396,1397],{"class":63},"            }\n",[57,1399,1400],{"class":59,"line":837},[57,1401,889],{"class":63},[57,1403,1404],{"class":59,"line":851},[57,1405,252],{"class":63},[57,1407,1408],{"class":59,"line":857},[57,1409,258],{"class":63},[57,1411,1412],{"class":59,"line":872},[57,1413,264],{"class":63},[57,1415,1416,1418,1420],{"class":59,"line":886},[57,1417,171],{"class":198},[57,1419,190],{"class":63},[57,1421,77],{"class":198},[10,1423,1424,1425,1427,1428,1430],{},"What would happen if we want to introduce a new state? What if we want to change the ",[20,1426,30],{}," class to ",[20,1429,828],{},"?",[40,1432,1434],{"id":1433},"handling-component-state-using-a-status-class","Handling component state using a Status class",[10,1436,1437],{},"Nothing prevents us from using JavaScript classes within our Vue components. When abstracting functionality, I always try to find the most pragmatic approach. We can achieve this by combining the best parts of both approaches above. Let's build the Status class now.",[48,1439,1443],{"className":1440,"code":1441,"language":1442,"meta":53,"style":53},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F classes\u002FStatus.js\n\nexport const STATUS = {\n  IDLE: \"idle\",\n  LOADING: \"loading\",\n  COMPLETED: \"completed\",\n  REJECTED: \"rejected\",\n};\n\nexport default class Status {\n  constructor(status = STATUS.IDLE) {\n    this.status = status;\n  }\n\n  get() {\n    return this.status;\n  }\n\n  set(status) {\n    this.status = status;\n  }\n\n  is(status) {\n    return this.status === status;\n  }\n\n  isLoading() {\n    return this.is(STATUS.LOADING);\n  }\n\n  isNotLoading() {\n    return !this.is(STATUS.LOADING);\n  }\n\n  isCompleted() {\n    return this.is(STATUS.COMPLETED);\n  }\n\n  isIdle() {\n    return this.is(STATUS.IDLE);\n  }\n\n  isRejected() {\n    return this.is(STATUS.REJECTED);\n  }\n\n  setLoading() {\n    this.set(STATUS.LOADING);\n  }\n\n  setCompleted() {\n    this.set(STATUS.COMPLETED);\n  }\n\n  setRejected() {\n    this.set(STATUS.REJECTED);\n  }\n\n  setIdle() {\n    this.set(STATUS.IDLE);\n  }\n\n  toggle() {\n    this.set(this.status === STATUS.IDLE ? STATUS.LOADING : STATUS.IDLE);\n  }\n\n  toString() {\n    return this.get();\n  }\n\n  valueOf() {\n    return this.get();\n  }\n}\n","javascript",[20,1444,1445,1451,1455,1471,1481,1491,1501,1511,1516,1520,1534,1555,1567,1571,1575,1582,1593,1597,1601,1612,1622,1626,1630,1641,1653,1657,1661,1668,1692,1696,1700,1707,1730,1734,1738,1745,1766,1770,1774,1781,1801,1806,1811,1819,1841,1846,1851,1859,1879,1884,1889,1897,1916,1921,1926,1934,1953,1958,1963,1971,1990,1995,2000,2008,2051,2056,2061,2069,2084,2089,2094,2102,2115,2120],{"__ignoreMap":53},[57,1446,1447],{"class":59,"line":60},[57,1448,1450],{"class":1449},"sJ8bj","\u002F\u002F classes\u002FStatus.js\n",[57,1452,1453],{"class":59,"line":67},[57,1454,182],{"emptyLinePlaceholder":181},[57,1456,1457,1460,1463,1466,1469],{"class":59,"line":80},[57,1458,1459],{"class":198},"export",[57,1461,1462],{"class":198}," const",[57,1464,1465],{"class":226}," STATUS",[57,1467,1468],{"class":198}," =",[57,1470,205],{"class":63},[57,1472,1473,1476,1479],{"class":59,"line":118},[57,1474,1475],{"class":63},"  IDLE: ",[57,1477,1478],{"class":96},"\"idle\"",[57,1480,230],{"class":63},[57,1482,1483,1486,1489],{"class":59,"line":140},[57,1484,1485],{"class":63},"  LOADING: ",[57,1487,1488],{"class":96},"\"loading\"",[57,1490,230],{"class":63},[57,1492,1493,1496,1499],{"class":59,"line":158},[57,1494,1495],{"class":63},"  COMPLETED: ",[57,1497,1498],{"class":96},"\"completed\"",[57,1500,230],{"class":63},[57,1502,1503,1506,1509],{"class":59,"line":168},[57,1504,1505],{"class":63},"  REJECTED: ",[57,1507,1508],{"class":96},"\"rejected\"",[57,1510,230],{"class":63},[57,1512,1513],{"class":59,"line":178},[57,1514,1515],{"class":63},"};\n",[57,1517,1518],{"class":59,"line":185},[57,1519,182],{"emptyLinePlaceholder":181},[57,1521,1522,1524,1526,1529,1532],{"class":59,"line":195},[57,1523,1459],{"class":198},[57,1525,202],{"class":198},[57,1527,1528],{"class":198}," class",[57,1530,1531],{"class":89}," Status",[57,1533,205],{"class":63},[57,1535,1536,1539,1541,1543,1545,1547,1550,1553],{"class":59,"line":208},[57,1537,1538],{"class":198},"  constructor",[57,1540,1364],{"class":63},[57,1542,930],{"class":789},[57,1544,1468],{"class":198},[57,1546,1465],{"class":226},[57,1548,1549],{"class":63},".",[57,1551,1552],{"class":226},"IDLE",[57,1554,1377],{"class":63},[57,1556,1557,1560,1562,1564],{"class":59,"line":214},[57,1558,1559],{"class":226},"    this",[57,1561,1259],{"class":63},[57,1563,93],{"class":198},[57,1565,1566],{"class":63}," status;\n",[57,1568,1569],{"class":59,"line":220},[57,1570,264],{"class":63},[57,1572,1573],{"class":59,"line":233},[57,1574,182],{"emptyLinePlaceholder":181},[57,1576,1577,1580],{"class":59,"line":243},[57,1578,1579],{"class":89},"  get",[57,1581,744],{"class":63},[57,1583,1584,1587,1590],{"class":59,"line":249},[57,1585,1586],{"class":198},"    return",[57,1588,1589],{"class":226}," this",[57,1591,1592],{"class":63},".status;\n",[57,1594,1595],{"class":59,"line":255},[57,1596,264],{"class":63},[57,1598,1599],{"class":59,"line":261},[57,1600,182],{"emptyLinePlaceholder":181},[57,1602,1603,1606,1608,1610],{"class":59,"line":267},[57,1604,1605],{"class":89},"  set",[57,1607,1364],{"class":63},[57,1609,930],{"class":789},[57,1611,1377],{"class":63},[57,1613,1614,1616,1618,1620],{"class":59,"line":470},[57,1615,1559],{"class":226},[57,1617,1259],{"class":63},[57,1619,93],{"class":198},[57,1621,1566],{"class":63},[57,1623,1624],{"class":59,"line":479},[57,1625,264],{"class":63},[57,1627,1628],{"class":59,"line":488},[57,1629,182],{"emptyLinePlaceholder":181},[57,1631,1632,1635,1637,1639],{"class":59,"line":493},[57,1633,1634],{"class":89},"  is",[57,1636,1364],{"class":63},[57,1638,930],{"class":789},[57,1640,1377],{"class":63},[57,1642,1643,1645,1647,1649,1651],{"class":59,"line":498},[57,1644,1586],{"class":198},[57,1646,1589],{"class":226},[57,1648,1259],{"class":63},[57,1650,1387],{"class":198},[57,1652,1566],{"class":63},[57,1654,1655],{"class":59,"line":503},[57,1656,264],{"class":63},[57,1658,1659],{"class":59,"line":512},[57,1660,182],{"emptyLinePlaceholder":181},[57,1662,1663,1666],{"class":59,"line":521},[57,1664,1665],{"class":89},"  isLoading",[57,1667,744],{"class":63},[57,1669,1670,1672,1674,1676,1679,1681,1684,1686,1689],{"class":59,"line":526},[57,1671,1586],{"class":198},[57,1673,1589],{"class":226},[57,1675,1549],{"class":63},[57,1677,1678],{"class":89},"is",[57,1680,1364],{"class":63},[57,1682,1683],{"class":226},"STATUS",[57,1685,1549],{"class":63},[57,1687,1688],{"class":226},"LOADING",[57,1690,1691],{"class":63},");\n",[57,1693,1694],{"class":59,"line":531},[57,1695,264],{"class":63},[57,1697,1698],{"class":59,"line":536},[57,1699,182],{"emptyLinePlaceholder":181},[57,1701,1702,1705],{"class":59,"line":541},[57,1703,1704],{"class":89},"  isNotLoading",[57,1706,744],{"class":63},[57,1708,1709,1711,1714,1716,1718,1720,1722,1724,1726,1728],{"class":59,"line":837},[57,1710,1586],{"class":198},[57,1712,1713],{"class":198}," !",[57,1715,1367],{"class":226},[57,1717,1549],{"class":63},[57,1719,1678],{"class":89},[57,1721,1364],{"class":63},[57,1723,1683],{"class":226},[57,1725,1549],{"class":63},[57,1727,1688],{"class":226},[57,1729,1691],{"class":63},[57,1731,1732],{"class":59,"line":851},[57,1733,264],{"class":63},[57,1735,1736],{"class":59,"line":857},[57,1737,182],{"emptyLinePlaceholder":181},[57,1739,1740,1743],{"class":59,"line":872},[57,1741,1742],{"class":89},"  isCompleted",[57,1744,744],{"class":63},[57,1746,1747,1749,1751,1753,1755,1757,1759,1761,1764],{"class":59,"line":886},[57,1748,1586],{"class":198},[57,1750,1589],{"class":226},[57,1752,1549],{"class":63},[57,1754,1678],{"class":89},[57,1756,1364],{"class":63},[57,1758,1683],{"class":226},[57,1760,1549],{"class":63},[57,1762,1763],{"class":226},"COMPLETED",[57,1765,1691],{"class":63},[57,1767,1768],{"class":59,"line":892},[57,1769,264],{"class":63},[57,1771,1772],{"class":59,"line":897},[57,1773,182],{"emptyLinePlaceholder":181},[57,1775,1776,1779],{"class":59,"line":902},[57,1777,1778],{"class":89},"  isIdle",[57,1780,744],{"class":63},[57,1782,1783,1785,1787,1789,1791,1793,1795,1797,1799],{"class":59,"line":907},[57,1784,1586],{"class":198},[57,1786,1589],{"class":226},[57,1788,1549],{"class":63},[57,1790,1678],{"class":89},[57,1792,1364],{"class":63},[57,1794,1683],{"class":226},[57,1796,1549],{"class":63},[57,1798,1552],{"class":226},[57,1800,1691],{"class":63},[57,1802,1804],{"class":59,"line":1803},41,[57,1805,264],{"class":63},[57,1807,1809],{"class":59,"line":1808},42,[57,1810,182],{"emptyLinePlaceholder":181},[57,1812,1814,1817],{"class":59,"line":1813},43,[57,1815,1816],{"class":89},"  isRejected",[57,1818,744],{"class":63},[57,1820,1822,1824,1826,1828,1830,1832,1834,1836,1839],{"class":59,"line":1821},44,[57,1823,1586],{"class":198},[57,1825,1589],{"class":226},[57,1827,1549],{"class":63},[57,1829,1678],{"class":89},[57,1831,1364],{"class":63},[57,1833,1683],{"class":226},[57,1835,1549],{"class":63},[57,1837,1838],{"class":226},"REJECTED",[57,1840,1691],{"class":63},[57,1842,1844],{"class":59,"line":1843},45,[57,1845,264],{"class":63},[57,1847,1849],{"class":59,"line":1848},46,[57,1850,182],{"emptyLinePlaceholder":181},[57,1852,1854,1857],{"class":59,"line":1853},47,[57,1855,1856],{"class":89},"  setLoading",[57,1858,744],{"class":63},[57,1860,1862,1864,1866,1869,1871,1873,1875,1877],{"class":59,"line":1861},48,[57,1863,1559],{"class":226},[57,1865,1549],{"class":63},[57,1867,1868],{"class":89},"set",[57,1870,1364],{"class":63},[57,1872,1683],{"class":226},[57,1874,1549],{"class":63},[57,1876,1688],{"class":226},[57,1878,1691],{"class":63},[57,1880,1882],{"class":59,"line":1881},49,[57,1883,264],{"class":63},[57,1885,1887],{"class":59,"line":1886},50,[57,1888,182],{"emptyLinePlaceholder":181},[57,1890,1892,1895],{"class":59,"line":1891},51,[57,1893,1894],{"class":89},"  setCompleted",[57,1896,744],{"class":63},[57,1898,1900,1902,1904,1906,1908,1910,1912,1914],{"class":59,"line":1899},52,[57,1901,1559],{"class":226},[57,1903,1549],{"class":63},[57,1905,1868],{"class":89},[57,1907,1364],{"class":63},[57,1909,1683],{"class":226},[57,1911,1549],{"class":63},[57,1913,1763],{"class":226},[57,1915,1691],{"class":63},[57,1917,1919],{"class":59,"line":1918},53,[57,1920,264],{"class":63},[57,1922,1924],{"class":59,"line":1923},54,[57,1925,182],{"emptyLinePlaceholder":181},[57,1927,1929,1932],{"class":59,"line":1928},55,[57,1930,1931],{"class":89},"  setRejected",[57,1933,744],{"class":63},[57,1935,1937,1939,1941,1943,1945,1947,1949,1951],{"class":59,"line":1936},56,[57,1938,1559],{"class":226},[57,1940,1549],{"class":63},[57,1942,1868],{"class":89},[57,1944,1364],{"class":63},[57,1946,1683],{"class":226},[57,1948,1549],{"class":63},[57,1950,1838],{"class":226},[57,1952,1691],{"class":63},[57,1954,1956],{"class":59,"line":1955},57,[57,1957,264],{"class":63},[57,1959,1961],{"class":59,"line":1960},58,[57,1962,182],{"emptyLinePlaceholder":181},[57,1964,1966,1969],{"class":59,"line":1965},59,[57,1967,1968],{"class":89},"  setIdle",[57,1970,744],{"class":63},[57,1972,1974,1976,1978,1980,1982,1984,1986,1988],{"class":59,"line":1973},60,[57,1975,1559],{"class":226},[57,1977,1549],{"class":63},[57,1979,1868],{"class":89},[57,1981,1364],{"class":63},[57,1983,1683],{"class":226},[57,1985,1549],{"class":63},[57,1987,1552],{"class":226},[57,1989,1691],{"class":63},[57,1991,1993],{"class":59,"line":1992},61,[57,1994,264],{"class":63},[57,1996,1998],{"class":59,"line":1997},62,[57,1999,182],{"emptyLinePlaceholder":181},[57,2001,2003,2006],{"class":59,"line":2002},63,[57,2004,2005],{"class":89},"  toggle",[57,2007,744],{"class":63},[57,2009,2011,2013,2015,2017,2019,2021,2023,2025,2027,2029,2031,2034,2036,2038,2040,2043,2045,2047,2049],{"class":59,"line":2010},64,[57,2012,1559],{"class":226},[57,2014,1549],{"class":63},[57,2016,1868],{"class":89},[57,2018,1364],{"class":63},[57,2020,1367],{"class":226},[57,2022,1259],{"class":63},[57,2024,1387],{"class":198},[57,2026,1465],{"class":226},[57,2028,1549],{"class":63},[57,2030,1552],{"class":226},[57,2032,2033],{"class":198}," ?",[57,2035,1465],{"class":226},[57,2037,1549],{"class":63},[57,2039,1688],{"class":226},[57,2041,2042],{"class":198}," :",[57,2044,1465],{"class":226},[57,2046,1549],{"class":63},[57,2048,1552],{"class":226},[57,2050,1691],{"class":63},[57,2052,2054],{"class":59,"line":2053},65,[57,2055,264],{"class":63},[57,2057,2059],{"class":59,"line":2058},66,[57,2060,182],{"emptyLinePlaceholder":181},[57,2062,2064,2067],{"class":59,"line":2063},67,[57,2065,2066],{"class":89},"  toString",[57,2068,744],{"class":63},[57,2070,2072,2074,2076,2078,2081],{"class":59,"line":2071},68,[57,2073,1586],{"class":198},[57,2075,1589],{"class":226},[57,2077,1549],{"class":63},[57,2079,2080],{"class":89},"get",[57,2082,2083],{"class":63},"();\n",[57,2085,2087],{"class":59,"line":2086},69,[57,2088,264],{"class":63},[57,2090,2092],{"class":59,"line":2091},70,[57,2093,182],{"emptyLinePlaceholder":181},[57,2095,2097,2100],{"class":59,"line":2096},71,[57,2098,2099],{"class":89},"  valueOf",[57,2101,744],{"class":63},[57,2103,2105,2107,2109,2111,2113],{"class":59,"line":2104},72,[57,2106,1586],{"class":198},[57,2108,1589],{"class":226},[57,2110,1549],{"class":63},[57,2112,2080],{"class":89},[57,2114,2083],{"class":63},[57,2116,2118],{"class":59,"line":2117},73,[57,2119,264],{"class":63},[57,2121,2123],{"class":59,"line":2122},74,[57,2124,2125],{"class":63},"}\n",[10,2127,2128,2129,2131,2132,2134],{},"The class is pretty straightforward, there is no complicated logic, just simple ",[20,2130,1868],{}," and ",[20,2133,2080],{}," methods for all of the states we can have. Let's now integrate this class in our simple form example:",[48,2136,2138],{"className":50,"code":2137,"language":52,"meta":53,"style":53},"\u002F\u002F button-wrap.vue\n\u003Ctemplate>\n  \u003Cbutton v-bind=\"$attrs\" v-on=\"$listeners\" :disabled=\"status.isLoading()\"\n  :class=\"{'is-valid': status.isCompleted(), 'is-rejected': status.isRejected()}\">\n    \u003Cspan v-if=\"status.isLoading()\">Loading ...\u003C\u002Fspan>\n    \u003Cslot v-else-if=\"status.isIdle() || status.isCompleted()\">\u003C\u002Fslot>\n  \u003C\u002Fbutton>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\n  import Status from '~\u002Fclasses\u002FStatus';\n\n  export default {\n    props: {\n      status: {\n        required: false,\n        default: () => new Status(),\n        type: Object,\n      }\n    }\n  }\n\u003C\u002Fscript>\n",[20,2139,2140,2144,2152,2177,2189,2208,2227,2235,2243,2247,2255,2271,2275,2283,2287,2291,2299,2316,2321,2325,2329,2333],{"__ignoreMap":53},[57,2141,2142],{"class":59,"line":60},[57,2143,64],{"class":63},[57,2145,2146,2148,2150],{"class":59,"line":67},[57,2147,70],{"class":63},[57,2149,74],{"class":73},[57,2151,77],{"class":63},[57,2153,2154,2156,2158,2160,2162,2164,2166,2168,2170,2172,2174],{"class":59,"line":80},[57,2155,83],{"class":63},[57,2157,86],{"class":73},[57,2159,90],{"class":89},[57,2161,93],{"class":63},[57,2163,97],{"class":96},[57,2165,100],{"class":89},[57,2167,93],{"class":63},[57,2169,105],{"class":96},[57,2171,108],{"class":89},[57,2173,93],{"class":63},[57,2175,2176],{"class":96},"\"status.isLoading()\"\n",[57,2178,2179,2182,2184,2187],{"class":59,"line":118},[57,2180,2181],{"class":89},"  :class",[57,2183,93],{"class":63},[57,2185,2186],{"class":96},"\"{'is-valid': status.isCompleted(), 'is-rejected': status.isRejected()}\"",[57,2188,77],{"class":63},[57,2190,2191,2193,2195,2197,2199,2202,2204,2206],{"class":59,"line":140},[57,2192,121],{"class":63},[57,2194,57],{"class":73},[57,2196,126],{"class":89},[57,2198,93],{"class":63},[57,2200,2201],{"class":96},"\"status.isLoading()\"",[57,2203,133],{"class":63},[57,2205,57],{"class":73},[57,2207,77],{"class":63},[57,2209,2210,2212,2214,2216,2218,2221,2223,2225],{"class":59,"line":158},[57,2211,121],{"class":63},[57,2213,145],{"class":73},[57,2215,381],{"class":89},[57,2217,93],{"class":63},[57,2219,2220],{"class":96},"\"status.isIdle() || status.isCompleted()\"",[57,2222,151],{"class":63},[57,2224,145],{"class":73},[57,2226,77],{"class":63},[57,2228,2229,2231,2233],{"class":59,"line":168},[57,2230,161],{"class":63},[57,2232,86],{"class":73},[57,2234,77],{"class":63},[57,2236,2237,2239,2241],{"class":59,"line":178},[57,2238,171],{"class":63},[57,2240,74],{"class":73},[57,2242,77],{"class":63},[57,2244,2245],{"class":59,"line":185},[57,2246,182],{"emptyLinePlaceholder":181},[57,2248,2249,2251,2253],{"class":59,"line":195},[57,2250,70],{"class":63},[57,2252,190],{"class":73},[57,2254,77],{"class":63},[57,2256,2257,2260,2263,2266,2269],{"class":59,"line":208},[57,2258,2259],{"class":198},"  import",[57,2261,2262],{"class":63}," Status ",[57,2264,2265],{"class":198},"from",[57,2267,2268],{"class":96}," '~\u002Fclasses\u002FStatus'",[57,2270,760],{"class":63},[57,2272,2273],{"class":59,"line":214},[57,2274,182],{"emptyLinePlaceholder":181},[57,2276,2277,2279,2281],{"class":59,"line":220},[57,2278,199],{"class":198},[57,2280,202],{"class":198},[57,2282,205],{"class":63},[57,2284,2285],{"class":59,"line":233},[57,2286,211],{"class":63},[57,2288,2289],{"class":59,"line":243},[57,2290,691],{"class":63},[57,2292,2293,2295,2297],{"class":59,"line":249},[57,2294,223],{"class":63},[57,2296,227],{"class":226},[57,2298,230],{"class":63},[57,2300,2301,2304,2306,2308,2311,2313],{"class":59,"line":255},[57,2302,2303],{"class":89},"        default",[57,2305,680],{"class":63},[57,2307,683],{"class":198},[57,2309,2310],{"class":198}," new",[57,2312,1531],{"class":89},[57,2314,2315],{"class":63},"(),\n",[57,2317,2318],{"class":59,"line":261},[57,2319,2320],{"class":63},"        type: Object,\n",[57,2322,2323],{"class":59,"line":267},[57,2324,252],{"class":63},[57,2326,2327],{"class":59,"line":470},[57,2328,258],{"class":63},[57,2330,2331],{"class":59,"line":479},[57,2332,264],{"class":63},[57,2334,2335,2337,2339],{"class":59,"line":488},[57,2336,171],{"class":63},[57,2338,190],{"class":73},[57,2340,77],{"class":63},[48,2342,2344],{"className":50,"code":2343,"language":52,"meta":53,"style":53},"\u002F\u002Fform.vue\n\u003Ctemplate>\n  \u003Cform @submit.prevent=\"onSubmit\">\n  \u002F\u002F\n  \u003Cbutton-wrap :status=\"status\">\n    Submit\n  \u003C\u002Fbutton-wrap>\n  \u003C\u002Fform>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\nimport Status from '~\u002Fclasses\u002FStatus';\n\nexport default {\n  data: () => ({\n    status: new Status()\n  }),\n\n  methods: {\n    onSubmit() {\n      this.status.toggle();\n\n      axios.post(url, data)\n        .then((response) => {\n          this.status.setCompleted();\n        })\n        .catch((error) => {\n          this.status.setRejected();\n        });\n        .finally(() => {\n          if(this.status.isNotRejected()) {\n            this.status.toggle();\n          }\n        }\n    }\n  }\n}\n\u003C\u002Fscript>\n",[20,2345,2346,2350,2358,2372,2376,2390,2394,2402,2410,2418,2422,2430,2443,2447,2455,2466,2479,2484,2488,2493,2500,2513,2517,2526,2543,2555,2560,2576,2587,2592,2604,2621,2631,2635,2640,2644,2648,2652],{"__ignoreMap":53},[57,2347,2348],{"class":59,"line":60},[57,2349,557],{"class":63},[57,2351,2352,2354,2356],{"class":59,"line":67},[57,2353,70],{"class":63},[57,2355,74],{"class":73},[57,2357,77],{"class":63},[57,2359,2360,2362,2364,2366,2368,2370],{"class":59,"line":80},[57,2361,83],{"class":63},[57,2363,572],{"class":73},[57,2365,575],{"class":89},[57,2367,93],{"class":63},[57,2369,580],{"class":96},[57,2371,77],{"class":63},[57,2373,2374],{"class":59,"line":118},[57,2375,587],{"class":63},[57,2377,2378,2380,2382,2384,2386,2388],{"class":59,"line":140},[57,2379,83],{"class":63},[57,2381,279],{"class":73},[57,2383,1161],{"class":89},[57,2385,93],{"class":63},[57,2387,1166],{"class":96},[57,2389,77],{"class":63},[57,2391,2392],{"class":59,"line":158},[57,2393,628],{"class":63},[57,2395,2396,2398,2400],{"class":59,"line":168},[57,2397,161],{"class":63},[57,2399,279],{"class":73},[57,2401,77],{"class":63},[57,2403,2404,2406,2408],{"class":59,"line":178},[57,2405,161],{"class":63},[57,2407,572],{"class":73},[57,2409,77],{"class":63},[57,2411,2412,2414,2416],{"class":59,"line":185},[57,2413,171],{"class":63},[57,2415,74],{"class":73},[57,2417,77],{"class":63},[57,2419,2420],{"class":59,"line":195},[57,2421,182],{"emptyLinePlaceholder":181},[57,2423,2424,2426,2428],{"class":59,"line":208},[57,2425,70],{"class":63},[57,2427,190],{"class":73},[57,2429,77],{"class":63},[57,2431,2432,2435,2437,2439,2441],{"class":59,"line":214},[57,2433,2434],{"class":198},"import",[57,2436,2262],{"class":63},[57,2438,2265],{"class":198},[57,2440,2268],{"class":96},[57,2442,760],{"class":63},[57,2444,2445],{"class":59,"line":220},[57,2446,182],{"emptyLinePlaceholder":181},[57,2448,2449,2451,2453],{"class":59,"line":233},[57,2450,1459],{"class":198},[57,2452,202],{"class":198},[57,2454,205],{"class":63},[57,2456,2457,2460,2462,2464],{"class":59,"line":243},[57,2458,2459],{"class":89},"  data",[57,2461,680],{"class":63},[57,2463,683],{"class":198},[57,2465,686],{"class":63},[57,2467,2468,2471,2474,2476],{"class":59,"line":249},[57,2469,2470],{"class":63},"    status: ",[57,2472,2473],{"class":198},"new",[57,2475,1531],{"class":89},[57,2477,2478],{"class":63},"()\n",[57,2480,2481],{"class":59,"line":255},[57,2482,2483],{"class":63},"  }),\n",[57,2485,2486],{"class":59,"line":261},[57,2487,182],{"emptyLinePlaceholder":181},[57,2489,2490],{"class":59,"line":267},[57,2491,2492],{"class":63},"  methods: {\n",[57,2494,2495,2498],{"class":59,"line":470},[57,2496,2497],{"class":89},"    onSubmit",[57,2499,744],{"class":63},[57,2501,2502,2505,2508,2511],{"class":59,"line":479},[57,2503,2504],{"class":226},"      this",[57,2506,2507],{"class":63},".status.",[57,2509,2510],{"class":89},"toggle",[57,2512,2083],{"class":63},[57,2514,2515],{"class":59,"line":488},[57,2516,182],{"emptyLinePlaceholder":181},[57,2518,2519,2522,2524],{"class":59,"line":493},[57,2520,2521],{"class":63},"      axios.",[57,2523,772],{"class":89},[57,2525,775],{"class":63},[57,2527,2528,2531,2533,2535,2537,2539,2541],{"class":59,"line":498},[57,2529,2530],{"class":63},"        .",[57,2532,783],{"class":89},[57,2534,786],{"class":63},[57,2536,790],{"class":789},[57,2538,793],{"class":63},[57,2540,683],{"class":198},[57,2542,205],{"class":63},[57,2544,2545,2548,2550,2553],{"class":59,"line":503},[57,2546,2547],{"class":226},"          this",[57,2549,2507],{"class":63},[57,2551,2552],{"class":89},"setCompleted",[57,2554,2083],{"class":63},[57,2556,2557],{"class":59,"line":512},[57,2558,2559],{"class":63},"        })\n",[57,2561,2562,2564,2566,2568,2570,2572,2574],{"class":59,"line":521},[57,2563,2530],{"class":63},[57,2565,823],{"class":89},[57,2567,786],{"class":63},[57,2569,828],{"class":789},[57,2571,793],{"class":63},[57,2573,683],{"class":198},[57,2575,205],{"class":63},[57,2577,2578,2580,2582,2585],{"class":59,"line":526},[57,2579,2547],{"class":226},[57,2581,2507],{"class":63},[57,2583,2584],{"class":89},"setRejected",[57,2586,2083],{"class":63},[57,2588,2589],{"class":59,"line":531},[57,2590,2591],{"class":63},"        });\n",[57,2593,2594,2596,2598,2600,2602],{"class":59,"line":536},[57,2595,2530],{"class":63},[57,2597,862],{"class":89},[57,2599,865],{"class":63},[57,2601,683],{"class":198},[57,2603,205],{"class":63},[57,2605,2606,2609,2611,2613,2615,2618],{"class":59,"line":541},[57,2607,2608],{"class":198},"          if",[57,2610,1364],{"class":63},[57,2612,1367],{"class":226},[57,2614,2507],{"class":63},[57,2616,2617],{"class":89},"isNotRejected",[57,2619,2620],{"class":63},"()) {\n",[57,2622,2623,2625,2627,2629],{"class":59,"line":837},[57,2624,802],{"class":226},[57,2626,2507],{"class":63},[57,2628,2510],{"class":89},[57,2630,2083],{"class":63},[57,2632,2633],{"class":59,"line":851},[57,2634,889],{"class":63},[57,2636,2637],{"class":59,"line":857},[57,2638,2639],{"class":63},"        }\n",[57,2641,2642],{"class":59,"line":872},[57,2643,258],{"class":63},[57,2645,2646],{"class":59,"line":886},[57,2647,264],{"class":63},[57,2649,2650],{"class":59,"line":892},[57,2651,2125],{"class":63},[57,2653,2654,2656,2658],{"class":59,"line":897},[57,2655,171],{"class":198},[57,2657,190],{"class":63},[57,2659,77],{"class":198},[10,2661,2662,2663,2667,2668,2670],{},"If you are a ",[2664,2665,2666],"em",{},"clean code"," freak like me, this code looks pretty dope. Now, you can use the ",[20,2669,37],{}," class anywhere and for different cases like fetching data from an API, submitting a form, toggling sates based on user actions, showing UI skeletons while prefetching data, etc.",[2672,2673],"hr",{},[10,2675,2676,2677,2681,2682,2689],{},"You can also use HOC (High order components) to abstract the state logic and use that within your components, but eventually, it boils down to the first\u002Fsecond scenario that I told you about in this post. This approach is framework agnostic, meaning that you can also use it in your React apps. You can always use a ",[2678,2679,2680],"strong",{},"state machine"," like ",[2683,2684,2688],"a",{"href":2685,"rel":2686},"https:\u002F\u002Fxstate.js.org\u002F",[2687],"nofollow","xstate"," but for simple logic, I find my approach way easier and more convenient that importing a whole new library. Thanks for reading. I will update this series with another post soon.",[2691,2692,2693],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":53,"searchDepth":67,"depth":67,"links":2695},[2696,2697,2698],{"id":42,"depth":80,"text":43},{"id":919,"depth":80,"text":920},{"id":1433,"depth":80,"text":1434},"JavaScript","2020\u002F05\u002F09",null,"md","\u002Fimages\u002Fis-loading.png","vue, vue.js, react, status, state, component state, state booleans, is loading, loading, loading boolean",{},"\u002Fblog\u002Fhandling-different-component-states-with-a-status-class","☕️ 7 min read",{"title":5,"description":12},"handling-different-component-states-with-a-status-class","blog\u002Fhandling-different-component-states-with-a-status-class","vue components, advanced vue, vue, javascript","d7m_uAebX5iydSEVSgOef0iK1chHy05HUBpeQPEieNg",1774945272381]