<Fragment> (<>...</>)
<Fragment>
, often used via <>...</>
syntax, lets you group elements without a wrapper node.
<>
<OneChild />
<AnotherChild />
</>
Reference
<Fragment>
Wrap elements in <Fragment>
to group them together in situations where you need a single element. Grouping elements in Fragment
has no effect on the resulting DOM; it is the same as if the elements were not grouped. The empty JSX tag <></>
is shorthand for <Fragment></Fragment>
in most cases.
Props
- optional
key
: Fragments declared with the explicit<Fragment>
syntax may have keys. - Experimental only optional
ref
: A ref object (e.g. fromuseRef
) or callback function. React provides aFragmentInstance
as the ref value that implements methods for interacting with the DOM nodes wrapped by the Fragment.
Experimental only FragmentInstance
When you pass a ref to a fragment, React provides a FragmentInstance
object with methods for interacting with the DOM nodes wrapped by the fragment:
Event handling methods:
addEventListener(type, listener, options?)
: Adds an event listener to all first-level DOM children of the Fragment.removeEventListener(type, listener, options?)
: Removes an event listener from all first-level DOM children of the Fragment.dispatchEvent(event)
: Dispatches an event to a virtual child of the Fragment to call any added listeners and can bubble to the DOM parent.
Layout methods:
compareDocumentPosition(otherNode)
: Compares the document position of the Fragment with another node.- If the Fragment has children, the native
compareDocumentPosition
value is returned. - Empty Fragments will attempt to compare positioning within the React tree and include
Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
. - Elements that have a different relationship in the React tree and DOM tree due to portaling or other insertions are
Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC
.
- If the Fragment has children, the native
getClientRects()
: Returns a flat array ofDOMRect
objects representing the bounding rectangles of all children.getRootNode()
: Returns the root node containing the Fragment’s parent DOM node.
Focus management methods:
focus(options?)
: Focuses the first focusable DOM node in the Fragment. Focus is attempted on nested children depth-first.focusLast(options?)
: Focuses the last focusable DOM node in the Fragment. Focus is attempted on nested children depth-first.blur()
: Removes focus ifdocument.activeElement
is within the Fragment.
Observer methods:
observeUsing(observer)
: Starts observing the Fragment’s DOM children with an IntersectionObserver or ResizeObserver.unobserveUsing(observer)
: Stops observing the Fragment’s DOM children with the specified observer.
Caveats
-
If you want to pass
key
to a Fragment, you can’t use the<>...</>
syntax. You have to explicitly importFragment
from'react'
and render<Fragment key={yourKey}>...</Fragment>
. -
React does not reset state when you go from rendering
<><Child /></>
to[<Child />]
or back, or when you go from rendering<><Child /></>
to<Child />
and back. This only works a single level deep: for example, going from<><><Child /></></>
to<Child />
resets the state. See the precise semantics here. -
Experimental only If you want to pass
ref
to a Fragment, you can’t use the<>...</>
syntax. You have to explicitly importFragment
from'react'
and render<Fragment ref={yourRef}>...</Fragment>
.
Usage
Returning multiple elements
Use Fragment
, or the equivalent <>...</>
syntax, to group multiple elements together. You can use it to put multiple elements in any place where a single element can go. For example, a component can only return one element, but by using a Fragment you can group multiple elements together and then return them as a group:
function Post() {
return (
<>
<PostTitle />
<PostBody />
</>
);
}
Fragments are useful because grouping elements with a Fragment has no effect on layout or styles, unlike if you wrapped the elements in another container like a DOM element. If you inspect this example with the browser tools, you’ll see that all <h1>
and <article>
DOM nodes appear as siblings without wrappers around them:
export default function Blog() { return ( <> <Post title="An update" body="It's been a while since I posted..." /> <Post title="My new blog" body="I am starting a new blog!" /> </> ) } function Post({ title, body }) { return ( <> <PostTitle title={title} /> <PostBody body={body} /> </> ); } function PostTitle({ title }) { return <h1>{title}</h1> } function PostBody({ body }) { return ( <article> <p>{body}</p> </article> ); }
Deep Dive
The example above is equivalent to importing Fragment
from React:
import { Fragment } from 'react';
function Post() {
return (
<Fragment>
<PostTitle />
<PostBody />
</Fragment>
);
}
Usually you won’t need this unless you need to pass a key
to your Fragment
.
Assigning multiple elements to a variable
Like any other element, you can assign Fragment elements to variables, pass them as props, and so on:
function CloseDialog() {
const buttons = (
<>
<OKButton />
<CancelButton />
</>
);
return (
<AlertDialog buttons={buttons}>
Are you sure you want to leave this page?
</AlertDialog>
);
}
Grouping elements with text
You can use Fragment
to group text together with components:
function DateRangePicker({ start, end }) {
return (
<>
From
<DatePicker date={start} />
to
<DatePicker date={end} />
</>
);
}
Rendering a list of Fragments
Here’s a situation where you need to write Fragment
explicitly instead of using the <></>
syntax. When you render multiple elements in a loop, you need to assign a key
to each element. If the elements within the loop are Fragments, you need to use the normal JSX element syntax in order to provide the key
attribute:
function Blog() {
return posts.map(post =>
<Fragment key={post.id}>
<PostTitle title={post.title} />
<PostBody body={post.body} />
</Fragment>
);
}
You can inspect the DOM to verify that there are no wrapper elements around the Fragment children:
import { Fragment } from 'react'; const posts = [ { id: 1, title: 'An update', body: "It's been a while since I posted..." }, { id: 2, title: 'My new blog', body: 'I am starting a new blog!' } ]; export default function Blog() { return posts.map(post => <Fragment key={post.id}> <PostTitle title={post.title} /> <PostBody body={post.body} /> </Fragment> ); } function PostTitle({ title }) { return <h1>{title}</h1> } function PostBody({ body }) { return ( <article> <p>{body}</p> </article> ); }
Experimental only Using Fragment refs for DOM interaction
Fragment refs allow you to interact with the DOM nodes wrapped by a Fragment without adding extra wrapper elements. This is useful for event handling, visibility tracking, focus management, and replacing deprecated patterns like ReactDOM.findDOMNode()
.
import { Fragment } from 'react';
function ClickableFragment({ children, onClick }) {
return (
<Fragment ref={fragmentInstance => {
fragmentInstance.addEventListener('click', handleClick);
return () => fragmentInstance.removeEventListener('click', handleClick);
}}>
{children}
</Fragment>
);
}
Experimental only Tracking visibility with Fragment refs
Fragment refs are useful for visibility tracking and intersection observation. This enables you to monitor when content becomes visible without requiring the child Components to expose refs:
import { Fragment, useRef, useLayoutEffect } from 'react';
function VisibilityObserverFragment({ threshold = 0.5, onVisibilityChange, children }) {
const fragmentRef = useRef(null);
useLayoutEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
onVisibilityChange(entries.some(entry => entry.isIntersecting))
},
{ threshold }
);
fragmentRef.current.observeUsing(observer);
return () => fragmentRef.current.unobserveUsing(observer);
}, [threshold, onVisibilityChange]);
return (
<Fragment ref={fragmentRef}>
{children}
</Fragment>
);
}
function MyComponent() {
const handleVisibilityChange = (isVisible) => {
console.log('Component is', isVisible ? 'visible' : 'hidden');
};
return (
<VisibilityObserverFragment onVisibilityChange={handleVisibilityChange}>
<SomeThirdPartyComponent />
<AnotherComponent />
</VisibilityObserverFragment>
);
}
This pattern is an alternative to Effect-based visibility logging, which is an anti-pattern in most cases. Relying on Effects alone does not guarantee that the rendered Component is observable by the user.
Experimental only Focus management with Fragment refs
Fragment refs provide focus management methods that work across all DOM nodes within the Fragment:
import { Fragment, useRef } from 'react';
function FocusFragment({ children }) {
const fragmentRef = useRef(null);
return (
<Fragment ref={(fragmentInstance) => fragmentInstance?.focus()}>
{children}
</Fragment>
);
}
The focus()
method focuses the first focusable element within the Fragment, while focusLast()
focuses the last focusable element.