How to stop repeating code by using Vue Composition API in large dependent components - when you’re in over your head

Logan Van Wagoner
6 min readMar 5, 2021

What you’ll find here:
1. An okay-ish backstory
2. Help using vue3’s composition api with dependent components
3. Help figuring out if using it makes sense for your project

Let’s go from this:

Lots of code that has to be repeated in other components

To this:

No repeated code with composition api

I have found that web development frameworks do a wonderful job explaining a new basic concept in ideal circumstances. Why wouldn’t they?

But when it comes to development in the wild, I often find myself looking at very non-straightforward ideas, concepts, and needs. Less than ideal circumstances. But, a lot cooler.

Working with vue3’s composition API was the most recent time I’ve been in over my head… well apart from that general in over my head feeling computer science gives me daily. So, this article should hopefully help you take the next step.

For reference I am using vue2 in the project, just installed the composition api as instructed here.

I’m hoping today I can be this useful to you ⬅️

To me, the best part about composition api is the replacement of repeated code with references to one source, almost like pointers to functions. In the documentation you’ll find great examples on how to use it with some simple functions and variables that naturally point to a parent component. What about when you have functions that make up one piece of your site or app that have to be reused for other pages or apps?

In my case, it was a financial pricing tool that used information about a user to calculate their results. First with their data, then their plans, then the pricing. The plans and pricing depended on their data and the pricing depend on both their data and plans.

Structure of components

It used to have repeated code in 3 places to manage this (it could have every page depend on a single monolith of JavaScript as well).

It took me, a young developer, about a week to figure out how to implement this (I didn’t really understand modular building, and hadn’t done it before which was probably my biggest hiccup). So let’s work through an example and save you some time. Behold 🤩 below a fantastically made vue component’s script. 🥲

//mediumcomponent.vue
export default {
name: 'mediumcomponent',
data() {
return {
isSuperRepeated: '',
repeatedVariable: '',
isRepeated: ''
};
},
methods: {
VeryRepeatedFunction() {
if (this.isSuperRepeated) {
//do fun stuff
this.isRepeated = true;
return this.repeatedVariable;
}
},
OtherVeryQuotedFunction() {
if (this.isRepeated) {
console.log('here we go again');
}
}
},
computed: {
amIrepeating() {
if (true) {
return true;
}
}
},
watch: {
isRepeated() {
this.OtherVeryQuotedFunction();
}
},
mounted() {
this.VeryRepeatedFunction();
}
};

Beautiful right?

Let’s say that our project depends on ‘VeryRepeatedFunction’ and ‘OtherVeryQuotedFunction’ in several other files.

Here is code from the script of another file

//second.vue
export default {
name: 'mediumcomponenttwo',
data() {
return {
isSuperRepeated: '',
repeatedVariable: '',
isRepeated: '',
unique: ''
};
},
methods: {
VeryRepeatedFunction() {
if (this.isSuperRepeated) {
//do fun stuff
this.isRepeated = true;
return this.repeatedVariable;
}
},
OtherVeryQuotedFunction() {
if (this.isRepeated) {
console.log('here we go again');
}
},
UniqueFunction() {
console.log('isnt unique spelled weird?');
}
},
computed: {
amIrepeating() {
if (true) {
return true;
}
}
},
watch: {
isRepeated() {
this.OtherVeryQuotedFunction();
}
},
mounted() {
this.VeryRepeatedFunction();
this.UniqueFunction();
}
};

As you can see over 90% of this file is just repeat. In our team’s case we were repeating all the functions and calculations of a previous components, plus adding new ones for the new component.

Now, let’s improve this if we can. As the vue documentation outlines we transition to composition api. I like to do this by copying functionality to another file and rewriting it (if you have already written it, otherwise just writing it) in the vue composition way as follows.

