When Vue's reactivity bites you
And it's your own fault...
May 27 2020
I’ve been working with a client on a promising and meaningful application. The main feature is to visualize and keep track of crew, alarms and mustering situations on ships. Being the lead front end developer on the project, I voted for building the application using Vue.js. It’s the framework I tend to lean towards for data-driven web apps, and the company’s CTO was also positive about going the Vue road.
Most of the time Vue works as I expect it to, and I really like it’s conceptual model. But in a couple of cases things got weird. To be more specific, reactive data not reacting to changes, and views not updating as they should. In both cases I spent hours debugging, refactoring and finding more or less elegant solutions - only to hours later realize it was all because of a beginner mistake...
What I did wrong
The reason things got messed up was because I added a new property to an object after initialization. Like this:
obj.newProperty = "hello". Nothing wrong with that, right?
Actually, Vue doesn't like that at all. If newProperty doesn’t exist when the component initializes, Vue can’t keep track of changes to it.
The reason? Vue wraps state with getters and setters so it can observe changes to it. So when I declared new properties after initialization, Vue had no way of knowing about it.
How to do it right
To fix this we use a Vue-method called $set. To add the new property we would say
Vue.$set(obj, “newProperty”, “hello”)
One line of code. One small change. Easy, right? Yes, easy! It’s also easy to overlook and spend hours debugging. 🤣 Both times my reaction to this mistake has been a spicy mix of frustration and relief. Hours wasted on debugging (frustration), changing one line and voila! Everything works (relief). The life of a developer, I guess.
Lesson learned? When Vue’s reactivity system doesn’t behave like expected, there’s a 99% chance it’s your own fault. By the way, you can read more about how Vue’s reactivity system works here.