I'm discovering VueJS and I don't understand exactly the differences between updated and watchers.
Updated hook
It is a lifecycle hook. According to the official documentation, it is triggered whenever data changes. So whenever a prop or a data is updated (the value, not only the pointer), updated is called.
Watchers
In the documentation, watchers are compared to computed properties. But in which cases would it be best to use updated instead of watchers ?
It seems that in both cases, DOM is not updated when the callback is called (nextTick() is required if we want to manipulate the changes in the DOM). The only difference I see is that watchers are only triggered when one precise property (or data) is updated where updated is always called.
I can't figure out what are the pros of updating whenever a data changes (updating) if we can be more accurate (watchers).
Here are my thoughts.
Thanks :)
The lifecycle hooks around update respond to changes in the DOM. Watchers respond to changes in the data. DOM changes are generally in response to data changes, but they might not be data owned by the component in question. One example where updated could be used is noticing that slot content has updated.
I think a better analogous lifecycle hook to the watchers may be the beforeUpdate hook. The updated hook is called after the virtual DOM has re-rendered, whereas beforeUpdate is called before the virtual DOM has re-rendered. You can see a visual representation of this on the diagram you linked to.
in which cases would it be best to use updated instead of watchers ? (...) I can't figure out what are the pros of updating whenever a data changes (updated) if we can be more accurate (watch).
The documentation says that you should prefer a watcher or computed property instead of updated if it is possible to achieve your goal that way. My understanding is that the updated hook was included to allow users to watch for any changes to the virtual DOM (see below).
Here's the explanation from the Vue 2.0 release notes on watch vs. updated:
User watchers created via vm.$watch are now fired before the associated component re-renders. This gives the user a chance to further update other state before the component re-render, thus avoiding unnecessary updates. For example, you can watch a component prop and update the component's own data when the prop changes.
To do something with the DOM after component updates, just use the updated lifecycle hook.
Related
Im actually learning Vue3.
It seems generally very clear to me.
But one thing is not clear at all.
The differecens between watch and beforeUpdate.
There are differences between this two?
And if yes, when is preferred use one rather than another?
Yes there are many differences. Watch observes only changes in the reactive data passed as the first argument, so it only operates after the monitored properties have changed. As for beforeUpdate , it is a life cycle that is called before the DOM is changed due to reactive data changes in the component, So it observes any reactive data in the component.
i think watch will triggerd after changing the data but beforeUpgrade is a hook and will look at the DOM for runnig something
With beforeUpdate you can listen to any change in the component. It will be called if any of the reactive elements change that is used in rendering the component.
With watch you can listen to specific reactive elements, even if they are not used in rendering the component.
I am using componentWillReceiveProps in many places in my application. Now, I have to replace them with either getDerivedStateFromProps() or componentDidUpdate(). First I thought of using getDerivedStateFromProps as it s alternative of componentWillReceiveProps as suggested react-native docs. But some people are highly recommending not to use this method, Instead suggesting to use componentDidUpdate. But for my requirement all new props must be set with the state before render. getDerivedStateFromProps is the best place to do so.
Hence, which one to use between getDerivedStateFromProps and componentDidUpdate?
From the React docs
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
getDerivedStateFromProps is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.
Deriving state leads to verbose code and makes your components
difficult to think about.
Make sure you’re familiar with simpler alternatives:
If you need to perform a side effect (for example, data fetching or an animation) in response to a change in props, use componentDidUpdate lifecycle instead.
If you want to re-compute some data only when a prop changes, use a memoization helper instead.
If you want to “reset” some state when a prop changes, consider either making a component fully controlled or fully uncontrolled with a key instead.
I'm losing track of reactivity overhead best practices in a Vue 2 Component. I need to generate a one time string with genId() and assign it to the component' id attribute. It seems like overkill to have any watching going on after that.
Is :id="myID" the right way to insert this into the html id?
And then when setting up the source where do I put the non-reactive data? I had 3 thoughts:
Add property myID: genId() to data. But doesn't that add it to the watchlist automatically even though it won't change? Causing overhead?
I read on Vue Forum from a year old answer that myID: genId() should go in the created hook. Are using hooks for this kind of thing a best practice? I thought hooks were discouraged.
Or I could put it in the component methods and then call it directly with :id="genId()
Is there a Vue way to do this?
Use method 2 for non-reactive data (and you use that component many many times on the page that the small overhead of adding the change listeners has any impact.)
created() {
this.myId = genId()
}
The 3 methods behave differently:
Method 1: data
This will call the genId() when the data object is created and add change listeners.
Method 2: created hook
This will call the genId() when the component object is created and doesn't add change listeners.
Method 3: method
This will call the genId() every time the template re-renders. Which happens every time a change is detected on a variable the view is listening to or a $forceUpdate() is called.
Ps. Vue objects already have a unique id: this._uid
but this is a private property and might change in a future version of Vue.
Let's say I have a <router-view> showing one component (A) and through a <router-link> this component will be replaced by another one (B).
Both components have their own beforeCreate and beforeDestroy hooks. I'd expect that if I navigated from A to B the sequence of events would be:
A.beforeDestroy
B.beforeCreate
But after doing some tests it appears to be the exact opposite: B.beforeCreate is always called before A.beforeDestroy.
Is that correct? And if it's correct, why is it this way? Doesn't make sense to me...
In my case all those hooks interact with some common data, so I'm facing race conditions here... Any suggestion on how to deal with that? I need to get some things done before creating B that cannot be started before destroying A...
Before the previous component is destroyed, the next component will be created first.
The purpose is obviously to avoid flickering as the view transitions from the previous component to the next component.
If the behavior you wanted is to make sure that a code should be executed always after the beforeDestroy and not before, you should use the mounted or beforeMount lifecycle hook.
I construct deep nested tree of parent and children Vue custom components using my top level component dynamically and then I am updating the data from which all tree is constructed. Which has an effect of rendering the entire tree (its a form with various custom components). I refresh/rebuild the whole form after fetching the data (which is what vue do for reactive data) that itself tell me how to regenerate the view (its like a JSON Schema from which I render the entire view).
This is related to my other issue here.
I am observing a very weird behavior in my Vue Application. When I destroy all my children components and rebuild the data to force rendering the form, it appears that even after I have called $destroy on every child component...Vue is not entirely removing them from cache?
Does vue remove the component from cache if a $destroy is called ?
Because I do not see multiple components of the same type in the Vue component list in the Chrome Vue DevTool extension panel. But I see that the same custom event is handled twice by the same component. Same function that handle the events is getting called twice even though there is only one component visible in Vue DevTools of this type.
This only happens after I render the form. When the page is loaded for the first time every thing works. Then after I reset the form by destroying the child component and resetting the data to re-render the form, magically this child component start handling the event twice.. and in 3rd render it handle the events thrice. But I see only one component in google chrome VueJS DevTool extension panel. So my guess is that vue is still keeping the previously destroyed component in cache. I am trying to figure out how should I destroy those components in the cache.
If anyone has observed something similar and found a solution please let me know.
At the moment I am going to dig little bit more on my component keys (this particular component does not have explicit key set by me).
First and foremost, the vue documentation states:
vm.$destroy
In normal use cases you shouldn’t have to call this method yourself.
Prefer controlling the lifecycle of child components in a data-driven
fashion using v-if and v-for.
So instead of destroying and rebuilding the components manually yourself, you should really letting vue handle that via v-if and v-for. If the components aren't updating to your changes, you might be dealing with a reactivity issue.
As you mentioned that this is a deeply nested structure, the reactivity is key to keeping the components up to data with the data.
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the Vue.set(object, key, value) method:
Vue.set(vm.someObject, 'b', 2)
Inside of a component:
this.$set(this.someObject, 'b', 2)
Also, keep in mind that Vue should be doing the heavy lifting in regards to component management, while you should define the parameters by which a component is rendered.