Skip to content
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

'too much recursion' hit when injecting Vue-based mixins #6190

Closed
razvyc opened this issue Jul 21, 2017 · 12 comments
Closed

'too much recursion' hit when injecting Vue-based mixins #6190

razvyc opened this issue Jul 21, 2017 · 12 comments

Comments

@razvyc
Copy link

razvyc commented Jul 21, 2017

Version

2.4.1

Reproduction link

https://jsfiddle.net/razvansbsb/2z359v28/

Steps to reproduce

  1. Define a component A that uses 2 mixins that each define their own provide properties wrapped in a Vue component, e.g. foo and bar.
  2. Define a component B inside A that uses inject to add foo and bar properties

What is expected?

Both foo and bar should be available in component B.

What is actually happening?

Get 'too much recursion' exception

@posva
Copy link
Member

posva commented Jul 22, 2017

You have to return plain objects in provide: https://jsfiddle.net/posva/nvbyv9wc/
I recommend you taking a look to provide inject: https://vuejs.org/v2/api/#provide-inject

@posva posva closed this as completed Jul 22, 2017
@razvyc
Copy link
Author

razvyc commented Jul 24, 2017

This used to work in 2.3.4. It stopped working in 2.4.0.
The problem occurs when trying to recursively merge the objects in mergeData. Can we add some smarts and if you detect a Vue object only clone the data properties?
Thanks!

@jasonsanjose
Copy link

@posva what's the meaning behind this note here https://vuejs.org/v2/api/#provide-inject:

Note: the provide and inject bindings are NOT reactive. This is intentional. However, if you pass down an observed object, properties on that object do remain reactive.

I took this to mean that reactive objects were not the default behavior but could be used if implemented.

@posva
Copy link
Member

posva commented Jul 24, 2017

@jasonsanjose It means that if you pass down objects that are being observed the injected properties can become reactive: https://jsfiddle.net/4yycfnfm/

@jasonsanjose
Copy link

@posva thanks for the clarification. We'll give that a try.

@aeharding
Copy link

aeharding commented Jul 27, 2017

I would also like to chime in that I received this issue trying to upgrade to 2.4.x. The regression from 2.3.x with an unhelpful error message made it really hard to track down.

I was also not doing anything weird, just copy-pasting this mixin from the vue-hackernews-2.0 project:
https://github.com/vuejs/vue-hackernews-2.0/blob/master/src/util/title.js

EDIT: Created vuejs/vue-hackernews-2.0#230

@xiechao1211
Copy link

i use the element-ui's el-upload compoent with vee-validate, it happens
wrong info is:Maximum call stack size exceeded at mergeData,so now ,what that i can do.

@jasonsanjose
Copy link

jasonsanjose commented Aug 8, 2017

@posva we're still looking for a solution. If you have time to chime in we would really appreciate it. If not, hopefully someone else here might have some ideas or at least be in the same situation.

Here's my updated example based on your last fiddle: https://jsfiddle.net/jason_sanjose/vzpmtcz2/2/. I added 2 grandchildren GrandChild1 references the injected bar directly, GrandChild2 references a computed property based on the injected bar.

Our goal is to mixin properties into a component tree and let them be inherited in some specific way. Here's a contrived example:

Let's say we're building a library of form components that can be nested. We want to mixin disabled state into all our form components and we also want that state to propagate down a sub tree.

<MegaForm> // disabled=false (default)
  <OtherForm disabled="true">
    <SubForm> // desired behavior: "inherits" disabled=true

For example, say MegaForm has some property that requires OtherForm and it's subtree to become disabled. We want SubForm to be able to get a reactive update when OtherForm disabled changes.

@posva
Copy link
Member

posva commented Aug 8, 2017

@jasonsanjose it's the same problem, the injected computed-stuff at Child is not reactive because it's a whole new object every time. It's the same as setting this.bar = { stuff: 'Completely new object' } (https://jsfiddle.net/uy757cu8/) at the root
I really think you're twisting this feature too much 😅 . It looks like you need a way of sharing state between components, but inject/provide is not meant for that

@jasonsanjose
Copy link

@posva Thanks for the feedback. We found a "creative" solution: https://jsfiddle.net/jason_sanjose/yc398k68/2/.

It involves some watchers on injected properties and a bit of indirection. It's not pretty nor easy to follow but it seems to work in 2.4.2. Hopefully we're still playing within the rules or at least not going to trip over any future behavior changes.

@jasonsanjose
Copy link

Here's a better example with cascading breadcrumbs: https://jsfiddle.net/jason_sanjose/sonurrof/2/

@SomeoneIsWorking
Copy link

I still have this problem. mergeData infinitely recurses with empty objects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants