Feb 02 2021 • 5 min read
The origin of this really simple state thing is a review comment about me finding a simpler way to show different views for the different states of an component.
Table of contents
One of my absolute favorite things about learning new programming languages is the new ways they cause you to think about approaching and solving problems. The way I thought about implementing this really simple state thing was borne of my delightful experience with enumerize (opens new window) and Ruby.
Enumerize goes on to do a bunch of neat things that makes your life easy like defining predicate methods that let you know if a particular state is the current state, preventing incorrect state etc.
Heavily inspired by enumerize I outlined what I wanted from my own implementation in Vue.
// mixins/reallysimplestatething.js
export default {
beforeCreate() {
const states = this.$options.states;
if (states) {
this.$options.computed = this.$options.computed || {};
states.forEach((state) => {
this.$options.computed[state] = function() {
return this.currentState == state;
};
});
}
},
data() {
const states = this.$options.states;
let stateData = {};
if (states) {
stateData = {
currentState: states[0],
};
}
return { ...stateData };
},
}
What's happening here:
beforeCreate
, I'm checking if the component being created has a states
options array defined.
data
, I'm setting up the reactive currentState
property that will be made accessible to the component. Setting the currentState
is where the magic happens. // Banks.vue
<template>
<div>
<Loader v-if="loading" />
<ul v-show="loaded">
<li v-for="bank in banks" :key="bank.id>
<p>{{bank.name}}</p>
</li>
</ul>
<Error v-if="error" message="errorMessage">
</div>
</template>
<script>
export default {
states: ["loading", "loaded", "error"],
data(){
return {
banks: [],
errorMessage: null,
};
},
methods: {
async getBanks(){
try{
const banks = await axios.get("/banks");
this.banks = response.data;
this.currentState = "loaded";
} catch(err){
this.currentState = "error";
this.errorMessage = err.response.data.errors[0].message;
}
}
},
created(){
this.getBanks();
}
}
</script>
What's happening here:
loading
loaded
error
states
options array and the really simple state thing will set the first entry as the default. In this case, loading
will be the state of the component until I transition away from it by setting currentState
to a new state.getBanks
, I'm transitioning to the loaded
state if I successfully get my list of banks or the error
state if I don't.In its current state (pun intended wink wink), the really simple state thing is very useful to me because it takes away the tedious recurrent chore of creating the predicate computed properties for my component's possible states and it does so with a delightful (to me) API. That said, there's quite a bit I can add to improve it and maybe I will do it and release it as a Vue plugin.
Hopefully this tutorial is useful to ya. Peace!