fix(warn): avoid warning on empty children with Suspense (#3962)

This commit is contained in:
Eduardo San Martin Morote 2023-11-06 10:48:40 +01:00 committed by GitHub
parent b39fa1f815
commit 405f34587a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 1 deletions

View File

@ -17,9 +17,12 @@ import {
onUnmounted,
onErrorCaptured,
shallowRef,
SuspenseProps,
resolveDynamicComponent,
Fragment
} from '@vue/runtime-test'
import { createApp, defineComponent } from 'vue'
import { type RawSlots } from 'packages/runtime-core/src/componentSlots'
describe('Suspense', () => {
const deps: Promise<any>[] = []
@ -1523,4 +1526,75 @@ describe('Suspense', () => {
expected = `<div>outerB</div><div>innerB</div>`
expect(serializeInner(root)).toBe(expected)
})
describe('warnings', () => {
// base function to check if a combination of slots warns or not
function baseCheckWarn(
shouldWarn: boolean,
children: RawSlots,
props: SuspenseProps | null = null
) {
const Comp = {
setup() {
return () => h(Suspense, props, children)
}
}
const root = nodeOps.createElement('div')
render(h(Comp), root)
if (shouldWarn) {
expect(`<Suspense> slots expect a single root node.`).toHaveBeenWarned()
} else {
expect(
`<Suspense> slots expect a single root node.`
).not.toHaveBeenWarned()
}
}
// actual function that we use in tests
const checkWarn = baseCheckWarn.bind(null, true)
const checkNoWarn = baseCheckWarn.bind(null, false)
test('does not warn on single child', async () => {
checkNoWarn({
default: h('div'),
fallback: h('div')
})
})
test('does not warn on null', async () => {
checkNoWarn({
default: null,
fallback: null
})
})
test('does not warn on <component :is="null" />', async () => {
checkNoWarn({
default: () => [resolveDynamicComponent(null)],
fallback: () => null
})
})
test('does not warn on empty array', async () => {
checkNoWarn({
default: [],
fallback: () => []
})
})
test('warns on multiple children in default', async () => {
checkWarn({
default: [h('div'), h('div')]
})
})
test('warns on multiple children in fallback', async () => {
checkWarn({
default: h('div'),
fallback: [h('div'), h('div')]
})
})
})
})

View File

@ -29,6 +29,7 @@ import {
assertNumber
} from '../warning'
import { handleError, ErrorCodes } from '../errorHandling'
import { NULL_DYNAMIC_COMPONENT } from '../helpers/resolveAssets'
export interface SuspenseProps {
onResolve?: () => void
@ -795,7 +796,11 @@ function normalizeSuspenseSlot(s: any) {
}
if (isArray(s)) {
const singleChild = filterSingleRoot(s)
if (__DEV__ && !singleChild) {
if (
__DEV__ &&
!singleChild &&
s.filter(child => child !== NULL_DYNAMIC_COMPONENT).length > 0
) {
warn(`<Suspense> slots expect a single root node.`)
}
s = singleChild

View File

@ -114,6 +114,7 @@ export type VNodeProps = {
type VNodeChildAtom =
| VNode
| typeof NULL_DYNAMIC_COMPONENT
| string
| number
| boolean