Uh oh!
There was an error while loading. Please reload this page.
feat(nuxt): remove wrapper from client only components - #6165
Conversation
✅ Deploy Preview for nuxt3-docs canceled.
|
- prefer using ctx for attrs instead of options - wrap with h() to avoid oldNodes is null issue
@danielroe it should be good now, i've tested on a component with a <template>
<div>
hellow world
<button@click="add">
{{ count }}
</button>
</div>
</template>
<script setup lang="ts">const count =ref(0)const add = () =>count.value++defineExpose({ add, count })</script><template>
<div>
hellow world
<button@click="add">
{{ count }}
</button>
</div>
</template>
<script lang="ts">exportdefault { setup () {const count =ref(0)const add = () =>count.value++return {count, add } }}</script> |
Uh oh!
There was an error while loading. Please reload this page.
danielroe
left a comment
There was a problem hiding this comment.
This is a nice fix ❤️
I've made a couple of minor changes - feel free to check and let me know if you agree.
huang-julien
commented
Jul 27, 2022
@danielroe only the setup state was missing, which was the "res". That mean we don't even have to use a collision-resistant name |
Uh oh!
There was an error while loading. Please reload this page.
Would you take a look at stateful use, and test on both build + dev mode? It's not quite there yet, and I wonder if we may have to migrate back to using a render function in some cases. Modify the example component <script setup lang="ts">function exposedFunc () {console.log('ok')}const state =ref('component')defineExpose({ exposedFunc })awaitnewPromise(resolve=>setTimeout(resolve, 300))onMounted(() => { console.log('mounted') })</script>
<template>
<div>
<!-- this can be commented in/out to trigger different compile approaches -->
client-only {{ state }}
</div>
</template>See SFC playground. |
i could fix the build-dev issue, i set this PR to draft to do more testing. There might be some refactor that can be done on the fix. I think moving |
- must use a Fragment to render the build component to avoid "f is null".
yes, it needs a fix. I've finally understood when does the component have the render function. Only <script setup> SFC are compiled into setup only component. So we need to keep the render function if the the original component have one |
checks
done on
|
Currently if users pass Would you explain more about the oldChildren null issue you unearthed? |
This was happening only in build, not sure why but at the setup render function, in some components, if we don't wrap the component render here with a Fragment, the component is not being re-rendered when mounted. And in some cases there's a oldChildren is null error triggered by vue in build and dev. I'll try to reproduce it. |
danielroe
commented
Jul 29, 2022
I'm sure you're looking into it, but just to clarify - we're currently getting attrs applied before mount, but not afterwards. |
here is the reproduction |
- set back attribute inheritance for template (runtime-compiler) - force null on Fragment props - use h() to render the functions with attrs inheritance
huang-julien
commented
Jul 29, 2022
yes, just fixed. Sorry for taking so much of your time for a simple PR 🙏 😢 |
danielroe
left a comment
There was a problem hiding this comment.
This is great - looks good in my testing! Not a simple PR by any means. Well done.
This is likely a Vue issue stackblitz, so using Fragment seems to be good to avoid this |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
ffxsam
commented
Aug 2, 2022
Thank you for this! @huang-julien@danielroe@pi0 |
🔗 Linked issue
resolvenuxt/nuxt#14310
❓ Type of change
📚 Description
Before, the createClientOnly returned a new component wrapping the component with ".client" in its name. So when we were setting a ref on
<HelloWorld ref="helloworld" />the ref assigned was on the<ClientOnly />component but not on<HelloWorld />.This PR make
createClientOnly()modifying the component instead of wrapping it. The setup hook return an additionnalmountedref(). It also override therender()function to conditionally render the component ifmountedvalue is set to true📝 Checklist