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

Async custom element does not inject value if it was moved before it was loaded #8127

Open
Truevoly opened this issue Apr 20, 2023 · 1 comment · May be fixed by #8132 or #9351
Open

Async custom element does not inject value if it was moved before it was loaded #8127

Truevoly opened this issue Apr 20, 2023 · 1 comment · May be fixed by #8132 or #9351

Comments

@Truevoly
Copy link

Vue version

3.2.47

Link to minimal reproduction

https://stackblitz.com/edit/vite-m1kzad?file=main.js

Steps to reproduce

  1. Open the page
  2. Wait for async component to resolve
  3. Validate that it renders provided value
  4. Uncomment setTimeout
  5. Validate that it renders default value

What is expected?

Both times provided value should be rendered

What is actually happening?

default value is rendered second time instead

System Info

No response

Any additional comments?

I was reading the source code for apiCustomElement.ts to better understand how provide/inject works in custom elements.
I've noticed that in _resolveDef method property _resolved is assigned to true before it is actually resolved. Since that property is queried in connectedCallback, I've wondered if I can move element before it is actually resolved, and that if that would force resolve method to run immediately. Sure enough it did.
However, this did not break rendering of the element, so it seems that render function handles different types of vnodes correctly (vnode.type returns different values, which probably also shouldn't be the case). But since internal Vue instance is created before definition was loaded, it does not know what values to provide

@Truevoly
Copy link
Author

Maybe something like this will work? Sorry, haven't tested this yet, just an idea.

apiCustomElement.ts

export class VueElement extends BaseClass {
  private _loading = false

  ...

  private _resolveDef() {
    if (this._loading) {
      return
    }
    this._loading = true

    ...

    const resolve = (def: InnerComponentDef, isAsync = false) => {      
      this._resolved = true
      this._loading = false
      const { props, styles } = def

      ...
    }
    ...
  }
}

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