diff --git a/docs/activityindicator.md b/docs/activityindicator.md index fc8edca4e25..c9d03b73021 100644 --- a/docs/activityindicator.md +++ b/docs/activityindicator.md @@ -78,6 +78,12 @@ Whether the indicator should hide when not animating. --- +### `ref` + +A ref setter that will be assigned an [element node](element-nodes) when mounted. + +--- + ### `size` Size of the indicator. diff --git a/docs/document-nodes.md b/docs/document-nodes.md new file mode 100644 index 00000000000..978ef87a1f8 --- /dev/null +++ b/docs/document-nodes.md @@ -0,0 +1,75 @@ +--- +id: document-nodes +title: Document nodes +--- + +Document nodes represent a complete native view tree. Apps using native navigation would provide a separate document node for each screen. Apps not using native navigation would generally provide a single document for the whole app (similar to single-page apps on Web). + +```SnackPlayer ext=js&name=Document%20instance%20example +import * as React from 'react'; +import {Text, TextInput, View} from 'react-native'; + +function MyComponent(props) { + return ( + + Start typing below + + + ) +} + +export default function AccessingDocument() { + const ref = React.useRef(null); + + React.useEffect(() => { + // Get the main text input in the screen and focus it after initial load. + const element = ref.current; + const doc = element.ownerDocument; + const textInput = doc.getElementById('main-text-input'); + textInput?.focus(); + }, []); + + return ( + + ); +} +``` + +--- + +## Reference + +### Web-compatible API + +From [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement): + +- Properties + - [`childElementCount`](https://developer.mozilla.org/en-US/docs/Web/API/Document/childElementCount) + - [`children`](https://developer.mozilla.org/en-US/docs/Web/API/Document/children) + - [`documentElement`](https://developer.mozilla.org/en-US/docs/Web/API/Document/documentElement) + - [`firstElementChild`](https://developer.mozilla.org/en-US/docs/Web/API/Document/firstElementChild) + - [`lastElementChild`](https://developer.mozilla.org/en-US/docs/Web/API/Document/lastElementChild) +- Methods + - [`getElementById()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById) + +From [`Node`](https://developer.mozilla.org/en-US/docs/Web/API/Node): + +- Properties + - [`childNodes`](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes) + - [`firstChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/firstChild) + - [`isConnected`](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) + - [`lastChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/lastChild) + - [`nextSibling`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nextSibling) + - [`nodeName`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeName) + - [`nodeType`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType) + - [`nodeValue`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeValue) + - [`ownerDocument`](https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument) + - [`parentElement`](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement) + - [`parentNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode) + - [`previousSibling`](https://developer.mozilla.org/en-US/docs/Web/API/Node/previousSibling) + - [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) +- Methods + - [`compareDocumentPosition()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition) + - [`contains()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/contains) + - [`getRootNode()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode) + - [`hasChildNodes()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/hasChildNodes) diff --git a/docs/element-nodes.md b/docs/element-nodes.md new file mode 100644 index 00000000000..1c0d639f3f0 --- /dev/null +++ b/docs/element-nodes.md @@ -0,0 +1,135 @@ +--- +id: element-nodes +title: Element nodes +--- + +Element nodes represent native components in the native view tree (similar to [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) nodes on Web). + +They are provided by all native components, and by many built-in components, via refs: + +```SnackPlayer ext=js&name=Element%20instances%20example +import * as React from 'react'; +import { View, SafeAreaView, StyleSheet, Text } from 'react-native'; + +const ViewWithRefs = () => { + const ref = React.useRef(null); + const [viewInfo, setViewInfo] = React.useState(''); + + React.useEffect(() => { + // `element` is an object implementing the interface described here. + const element = ref.current; + const rect = JSON.stringify(element.getBoundingClientRect()); + setViewInfo( + `Bounding rect is: ${rect}.\nText content is: ${element.textContent}`, + ); + }, []); + + return ( + + + Hello world! + + {viewInfo} + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + content: { + padding: 10, + backgroundColor: 'gray', + }, +}); + +export default ViewWithRefs; +``` + +:::info +Note that some built-in components are only a container for other components (including native components). For example, `ScrollView` internally renders a native scroll view and a native view, which are accessible through the ref it provides using methods like `getNativeScrollRef()` and `getInnerViewRef()`. +::: + +--- + +## Reference + +### Web-compatible API + +From [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement): + +- Properties + - [`offsetHeight`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight) + - [`offsetLeft`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft) + - [`offsetParent`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent) + - [`offsetTop`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop) + - [`offsetWidth`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth) +- Methods + - [`blur()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/blur). + - [`focus()`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus). + - ⚠️ The `options` parameter is not supported. + +From [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element): + +- Properties + - [`childElementCount`](https://developer.mozilla.org/en-US/docs/Web/API/Element/childElementCount) + - [`children`](https://developer.mozilla.org/en-US/docs/Web/API/Element/children) + - [`clientHeight`](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight) + - [`clientLeft`](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientLeft) + - [`clientTop`](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientTop) + - [`clientWidth`](https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth) + - [`firstElementChild`](https://developer.mozilla.org/en-US/docs/Web/API/Element/firstElementChild) + - [`id`](https://developer.mozilla.org/en-US/docs/Web/API/Element/id) + - ℹ️ Returns the value of the `id` or `nativeID` props. + - [`lastElementChild`](https://developer.mozilla.org/en-US/docs/Web/API/Element/lastElementChild) + - [`nextElementSibling`](https://developer.mozilla.org/en-US/docs/Web/API/Element/nextElementSibling) + - [`nodeName`](https://developer.mozilla.org/en-US/docs/Web/API/Element/nodeName) + - [`nodeType`](https://developer.mozilla.org/en-US/docs/Web/API/Element/nodeType) + - [`nodeValue`](https://developer.mozilla.org/en-US/docs/Web/API/Element/nodeValue) + - [`previousElementSibling`](https://developer.mozilla.org/en-US/docs/Web/API/Element/previousElementSibling) + - [`scrollHeight`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight) + - [`scrollLeft`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft) + - ⚠️ For built-in components, only `ScrollView` instances can return a value other than zero. + - [`scrollTop`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop) + - ⚠️ For built-in components, only `ScrollView` instances can return a value other than zero. + - [`scrollWidth`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollWidth) + - [`tagName`](https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName) + - ℹ️ Returns a normalized native component name prefixed with `RN:`, like `RN:View`. + - [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Element/textContent) +- Methods + - [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) + - [`hasPointerCapture()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/hasPointerCapture) + - [`setPointerCapture()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture) + - [`releasePointerCapture()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/releasePointerCapture) + +From [`Node`](https://developer.mozilla.org/en-US/docs/Web/API/Node): + +- Properties + - [`childNodes`](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes) + - [`firstChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/firstChild) + - [`isConnected`](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) + - [`lastChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/lastChild) + - [`nextSibling`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nextSibling) + - [`nodeName`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeName) + - [`nodeType`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType) + - [`nodeValue`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeValue) + - [`ownerDocument`](https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument) + - ℹ️ Will return the [document instance](/docs/next/document-instances) where this component was rendered. + - [`parentElement`](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement) + - [`parentNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode) + - [`previousSibling`](https://developer.mozilla.org/en-US/docs/Web/API/Node/previousSibling) + - [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) +- Methods + - [`compareDocumentPosition()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition) + - [`contains()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/contains) + - [`getRootNode()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode) + - ℹ️ Will return a reference to itself if the component is not mounted. + - [`hasChildNodes()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/hasChildNodes) + +### Legacy API + +- [`measure()`](/docs/next/legacy/direct-manipulation#measurecallback) +- [`measureInWindow()`](/docs/next/legacy/direct-manipulation#measureinwindowcallback) +- [`measureLayout()`](/docs/next/legacy/direct-manipulation#measurelayoutrelativetonativecomponentref-onsuccess-onfail) +- [`setNativeProps()`](/docs/next/legacy/direct-manipulation#setnativeprops-with-touchableopacity) diff --git a/docs/image.md b/docs/image.md index 9b0ba6446e3..5f6a2a5b1ad 100644 --- a/docs/image.md +++ b/docs/image.md @@ -334,6 +334,12 @@ A string indicating which referrer to use when fetching the resource. Sets the v --- +### `ref` + +A ref setter that will be assigned an [element node](element-nodes) when mounted. + +--- + ### `resizeMethod`
Android
The mechanism that should be used to resize the image when the image's dimensions differ from the image view's dimensions. Defaults to `auto`. diff --git a/docs/imagebackground.md b/docs/imagebackground.md index eba3b41b683..6670fd3b632 100644 --- a/docs/imagebackground.md +++ b/docs/imagebackground.md @@ -71,11 +71,7 @@ Inherits [Image Props](image.md#props). ### `imageRef` -Allows to set a reference to the inner `Image` component - -| Type | -| ------------------------------------------------------------- | -| [Ref](https://react.dev/learn/manipulating-the-dom-with-refs) | +A ref setter that will be assigned the [element node](element-nodes) of the inner `Image` component when mounted. --- diff --git a/docs/modal.md b/docs/modal.md index 66e1727be29..739be7205c3 100644 --- a/docs/modal.md +++ b/docs/modal.md @@ -189,6 +189,12 @@ This requires you to implement the `onRequestClose` prop to handle the dismissal --- +### `ref` + +A ref setter that will be assigned an [element node](element-nodes) when mounted. + +--- + ### `onRequestClose` The `onRequestClose` callback is called when the user taps the hardware back button on Android or the menu button on Apple TV. Because of this required prop, be aware that `BackHandler` events will not be emitted as long as the modal is open. diff --git a/docs/nodes.md b/docs/nodes.md new file mode 100644 index 00000000000..1c8a88ba918 --- /dev/null +++ b/docs/nodes.md @@ -0,0 +1,18 @@ +--- +id: nodes +title: Nodes from refs +--- + +React Native apps render a native view tree that represents the UI, similar to how React DOM does on Web (the DOM tree). React Native provides imperative access to this tree via [refs](https://react.dev/learn/manipulating-the-dom-with-refs), which are returned by all native components (including those rendered by built-in components like [`View`](/docs/next/view)). + +React Native provides 3 types of nodes: + +- [Elements](/docs/next/element-nodes): element nodes represent native components in the native view tree (similar to [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) nodes on Web). They are provided by all native components via refs. +- [Text](/docs/next/text-nodes): text nodes represent raw text content on the tree (similar to [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text) nodes on Web). They are not directly accessible via `refs`, but can be accessed using methods like [`childNodes`](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes) on element refs. +- [Documents](/docs/next/document-nodes): document nodes represent a complete native view tree (similar to [`Document`](https://developer.mozilla.org/en-US/docs/Web/API/Document) nodes on Web). Like text nodes, they can only be accessed through other nodes, using properties like [`ownerDocument`](https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument). + +As on Web, these nodes can be used to traverse the rendered UI tree, access layout information or execute imperative operations like `focus`. + +:::info +**Unlike on Web, these nodes do not allow mutation** (e.g.: [`node.appendChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)), as the tree contents are fully managed by the React renderer. +::: diff --git a/docs/switch.md b/docs/switch.md index fcbaae7b1de..4f9055c6256 100644 --- a/docs/switch.md +++ b/docs/switch.md @@ -96,6 +96,12 @@ Invoked when the user tries to change the value of the switch. Receives the new --- +### `ref` + +A ref setter that will be assigned an [element node](element-nodes) when mounted. + +--- + ### `thumbColor` Color of the foreground switch grip. If this is set on iOS, the switch grip will lose its drop shadow. diff --git a/docs/text-nodes.md b/docs/text-nodes.md new file mode 100644 index 00000000000..7fdbacf550f --- /dev/null +++ b/docs/text-nodes.md @@ -0,0 +1,86 @@ +--- +id: text-nodes +title: Text nodes +--- + +Text nodes represent raw text content on the tree (similar to [`Text`](https://developer.mozilla.org/en-US/docs/Web/API/Text) nodes on Web). They are not directly accessible via `refs`, but can be accessed using methods like [`childNodes`](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes) on element refs. + +```SnackPlayer ext=js&name=Text%20instances%20example +import * as React from 'react'; +import { SafeAreaView, StyleSheet, Text } from 'react-native'; + +const TextWithRefs = () => { + const ref = React.useRef(null); + const [viewInfo, setViewInfo] = React.useState(''); + + React.useEffect(() => { + // `textElement` is an object implementing the interface described here. + const textElement = ref.current; + const textNode = textElement.childNodes[0]; + setViewInfo( + `Text content is: ${textNode.nodeValue}`, + ); + }, []); + + return ( + + + Hello world! + + {viewInfo} + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + content: { + padding: 10, + backgroundColor: 'gray', + }, +}); + +export default TextWithRefs; +``` + +--- + +## Reference + +### Web-compatible API + +From [`CharacterData`](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData): + +- Properties + - [`data`](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/data) + - [`length`](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/length) + - [`nextElementSibling`](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/nextElementSibling) + - [`previousElementSibling`](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/previousElementSibling) +- Methods + - [`substringData()`](https://developer.mozilla.org/en-US/docs/Web/API/CharacterData/substringData) + +From [`Node`](https://developer.mozilla.org/en-US/docs/Web/API/Node): + +- Properties + - [`childNodes`](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes) + - [`firstChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/firstChild) + - [`isConnected`](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) + - [`lastChild`](https://developer.mozilla.org/en-US/docs/Web/API/Node/lastChild) + - [`nextSibling`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nextSibling) + - [`nodeName`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeName) + - [`nodeType`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType) + - [`nodeValue`](https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeValue) + - [`ownerDocument`](https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument) + - ℹ️ Will return the [document instance](/docs/next/document-instances) where this component was rendered. + - [`parentElement`](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentElement) + - [`parentNode`](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode) + - [`previousSibling`](https://developer.mozilla.org/en-US/docs/Web/API/Node/previousSibling) + - [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) +- Methods + - [`compareDocumentPosition()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition) + - [`contains()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/contains) + - [`getRootNode()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/getRootNode) + - ℹ️ Will return a reference to itself if the component is not mounted. + - [`hasChildNodes()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/hasChildNodes) diff --git a/docs/text.md b/docs/text.md index b6a0202e2e9..c45892ce2a4 100644 --- a/docs/text.md +++ b/docs/text.md @@ -638,6 +638,14 @@ When the scroll view is disabled, this defines how far your touch may move off o --- +### `ref` + +A ref setter that will be assigned an [element node](element-nodes) when mounted. + +Note that `Text` components don't provide text nodes, the same way that paragraph elements (`

`) on Web are element nodes instead of text nodes. Text nodes can be found as their child nodes instead. + +--- + ### `role` `role` communicates the purpose of a component to the user of an assistive technology. Has precedence over the [`accessibilityRole`](text#accessibilityrole) prop. diff --git a/docs/touchablehighlight.md b/docs/touchablehighlight.md index cd6313e66fe..98ea0823783 100644 --- a/docs/touchablehighlight.md +++ b/docs/touchablehighlight.md @@ -122,6 +122,12 @@ Called immediately after the underlay is shown. --- +### `ref` + +A ref setter that will be assigned an [element node](element-nodes) when mounted. + +--- + ### `style` | Type | diff --git a/docs/touchableopacity.md b/docs/touchableopacity.md index 025f38aa4c9..72af0bc5f49 100644 --- a/docs/touchableopacity.md +++ b/docs/touchableopacity.md @@ -143,3 +143,9 @@ TV next focus up (see documentation for the View component). | Type | | ------ | | number | + +--- + +### `ref` + +A ref setter that will be assigned an [element node](element-nodes) when mounted. diff --git a/docs/view.md b/docs/view.md index b967c0a64b6..3fd3c7fb4bd 100644 --- a/docs/view.md +++ b/docs/view.md @@ -729,6 +729,12 @@ Controls whether the `View` can be the target of touch events. --- +### `ref` + +A ref setter that will be assigned an [element node](element-nodes) when mounted. + +--- + ### `removeClippedSubviews` This is a reserved performance property exposed by `RCTView` and is useful for scrolling content when there are many subviews, most of which are offscreen. For this property to be effective, it must be applied to a view that contains many subviews that extend outside its bound. The subviews must also have `overflow: hidden`, as should the containing view (or one of its superviews). diff --git a/website/sidebars.ts b/website/sidebars.ts index 42c4c457ab7..dd8be8dbb40 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -315,6 +315,7 @@ export default { items: ['inputaccessoryview', 'safeareaview'], }, ], + Refs: ['nodes', 'element-nodes', 'text-nodes', 'document-nodes'], Props: [ 'image-style-props', 'layout-props',