hakimel/reveal.js · error · Error
Fragment with asChild expects exactly one non-Fragment React
Error message
Fragment with asChild expects exactly one non-Fragment React element child.
What it means
After Children.only succeeds (fragment.tsx:48), the wrapper checks isValidElement(child) and that child.type is not React.Fragment (:53). If the single child is a Fragment (<>...</> or <Fragment>), it throws. The rationale: cloneElement would merge className/style/data-fragment-index onto the child, but React.Fragment does not render a host node and silently drops those props, so the fragment styling/index would be lost.
Source
Thrown at react/src/components/fragment.tsx:54
index,
as,
asChild,
className,
style,
children,
}: FragmentProps) {
const classes = mergeClassNames('fragment', animation, className);
if (asChild) {
let child: ReactElement<FragmentChildProps>;
try {
child = Children.only(children) as ReactElement<FragmentChildProps>;
} catch {
throw new Error('Fragment with asChild expects exactly one React element child.');
}
if (!isValidElement(child) || child.type === ReactFragment) {
throw new Error('Fragment with asChild expects exactly one non-Fragment React element child.');
}
const fragmentChildProps: FragmentChildProps = {
className: mergeClassNames(child.props.className, classes),
style: mergeStyles(child.props.style, style),
};
if (index !== undefined) {
fragmentChildProps['data-fragment-index'] = index;
}
return cloneElement(child, fragmentChildProps);
}
const Tag = as ?? 'span';
return (
<Tag className={classes} style={style} data-fragment-index={index}>View on GitHub (pinned to a3b9406956)
Solutions
- Replace the Fragment/<> child with a real host element (div, span, li, etc.) so className and style can be applied.
- If you only need grouping, remove asChild so Fragment renders its own <span> wrapper instead of cloning.
- Flatten the structure: move fragment styling onto the actual leaf element rather than onto a Fragment.
- Check child.type at authoring time — if it equals React.Fragment, this error will fire.
Example fix
// before — Fragment as the asChild target
<Fragment asChild index={0}>
<>
<strong>A</strong> and <em>B</em>
</>
</Fragment>
// after — use a real host element
<Fragment asChild index={0}>
<span><strong>A</strong> and <em>B</em></span>
</Fragment> Defensive patterns
Strategy: type-guard
Validate before calling
import { Fragment as ReactFragment, isValidElement, type ReactElement } from 'react';
function assertNonFragmentChild(child) {
if (!isValidElement(child) || child.type === ReactFragment) {
throw new Error('Fragment asChild requires a real host element, not a Fragment.');
}
} Type guard
import { Fragment as ReactFragment, isValidElement, type ReactElement } from 'react';
function isAdoptableHostElement(child): child is ReactElement {
return isValidElement(child) && child.type !== ReactFragment;
} Prevention
- Use a real host element (div/span/li/...) as the asChild target so className/style survive cloneElement.
- Do not use <>...</> or <React.Fragment> under asChild.
- If grouping is all you need, remove asChild instead of fighting it.
When it happens
Trigger: Using the <>...</> shorthand or <React.Fragment> as the asChild target; passing a component that resolves to Fragment at runtime; a memoized/lazy element whose type identity equals React.Fragment; nesting <Fragment asChild> inside another <Fragment asChild> using a Fragment as the bridge.
Common situations: Reaching for <> to group children and then enabling asChild on the parent; refactoring a wrapper element to a Fragment for layout reasons while keeping asChild; copy-paste from a pattern that used a real element.
Related errors
- Fragment with asChild expects exactly one React element chil
- Please specify a valid media type to preview
AI-assisted analysis of hakimel/reveal.js@a3b9406956 (2026-08-12).
Data as JSON: /api/errors/0dd2e685ad92afd0.
Report an issue: GitHub.