<Fragment> (<>...</>)
<Fragment>
, часто використовується за допомогою синтаксису <>...</>
, дозволяє групувати елементи без елементу-обгортки.
<>
<OneChild />
<AnotherChild />
</>
Опис
<Fragment>
Огорніть елементи у <Fragment>
щоб групувати їх разом в ситуаціях, коли вам потрібен один елемент. Групування елементів у Fragment
не впливає на результуючий DOM; це так само, ніби елементи і не були згруповані. Переважно, порожній тег JSX <></>
є скороченням для <Fragment></Fragment>
.
Пропси
- опційний
key
: Фрагменти, оголошені з явним синтаксисом<Fragment>
можуть мати ключі. - Лише сanary 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.
Лише сanary 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.
Обмеження
-
Якщо ви хочете передати
key
для Fragment, ви не можете використовувати синтаксис<>...</>
. Ви маєте явно імпортуватиFragment
з'react'
та рендерити<Fragment key={yourKey}>...</Fragment>
. -
React не буде скидати стан компонента коли ви переходите від рендерингу
<><Child /></>
до[<Child />]
або назад, або коли ви переходите від рендерингу<><Child /></>
до<Child />
і назад. Це може працювати лише на одному рівні вкладеності: наприклад, перехід від<><><Child /></></>
до<Child />
скидає стан компонента. Дивіться точну семантику тут. -
Лише сanary 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>
.
Використання
Повернення кількох елементів
Використовуйте Fragment
, або еквівалентний синтаксис <>...</>
, для групування кількох елементів разом. Ви можете використовувати його для збору кількох елементів в будь-якому місці, де може бути один елемент. Наприклад, компонент може повернути тільки один елемент, але за допомогою Fragment ви можете групувати кілька елементів разом і повертати їх як групу:
function Post() {
return (
<>
<PostTitle />
<PostBody />
</>
);
}
Фрагменти є корисним інструментом, оскільки групування елементів з Fragment
не має впливу на розташування або стилізацію, на відміну від огортання елементів в інший контейнер, такий як DOM-елемент. Якщо ви перевірите цей приклад за допомогою інструментів браузера, ви побачите, що всі DOM-вузли <h1>
і <article>
відображаються як сусідні елементи без обгорток навколо них:
export default function Blog() { return ( <> <Post title="Оновлення" body="Минув деякий час після мого останнього повідомлення..." /> <Post title="Мій новий блог" body="Я розпочинаю новий блог!" /> </> ) } 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> ); }
Занурення
Цей приклад еквівалентний імпорту Fragment
з React:
import { Fragment } from 'react';
function Post() {
return (
<Fragment>
<PostTitle />
<PostBody />
</Fragment>
);
}
Зазвичай вам не потрібно цього робити, якщо вам не треба передавати key
у ваш Fragment
.
Присвоєння змінній декількох елементів
Як і будь-який інший елемент, Fragment
елементи можна присвоювати змінним, передавати їх як пропси тощо:
function CloseDialog() {
const buttons = (
<>
<OKButton />
<CancelButton />
</>
);
return (
<AlertDialog buttons={buttons}>
Ви впевнені, що хочете залишити цю сторінку?
</AlertDialog>
);
}
Групування елементів з текстом
Ви можете використовувати Fragment
, щоб групувати текст разом з компонентами:
function DateRangePicker({ start, end }) {
return (
<>
Від
<DatePicker date={start} />
до
<DatePicker date={end} />
</>
);
}
Відображення списку фрагментів
Ось ситуація, коли вам потрібно написати Fragment
явно, замість використання синтаксису <></>
. Якщо ви рендерите кілька елементів в циклі, вам потрібно призначити key
кожному елементу. Якщо елементи всередині циклу є Фрагментами, то вам потрібно використовувати звичайний синтаксис елементів JSX, щоб мати змогу вказати атрибут key
:
function Blog() {
return posts.map(post =>
<Fragment key={post.id}>
<PostTitle title={post.title} />
<PostBody body={post.body} />
</Fragment>
);
}
Ви можете перевірити DOM, щоб переконатися, що дочірні компоненти Fragment нічим не обгортуються:
import { Fragment } from 'react'; const posts = [ { id: 1, title: 'Оновлення', body: "Минув деякий час після мого останнього повідомлення..." }, { id: 2, title: 'Мій новий блог', body: 'Я розпочинаю новий блог!' } ]; 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> ); }
Лише сanary 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>
);
}
Лише сanary 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.
Лише сanary 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.