-
Notifications
You must be signed in to change notification settings - Fork 35
Deep watchers create infinite recursion #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi, If everything works fine with the I'm not quite sure about your use case though. Are you setting the value of a prop to a |
Thanks for the response. I've been trying to get a minimal repro working, but it's actually not happening. I had the same question as you, about setting the value of a prop to a VueType, but it looks like for some reason, If I can find a full repro, I'll get back to you. |
OK, I've determined what is happening here. It looks like a "not technically a bug" on our end, but definitely "bad behaviour" coupled with this "maybe-a-bug" on your end. It turns out that we are passing components as props, in some cases. This is very useful for abstract components, and so on. However, it gets weird because we have a prop which is a (poorly defined) object which includes a component as well as other data. At some point deep in the chain we add a deep watcher on the object that has a component on it. If that component has a VueType, the infinite recursion happens. Obviously we shouldn't be deep watching that arbitrary object, but just watching the data we actually care about, so I'll see about making that fix in our code. You can see it happening here: https://codepen.io/dougalg/pen/vYYjxjz?editors=1010 That said, I still feel like this might be worth fixing in the shim file as well? Of course, not sure about the impact on file size it will have. |
Thank you for the detailed explanation. Ok, I understand your point. I agree with you that maybe deep-watching an object containing a component definition is not the best choice performance-wise. I also agree that since using the real library does not raise the issue I need to fix the shim to solve that inconsistency. I don't think the impact on the code will be too big. I didn't consider a use case like yours in the first place so I kept it at the minimum since Vue does not perform prop validation in production (at least not like in production). In the meantime, there might be a couple of options to fix the problem:
const abstractComponent = {
template: `<p>aaa</p>`,
props: Object.freeze({
text: VueTypes.string.def('hello'),
}),
};
computed: {
complexProp() {
return {
component: () => abstractComponent,
text: 'wow'
};
},
},
// and
template: `
<component
:is="complexProp.component()"
:text="complexProp.text"
/>
`, I'll keep you updated on the release of a fix. |
That's great. Thanks a lot! We already have a temporary fix by removing VueTypes in the broken component. I'm looking into making the deep watcher simpler and more efficient and removing the watch on the internal component completely. As you said, there's no way that it's good for performance! |
Hi, I published a beta version with a fix:
When you have time, could you check if it solves the issue? |
This fixes the issue we were seeing! Thank you for the responsiveness :) |
Cool! Published as Feel free to re-open this issue if you encounter this bug again. |
When using the shim, if you have a deep watcher on a prop that is defined as a
VueTypes.*
it creates an infinite loop. This is because Vue attempts to look upisRequired
which is a getter that returnsthis
. Ifdeep: true
is set on the watcher, then it attempts to look at the value returned fromisRequired
which is the parent object, so it recurses infinitely.I think the simplest way to resolve this bug is, unfortunately, a breaking change. Change
.isRequired
to.isRequired()
. This way it will return a function, rather thanthis
when it is accessed by Vue.The text was updated successfully, but these errors were encountered: