Subscribe on changes!

Using Suspense wrapped components prevents Template Ref's from being available during onMount in setup()

avatar
Aug 27th 2020

Version

3.0.0-rc.9

Reproduction link

https://codesandbox.io/s/vue-3-suspense-template-ref-onmount-issue-8diff?file=/src/App.vue

Steps to reproduce

Create a suspense wrapper for some components - including an async one - then try to access refs defined in the templates during onMounted. The ref will not be available either inside the component's own onMounted nor to it's parent if a ref is supplied to the component itself.

What is expected?

Same behaviour as without using Suspense - that the refs to the component, and inside the component, will be available during onMounted

What is actually happening?

The refs do not resolve until after onMounted and also do not "watch" correctly in respect to that (cannot be reliably used as a workaround).


I tried versions 3.1 -> 3.9

Ran into it developing an intersectionObserver lib for an aync component and the ref was not available until after onMounted although the lib worked fine before implementing Suspense. Removing the asyc component correctly fixes the ref's availability during onMounted therefore it is the use of Suspense causing the issue. Removing Suspense resolves the issue.

avatar
Aug 28th 2020
  1. The ref not being available in parent mounted is expected behavior. Suspense means its inner content may or may not be resolved when the parent component itself is considered "mounted". Or in other words, the parent's mounted hook is not going to wait for async child content (similar to how it won't wait for a child async component in v2).

  2. You can watch(componentRef, el => {}) in the parent. I just tested that and it works as expected. If you can't get that working, please open a new issue with the exact repro with the watch behavior.

avatar
Aug 30th 2020

Hi thanks for looking into this.

I understand the parent behavior and this makes perfect sense. However it is the ref inside the async component that I want to access (ie, in the component itself - not from it's parent)

After adding the watch command the issue remains in that the watch never resolves with the actual reference inside the asyc component.

I cannot seem to access the ref at onMounted nor using watch inside the async component, though it does resolve itself eventually - just without any way to catch it - the watch command does not seem to trigger. I have tried both ways of using watch (first param as func / named const).

See the child component (not the parent - as that acts exactly as you describe) and I have added the watch commands too and some pausing :

https://codesandbox.io/s/vue-3-suspense-template-ref-onmount-issue-8diff?file=/src/Component.vue

I can add you to my actual codebase if you would like to see the issue in context, it is in a private github repo but I can provide you access.

avatar
Aug 30th 2020

On further inspection feel free to keep this ticket closed.

The child component reference does actually resolve correctly with the latest RC and I have been unable to replicate the behavior I experienced in the async children - they all seem to be getting their refs at the expected onMount. 👍

I restarted Vite and although no errors were thrown, the code now operates as expected.

I've written a handy method for the async parent that integrates onMounted into an onRefAvailable that just checks for the existence of the ref on mounted and if not available start a watch that is then removed on resolution or onUnmounted. Seems to work fine for when you really need the ref.

https://gist.github.com/designerzen/8510c5f53be2b15dd61556681f904fb3