-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Deep (nested) <slot />
in Vue component not rendering when hydrated
#6669
Comments
Willing to add a PR if the issue in the astro code can be pointed out 😄 |
<slot />
in Vue component not rendering when hydrated<slot />
in Vue component not rendering when hydrated
@matthewp is there any chance of you pointing me in the right direction of what code I could be looking at to work on a PR resolve this? Thanks |
in core folder I think |
Do you think it's a core rendering issue or a vue renderer issue? Not being familiar with the code base makes it a little hard to know where to begin debugging |
From what I can gather in my reproduction, the only difference is that it seems to not be rendering the |
astro/packages/integrations/vue/server.js Line 10 in c87d42e
here, I am logging out the value of in the second entry, you can see the {
default: [String (SlotString): '\n\t\t\t\t\t\t<p>Slot Text!</p>\n\t\t\t\t\t'] [HTMLString] {
instructions: null,
[Symbol(astro:slot-string)]: true
}
}
{
default: [String (SlotString): '\n' +
'\t\t\t\t\t<astro-island uid="IyM0O" component-url="/src/components/VueCounter.vue" component-export="default" renderer-url="/node_modules/.vite/deps/@astrojs_vue_client__js.js?v=6f754f08" props="{}" ssr="" client="load" before-hydration-url="/@id/astro:scripts/before-hydration.js" opts="{"name":"VueCounter","value":true}" await-children=""><div class="counter"><div class="counter-tool"><button>-</button><pre>0</pre><button>+</button></div><div class="counter-message"><!--[--><astro-slot>\n' +
'\t\t\t\t\t\t<p>Slot Text!</p>\n' +
'\t\t\t\t\t</astro-slot><!--]--></div></div></astro-island>\n' +
'\t\t\t\t'] [HTMLString] {
instructions: [ [Object] ],
[Symbol(astro:slot-string)]: true
}
}
{
default: [String (SlotString): '\n' +
'\t\t\t\t<div class="vue-slot"><!--[-->\n' +
'\t\t\t\t\t<astro-island uid="IyM0O" component-url="/src/components/VueCounter.vue" component-export="default" renderer-url="/node_modules/.vite/deps/@astrojs_vue_client__js.js?v=6f754f08" props="{}" ssr="" client="load" before-hydration-url="/@id/astro:scripts/before-hydration.js" opts="{"name":"VueCounter","value":true}" await-children=""><div class="counter"><div class="counter-tool"><button>-</button><pre>0</pre><button>+</button></div><div class="counter-message"><!--[-->\n' +
'\t\t\t\t\t\t<p>Slot Text!</p>\n' +
'\t\t\t\t\t<!--]--></div></div></astro-island>\n' +
'\t\t\t\t<!--]--></div>\n' +
'\t\t\t'] [HTMLString] {
instructions: [ [Object] ],
[Symbol(astro:slot-string)]: true
}
} |
@matthewp @wulinsheng123 I think I've found the culprit
if I change this line to simply: yield markHTMLString(html); ...then the slot content hydrates correctly as the |
Yes, that is indeed the issue. But unfortunately those astro-slot elements are needed for hydration. So the issue occurs when there are nested hydrated components inside of other framework components. This is the same underlying bug as #6597 which I'm hoping to look at soon. I wish I had an answer as to how to fix it but I don't quite know yet. Your example is a bit of a wrinkle because the other is also hydrated. |
@matthewp what about something like this? let processedHtml = html;
const islandRegex = /<astro-island.+?>.+?<\/astro-island>/gsm;
const islandMatches = processedHtml.match(islandRegex);
// astro-islands are replaced with a unique placeholder to avoid nested slots being removed
if (islandMatches) {
islandMatches.forEach(function (islandMatch, i) {
processedHtml = processedHtml.replace(islandMatch, `<astro-island-placeholder-${i} />`);
});
}
// remove remaining astro-slot elements
processedHtml = processedHtml.replace(/\<\/?astro-slot\b[^>]*>/g, "");
// replace placeholders with original astro-island elements
if (islandMatches) {
islandMatches.forEach(function (islandMatch, i) {
processedHtml = processedHtml.replace(`<astro-island-placeholder-${i} />`, islandMatch);
});
}
yield markHTMLString(processedHtml); |
What version of
astro
are you using?2.1.7
Are you using an SSR adapter? If so, which one?
None
What package manager are you using?
npm
What operating system are you using?
Mac
What browser are you using?
Chrome, Firefox
Describe the Bug
Deep
<slot />
in Vue component not rendering when hydrated when nested within another Vue component that isn't hydrated.It looks like it was an issue in v1 last year, as mentioned here in this issue #4970
But it also looks like @matthewp said it should be fixed in this comment #4970 (comment), though looking at the stackblitz he linked to in that comment, the same "Hydration completed but contains mismatches." is happening.
I've put together a reproduction show what works and does not work here: https://stackblitz.com/edit/github-f6ayhq-eqxoez
The expectation is that a Vue component with a slot that isn't hydrated should simply render as HTML and the nested Vue component that should hydrate renders without mismatch.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/github-f6ayhq-eqxoez
Participation
The text was updated successfully, but these errors were encountered: