Closed brillout closed 3 months ago
Hello. Can you please take a look at https://github.com/vikejs/vike-vue/pull/110? It's about this issue and https://github.com/vikejs/vike-vue/issues/67
It's not polished and there are decisions to be made about:
createClientOnlyComponent
)ssr-content
)But at least it works with props, events, and slots
- should the component be removed
Does <ClientOnly>
support any use case that clientOnly()
doesn't? If not then, yes, I think we should remove it and release a breaking change and bump the minor semver. We're still on 0.x.y
so I think it's ok.
- the name of the function (maybe
createClientOnlyComponent
)
I think clientOnly()
is both succint and clear?
- where it is exposed
So far, we export utils at vike-vue/utilName
. So vike-vue/clientOnly
.
Eventually merging exports to the root export vike-vue
is a consideration, but we need to double check whether Rollup's code-splitting works (it should in principle, but we should be sure about it as bloating the client-side is a no-go).
- the name of the fallback slot (maybe
ssr-content
)
How about <template #fallback>
?
- I need some help with a typing error when resolving import (https://github.com/vikejs/vike-vue/pull/110/files#diff-e0ffd04a4eabd913ea52d413b3cb2221e6b1ff796c6981a2adecf58a067031b3R79)
I'll have a look at it later today.
<ClientOnly>
can do better that the functionclientOnly
does not convey that it creates a component (defineComponent
, defineAsyncComponent
- maybe defineClientOnlyComponent
)<template #fallback>
- I was thinking about avoiding as much as possible to override a named slot of the wrapped component
clientOnly
does not convey that it creates a componen
Unless I'm missing some Vue convention, I think it's ok.
<template #fallback>
- I was thinking about avoiding as much as possible to override a named slot of the wrapped component
Good point. How about an option? For example:
function clientOnly(
componentLoader: () => Component,
{ fallbackSlotName = 'fallback' }: { fallbackSlotName?: string } = {}
) {
// ...
}
- I need some help with a typing error when resolving import (https://github.com/vikejs/vike-vue/pull/110/files#diff-e0ffd04a4eabd913ea52d413b3cb2221e6b1ff796c6981a2adecf58a067031b3R79)
The generic can be any type, maybe we should make it more restrictive?
For example, TS won't complain with the following:
clientOnly(
() => 12
)
Did you mean more something like T extends { new (): ComponentPublicInstance }
instead of T extends Component = { new (): ComponentPublicInstance }
?
Honestly I was just trying to find a way to pass the type of the imported component to the result of clientOnly.
About typing, I cannot make heads or tails of why it accepts something like () => 2
, so if someone can bring some sanity there while still keeping autocomplete on use please help.
@4350pChris WDYT? I'll have a look at it if Chris is busy.
I don't know much about Volar, but I presume using a generic to do the trick?
function clientOnly<Component, FallbackSlotName extends string = 'fallback'>(
componentLoader: () => Component,
{ fallbackSlotName }: { fallbackSlotName?: FallbackSlotName } = {}
) {
// ...
}
See for example the type of slotName1
and slotName2
in this playground.
I cannot make it work, sorry
- if we allow changing the fallback slot name with parameter we lose the autocomplete
I can't make autocomplete work at all on my setup. I'm trying with VSCode + Vue plugin, am I missing something?
When my cursor hovers #client-only-fall
VSCode isn't suggesting #client-only-fallback
:
For me the steps are:
pnpm reset
vike-vue
Developer: Reload Window
works for sureAh, it works now! Thanks. Sorry I'm a VSCode newbie :sweat_smile:
No problem - I feel the same with TS magic (especially when combined with Vue)
Indeed, there doesn't seem to be any Slot type that supports a extends string
generic.
Would it be possible to have clientOnly()
use #fallback
by default and if there is a conflict with the inner component then clientOnly()
uses #client-only-fallback
instead? Maybe it's a bit tricky to implement?
It would be the same problem with TS - we cannot make the slot name dynamic and still expose it in typescript (at least I don;t know how)
It isn't dynamic and instead we define two static slots fallback
and client-only-fallback
.
Maybe it's a bit tricky to implement?
If it's too tricky then I'd say let's go for only one slot client-only-fallback
. But maybe it's worth trying? I think the docs can be clear:
Use
#client-only-fallback
if the inner component uses#fallabck
.
Ah, you mean like that (define both slots) - it might work. Meanwhile if someone can understand why () => 1
satisfies T extends Component
it would help :D
Looking at it as we speak :)
Let me have a closer look.
Btw. I think you can remove = { new (): ComponentPublicInstance }
, since source
is a required parameter.
Which makes sense from a JSX perspective.
Btw. I think you can remove = { new (): ComponentPublicInstance }, since source is a required parameter.
For some reason if I remove that we lose autocomplete for props/events/slots for resulting component
Actually, () => 1 is a valid Component
Nice - you're right
For some reason if I remove that we lose autocomplete for props/events/slots for resulting component
Sounds like a Volar quirk.
Yep, editor quirk. I updated the PR - it has 2 commits - the second one should be removed before merge
@pdanpdan Can I merge this? Looks good from my point of view.
Yes, all done from my point of view
BTW, do you have any idea about this? https://github.com/vikejs/vike-vue/pull/110#discussion_r1630722333
BTW, do you have any idea about this? https://github.com/vikejs/vike-vue/pull/110#discussion_r1630722333
Unfortunately no. I tried a bit and couldn't get it working either.
See:
I think we can & should also deprecate the
<ClientOnly>
wrapper component in favor of aclientOnly()
function. It's a much nicer DX.