8000 fix(nuxt): pass attrs down to single child of `<ClientOnly>` (#32131) · nuxt/nuxt@c0a518f · GitHub
[go: up one dir, main page]

Skip to content

Commit c0a518f

Browse files
authored
fix(nuxt): pass attrs down to single child of <ClientOnly> (#32131)
1 parent 7decdf4 commit c0a518f

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

packages/nuxt/src/app/components/client-only.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ const STATIC_DIV = '<div></div>'
1212
export default defineComponent({
1313
name: 'ClientOnly',
1414
inheritAttrs: false,
15-
1615
props: ['fallback', 'placeholder', 'placeholderTag', 'fallbackTag'],
1716
setup (props, { slots, attrs }) {
1817
const mounted = ref(false)
@@ -29,7 +28,13 @@ export default defineComponent({
2928
}
3029
provide(clientOnlySymbol, true)
3130
return () => {
32-
if (mounted.value) { return slots.default?.() }
31+
if (mounted.value) {
32+
const vnodes = slots.default?.()
33+
if (vnodes && vnodes.length === 1) {
34+
return [cloneVNode(vnodes[0]!, attrs)]
35+
}
36+
return vnodes
37+
}
3338
const slot = slots.fallback || slots.placeholder
3439
if (slot) { return h(slot) }
3540
const fallbackStr = props.fallback || props.placeholder || ''

test/nuxt/client-only.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { flushPromises, mount } from '@vue/test-utils'
66

77
import { createClientOnly } from '../../packages/nuxt/src/app/components/client-only'
88
import { createClientPage } from '../../packages/nuxt/dist/components/runtime/client-component'
9+
import { ClientOnly } from '#components'
910

1011
describe('client pages', () => {
1112
it('should render without a wrapper', async () => {
@@ -52,6 +53,32 @@ describe('client pages', () => {
5253
})
5354
})
5455

56+
describe('client-only', () => {
57+
it('should render its children', async () => {
58+
const component = defineComponent({
59+
setup () {
60+
return () => h(ClientOnly, {}, {
61+
default: () => h('div', {}, 'client-only'),
62+
})
63+
},
64+
})
65+
const wrapper = await mountSuspended(component)
66+
expect(wrapper.html()).toMatchInlineSnapshot(`"<div>client-only</div>"`)
67+
})
68+
69+
it('should support inherited attributes', async () => {
70+
const component = defineComponent({
71+
setup () {
72+
return () => h(ClientOnly, { class: 'test', id: 'test' }, {
73+
default: () => h('div', {}, 'client-only'),
74+
})
75+
},
76+
})
77+
const wrapper = await mountSuspended(component)
78+
expect(wrapper.html()).toMatchInlineSnapshot(`"<div class="test" id="test">client-only</div>"`)
79+
})
80+
})
81+
5582
const Client = defineComponent({
5683
name: 'TestClient',
5784
setup () {

0 commit comments

Comments
 (0)
0