-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Add experimental docs for Fragment refs #8010
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -4,7 +4,9 @@ title: <Fragment> (<>...</>) | |||||
|
||||||
<Intro> | ||||||
|
||||||
`<Fragment>`, often used via `<>...</>` syntax, lets you group elements without a wrapper node. | ||||||
`<Fragment>`, often used via `<>...</>` syntax, lets you group elements without a wrapper node. | ||||||
|
||||||
<Experimental> Fragments can also accept refs, which enable interacting with underlying DOM nodes without adding wrapper elements. See reference and usage below.</Experimental> | ||||||
|
||||||
```js | ||||||
<> | ||||||
|
@@ -28,13 +30,42 @@ Wrap elements in `<Fragment>` to group them together in situations where you nee | |||||
#### Props {/*props*/} | ||||||
|
||||||
- **optional** `key`: Fragments declared with the explicit `<Fragment>` syntax may have [keys.](/learn/rendering-lists#keeping-list-items-in-order-with-key) | ||||||
- <ExperimentalBadge /> **optional** `ref`: A ref object or callback function. React will forward the ref to a `FragmentInstance` object that provides methods for interacting with the DOM nodes wrapped by the Fragment. | ||||||
|
||||||
### <ExperimentalBadge /> FragmentInstance {/*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`. | ||||||
- `getClientRects()`: Returns a flat array of `DOMRect` objects representing the bounding rectangles of all children. | ||||||
- `getRootNode()`: Returns the root node containing the Fragment's parent DOM node. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dumb question but why can we easily get the root node, but not the parent node? Wouldn't this be more flexible alternative to findDOMNode? |
||||||
|
||||||
**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 if `document.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 {/*caveats*/} | ||||||
|
||||||
- If you want to pass `key` to a Fragment, you can't use the `<>...</>` syntax. You have to explicitly import `Fragment` from `'react'` and render `<Fragment key={yourKey}>...</Fragment>`. | ||||||
|
||||||
- React does not [reset state](/learn/preserving-and-resetting-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.](https://gist.github.com/clemmy/b3ef00f9507909429d8aa0d3ee4f986b) | ||||||
|
||||||
- <ExperimentalBadge /> If you want to pass `ref` to a Fragment, you can't use the `<>...</>` syntax. You have to explicitly import `Fragment` from `'react'` and render `<Fragment ref={yourRef}>...</Fragment>`. | ||||||
|
||||||
--- | ||||||
|
||||||
## Usage {/*usage*/} | ||||||
|
@@ -208,3 +239,92 @@ function PostBody({ body }) { | |||||
``` | ||||||
|
||||||
</Sandpack> | ||||||
|
||||||
--- | ||||||
|
||||||
### <ExperimentalBadge /> Using Fragment refs for DOM interaction {/*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()`. | ||||||
|
||||||
```js | ||||||
import { Fragment } from 'react'; | ||||||
|
||||||
function ClickableFragment({ children, onClick }) { | ||||||
return ( | ||||||
<Fragment ref={fragmentInstance => { | ||||||
fragmentInstance.addEventListener('click', handleClick); | ||||||
return () => fragmentInstance.removeEventListener('click', handleClick); | ||||||
}}> | ||||||
{children} | ||||||
</Fragment> | ||||||
); | ||||||
} | ||||||
``` | ||||||
--- | ||||||
|
||||||
### <ExperimentalBadge /> Tracking visibility with Fragment refs {/*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: | ||||||
|
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: | |
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: |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "not what you want" feels a bit too casual and imprecise for the docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like a typo, PR #8056
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.