I am getting my head round the different ways of communicating between components and their children, grandchildren, etc., and have been taking a look at provide/inject for the first time. I can get this to work fine without being reactive (which I know is the way it is designed), but cannot get reactive behaviour using an observed object. Let's say I have a nested object structure, A > B > C, where A is the grandparent of C. I have a data property of A, 'page', changes to which I would like to observe in grandchild C. If I just provide 'page' in A and inject 'page' in C, it's not reactive (by design). I thought if I did something like this instead it might work:
In provider:
data() {
return {
page: null,
obj:{currentPage:this.page}
}
},
provide(){
return {
obj: this.obj
}
}
In child or grandchild:
inject: ['obj']
But it doesn't. If I try to use obj.currentPage in the grandchild component, it is undefined.
I'm sure this is pretty straightforward. What am I not getting?
Using the data() function The first technique is to make the object reactive by initializing it in our data() function: export default { provide() { return { reactive: this. reactive }; }, data() { return { reactive: { value: "Hello there" } }; } }; Any object that is initialized here will be made reactive by Vue.
We also need to use the provide() notation if we are giving any per-instance state - i.e. where the data is coming from the data() function. Now that we've provided data, it can be accessed in any child component at any level by using the inject function.
I spent a lot of time, trying to make provided/injected object reactive, and after all it was eureka! We can simply pass a function returning an object, not an object themself.
It seems as a good solution to me.
Provider:
data(){
return {
something: ...,
}
}
provide(){
return {
getSomething: () => this.something,
}
}
Descedant component:
inject: ['getSomething'],
computed: {
something(){
return this.getSomething();
}
}
So, in descedant component, computed property this.something
became reactive.
Well, as ever the answer turned out to be in a completely different place from where I was looking. There is nothing wrong with the reactivity of the 'obj' object being provided. The problem lies in the fact that the object is not being updated in the parent data object. I had obj:{currentPage:this.page}
assuming that when this.page
changes, the property within obj
would be updated, but it isn't. So I have two options here, unless I've missed something: firstly, use a watch
on page
, updating the obj
property; or forget about this.page
altogether and make sure any updates which were hitherto done to this.page
are instead done to this.obj.currentPage
. It's just a case of deciding which approach is the less messy. All part of an interesting learning exercise.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With