Common Mistakes in
(And, more importantly... how to avoid them)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10900659/pasted-from-clipboard.png)
ue.js
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/8969634/headshot.png)
Daniel Kelly
Lead Instructor @ Vue School
Full Stack developer (10 + years)
Husband and Father
presentation Icons from fontawesome.com
Why this topic
?
- We're all human and make mistakes
- Simple mistakes can cause big headaches
- Learn from the mistakes of others
- It's a very practical topic
Why this topic?
?
Mistake # 1
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
index as :key
<li
v-for="(item, index) in items"
:key="index"
>...</li>
What's wrong with this? 🤔
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
index as :key
<li
v-for="(item, index) in items"
:key="index"
>...</li>
What's wrong with this? 🤔
❌
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
index as :key
Bug Manifests Under 2 Conditions
- When the elements in the array change order
- When a nested element or component has it's own state
It's tricky!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10900830/pasted-from-clipboard.png)
Let's look at an example!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
index as :key
It's not just for loops!
Let's look at an example!
Mistake # 2
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Non-reactive value as dep
const cookiesAccepted = computed(()=>
localStorage.getItem("cookiesAccepted")
)
What's wrong with this? 🤔
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Non-reactive value as dep
const cookiesAccepted = computed(()=>
localStorage.getItem("cookiesAccepted")
)
What's wrong with this? 🤔
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Non-reactive value as dep
const cookiesAccepted = computed(()=>
localStorage.getItem("cookiesAccepted")
) // 0
localStorage.setItem("cookiesAccepted", 1)
cookiesAccepted.value // 0
Changing the value of local storage doesn't update the value of the computed prop.
const accepted = 0;
const cookiesAccepted = computed(()=> accepted)
This is more obvious
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Non-reactive value as dep
Often see this with browser API's:
- localStorage
- Date()
- DOM element properties
(like clientWidth, etc) - etc
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Non-reactive value as dep
And, of course, usually these hide in more complex computed props
(nothing as obvious as our simple example)
What's the solution?
🤔
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Reactive Deps
VueUse
VueUse
handy reactive wrapper around browser APIs
Let's look at an example!
Mistake # 3
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Replacing Reactive State
let posts = reactive([
'Post 1',
'Post 2'
]);
function loadMore(){
// fetch more posts, etc
posts = newPosts;
}
What's wrong
with this? 🤔
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Replacing Reactive State
let posts = reactive([
'Post 1',
'Post 2'
]);
function loadMore(){
// fetch more posts, etc
posts = newPosts;
}
What's wrong
with this? 🤔
👈 replacing reactive
kills reactivity
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Replacing Reactive State
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10900724/Screenshot_2023-11-07_at_4.01.48_PM.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10900724/Screenshot_2023-11-07_at_4.01.48_PM.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Replacing Reactive State
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10900724/Screenshot_2023-11-07_at_4.01.48_PM.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10900724/Screenshot_2023-11-07_at_4.01.48_PM.png)
Let's look at some examples!
Moral of the story:
just use ref() everywhere!
I'm not the only one,
it's the recommendation of the official Vue.js docs
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11152193/Screenshot_2024-02-27_at_2.04.44_PM.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11152194/Screenshot_2024-02-27_at_2.05.05_PM.png)
I'm not the only one,
it's the recommendation of the official Vue.js docs
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11152193/Screenshot_2024-02-27_at_2.04.44_PM.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11152194/Screenshot_2024-02-27_at_2.05.05_PM.png)
Oh and one more reason to use ref() everywhere
default watcher depth is different between ref() and reactive()
Let's see an example of that
Mistake # 4
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Mutating Props
<script setup lang="ts">
defineProps<{
modelValue: string;
}>();
</script>
<template>
<input id="username" v-model="modelValue" />
</template>
What's wrong with this? 🤔
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/9993532/vue-logo-border.png)
Mutating Props
<script setup lang="ts">
defineProps<{
modelValue: string;
}>();
</script>
<template>
<input id="username" v-model="modelValue" />
</template>
What's wrong with this? 🤔
Mutating a prop
Let's look at some examples!
Common Vue.js Mistakes and How to Avoid Them
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10847190/Screenshot_2023-10-18_at_11.03.37_AM.png)
🔥 Free
https://vueschool.io/courses/common-vue-js-mistakes-and-how-to-avoid-them
- Omitting the Key Directive on v-for
- Prop Drilling
- Watching Arrays the Wrong Way
- Replacing Reactive State the Wrong Way
- Unintentionally Mutating Props
- Forgetting to Clean Up Your Manual Event Listeners
- Expecting Changes to Non-Reactive Dependencies to Trigger Updates
- Not Considering TypeScript
- Destructuring Reactive Data
- Calling Composables in the Wrong Place
- Using v-html with User Provided Data
- Unnecessary Manual DOM Manipulation
👈
👈
👈
👈
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10900832/Screenshot_2023-11-07_at_3.14.27_PM.png)
But before I go!
certificates.dev
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11341037/Screenshot_2024-05-16_at_12.04.47_PM.png)
83% say the exam is moderate to difficult
74% say it actually helped improve their Vue.js skills
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11480168/CERT-Angular.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11480170/CERT-JavaScript.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11480173/CERT-Vue.js.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11480178/CERT-Vue.js.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11480179/CERT-Nuxt.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11480053/LDX-Logo.png)
Developer Experience
Your Path to a Dynamic and Engaging
certificates.dev
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11341041/Screenshot_2024-05-16_at_12.05.12_PM.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11341044/Screenshot_2024-05-16_at_12.07.06_PM.png)
frontendnation.com
60+
Speakers
vue.school/masterclass
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11154343/Screenshot_2024-02-28_at_9.26.12_AM.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11154345/Untitled__1_.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11077145/Screenshot_2024-01-25_at_9.34.41_AM.png)
Not just crappy multiple choice questions
👉 you gotta code to pass
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/6755879/vueschool_sticker_good.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/6755879/vueschool_sticker_good.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/6755879/vueschool_sticker_good.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/6755879/vueschool_sticker_good.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/9626963/stickers-1-01.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/6755879/vueschool_sticker_good.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/9626964/stickers-1-02.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/9626965/stickers-1-03.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/9626963/stickers-1-01.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/6755879/vueschool_sticker_good.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/9626964/stickers-1-02.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/636679/images/9626963/stickers-1-01.png)
Grab Some Swag 🤗
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11154364/TS_%2B_Vue.js-1.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11154369/VueUse_CheatSheet_-_Light.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11480160/c341092b-fa99-4c7c-b22a-f7df7d1366d3.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/11154419/tshirt.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10847236/pasted-from-clipboard.png)
danielkelly_io
I'll tweet out the slides and the codebase after this
![](https://s3.amazonaws.com/media-p.slid.es/uploads/1984687/images/10847253/x.png)
Thank you 🙏
Go code awesome things!
(with Vue 😉)
Common Mistakes in Vue.js and How to Avoid Them
By Daniel Kelly
Common Mistakes in Vue.js and How to Avoid Them
- 1,099