-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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">
export default {
setup () {
const count = ref(0)
const add = () => count.value++
return {
count, add
}
}
}
</script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nice fix β€οΈ
I've made a couple of minor changes - feel free to check and let me know if you agree.
@danielroe only the setup state was missing, which was the "res". That mean we don't even have to use a collision-resistant name |
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 })
await new Promise(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. |
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
yes, just fixed. Sorry for taking so much of your time for a simple PR π π’ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this!
Thank you for this! @huang-julien @danielroe @pi0 |
π Linked issue
resolve nuxt/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 additionnalmounted
ref()
. It also override therender()
function to conditionally render the component ifmounted
value is set to trueπ Checklist