//forMedium.js
import { ref } from '@vue/composition-api';
export default function GetRepeatedComposables() {
const isSuperRepeated = ref('');
const isRepeated = ref('');
const repeatedVariable = ref('');
const VeryRepeatedFunction = (() => {
if (isSuperRepeated.value) {
//do fun stuff
isRepeated.value = true;
return repeatedVariable.value;
}
})
const OtherVeryQuotedFunction = (() => {
if (isRepeated.value) {
console.log('here we go again');
}
})
return {
isSuperRepeated,
isRepeated,
repeatedVariable,
VeryRepeatedFunction,
OtherVeryQuotedFunction
}
}
“It’s all coming together” — Kronk

We then reference those repeated functions in the ‘setup’ of our two components.

//mediumcomponent.vue
import GetRepeatedComposables from 'forMedium.js';
export default {
name: 'mediumcomponent',
setup() {
const {
isSuperRepeated,
isRepeated,
repeatedVariable,
VeryRepeatedFunction,
OtherVeryQuotedFunction
} = GetRepeatedComposables();
return {
isSuperRepeated,
isRepeated,
repeatedVariable,
VeryRepeatedFunction,
OtherVeryQuotedFunction
}
},
data() {
return {
//nicely cleaned up
};
},
computed: {
amIrepeating() {
if (true) {
return true;
}
}
},
watch: {
isRepeated() {
this.OtherVeryQuotedFunction();
}
},
mounted() {
this.VeryRepeatedFunction();
}
};

After the first you may be thinking… wait, that’s just as much code. And you would be right.

I’ll talk about that later. First, let’s look at our second component.

//second.vue
import GetRepeatedComposables from 'forMedium.js';
export default {
name: 'mediumcomponenttwo',
setup() {
const {
isSuperRepeated,
isRepeated,
repeatedVariable,
VeryRepeatedFunction,
OtherVeryQuotedFunction
} = GetRepeatedComposables();
return {
isSuperRepeated,
isRepeated,
repeatedVariable,
VeryRepeatedFunction,
OtherVeryQuotedFunction
};
},
data() {
return {
unique: ''
};
},
methods: {
UniqueFunction() {
console.log('isnt unique spelled weird?');
}
},
computed: {
amIrepeating() {
if (true) {
return true;
}
}
},
watch: {
isRepeated() {
this.OtherVeryQuotedFunction();
}
},
mounted() {
this.VeryRepeatedFunction();
this.UniqueFunction();
}
};

That same code referenced here means that we are using one source of truth for our code. An update to the file ‘forMedium.js’ is felt in both of these components and thus the maintainability just jumped up and the ease of improvements did too. I of course noticed an exponential increase going from making changes in three spots to making changes in one very easy to find spot.

As you read the docs you’ll see you can also handle mounted, watch, and computed values with setup and composition api.

That should be enough to help you get started if you want to go down the path of composition api use for your project. Good luck!

If you’re still here, you may be trying to decide if composition api makes sense in your project or if you should rethink your structure more entirely to avoid dealing with large components depending on each other. Maybe you can, each project is different.

Deciding on whether or not to use vue’s composition api comes with some trade offs to consider. Doesn’t almost everything?

Consider this brief list of my experience with composition api’s strengths and weaknesses.

Best for:

  • Projects repeating code often
  • Larger projects for organization
  • Prior experience using it (removes the large learning curve)
  • Teams/user that prefer it

Struggles with:

  • Large lists of references in set up function
  • Quick projects/prototypes since it’s more advance
  • A beginner to front end work since their is a lot to understand and the use is complex (big learning curve)

Next to consider is this: whether or not you prefer it, some projects are going to be best maintained using something like this. It’s simply one of the best options.

For our team, the pricing tool concept was developed by someone we contracted with, and the calculations depended on the previous components calculations. Really, there wasn’t much of a restructuring option without major rewrites to our DB. That would have been fine, but the planned replacement of hand entered info with calls to company apis makes this idea much less helpful.

You might be in a similar situation and what you intend to build requires large form components with lots of repeated code. If that’s the case and your working in vue, the composition api could be your best choice!

A farewell war cry

Since implementing it for the first time, I’ve really enjoyed its use and the ease of maintaining or improving the system! Feel free to reach out if you want to talk use cases from someone who made the jump.

--

--