mirror of https://github.com/vuejs/core.git
fix(warn): avoid warning on empty children with Suspense (#3962)
This commit is contained in:
parent
b39fa1f815
commit
405f34587a
|
@ -17,9 +17,12 @@ import {
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
onErrorCaptured,
|
onErrorCaptured,
|
||||||
shallowRef,
|
shallowRef,
|
||||||
|
SuspenseProps,
|
||||||
|
resolveDynamicComponent,
|
||||||
Fragment
|
Fragment
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
import { createApp, defineComponent } from 'vue'
|
import { createApp, defineComponent } from 'vue'
|
||||||
|
import { type RawSlots } from 'packages/runtime-core/src/componentSlots'
|
||||||
|
|
||||||
describe('Suspense', () => {
|
describe('Suspense', () => {
|
||||||
const deps: Promise<any>[] = []
|
const deps: Promise<any>[] = []
|
||||||
|
@ -1523,4 +1526,75 @@ describe('Suspense', () => {
|
||||||
expected = `<div>outerB</div><div>innerB</div>`
|
expected = `<div>outerB</div><div>innerB</div>`
|
||||||
expect(serializeInner(root)).toBe(expected)
|
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')]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -29,6 +29,7 @@ import {
|
||||||
assertNumber
|
assertNumber
|
||||||
} from '../warning'
|
} from '../warning'
|
||||||
import { handleError, ErrorCodes } from '../errorHandling'
|
import { handleError, ErrorCodes } from '../errorHandling'
|
||||||
|
import { NULL_DYNAMIC_COMPONENT } from '../helpers/resolveAssets'
|
||||||
|
|
||||||
export interface SuspenseProps {
|
export interface SuspenseProps {
|
||||||
onResolve?: () => void
|
onResolve?: () => void
|
||||||
|
@ -795,7 +796,11 @@ function normalizeSuspenseSlot(s: any) {
|
||||||
}
|
}
|
||||||
if (isArray(s)) {
|
if (isArray(s)) {
|
||||||
const singleChild = filterSingleRoot(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.`)
|
warn(`<Suspense> slots expect a single root node.`)
|
||||||
}
|
}
|
||||||
s = singleChild
|
s = singleChild
|
||||||
|
|
|
@ -114,6 +114,7 @@ export type VNodeProps = {
|
||||||
|
|
||||||
type VNodeChildAtom =
|
type VNodeChildAtom =
|
||||||
| VNode
|
| VNode
|
||||||
|
| typeof NULL_DYNAMIC_COMPONENT
|
||||||
| string
|
| string
|
||||||
| number
|
| number
|
||||||
| boolean
|
| boolean
|
||||||
|
|
Loading…
Reference in New Issue