- Spec files
npm-react
Describes: pkg:npm/react@19.1.x
- Description
- React is a JavaScript library for building user interfaces with a declarative, component-based approach.
- Author
- tessl
- Last updated
refs.md docs/
1# Refs and Forward Refs23Reference system for accessing DOM nodes and component instances. Refs provide a way to access DOM nodes or React elements created in the render method directly.45## Capabilities67### createRef89Creates a ref object for accessing DOM nodes in class components.1011```typescript { .api }12/**13* Creates a ref object for class components14* @returns RefObject with current property15*/16function createRef<T = any>(): React.RefObject<T>;1718interface RefObject<T> {19readonly current: T | null;20}21```2223**Usage Examples:**2425```typescript26import React, { Component, createRef } from "react";2728class TextInput extends Component {29private inputRef = createRef<HTMLInputElement>();3031focusInput = () => {32this.inputRef.current?.focus();33};3435render() {36return (37<div>38<input ref={this.inputRef} type="text" />39<button onClick={this.focusInput}>Focus Input</button>40</div>41);42}43}44```4546### useRef Hook4748Hook for creating mutable ref objects in function components (covered in detail in Hooks documentation).4950```typescript { .api }51/**52* Creates a mutable ref object for function components53* @param initialValue - Initial value for the ref54* @returns MutableRefObject with current property55*/56function useRef<T = undefined>(): React.MutableRefObject<T | undefined>;57function useRef<T = undefined>(initialValue: T): React.MutableRefObject<T>;58function useRef<T>(initialValue: T | null): React.RefObject<T>;5960interface MutableRefObject<T> {61current: T;62}63```6465**Usage Examples:**6667```typescript68import React, { useRef, useEffect } from "react";6970function AutoFocusInput() {71const inputRef = useRef<HTMLInputElement>(null);72const renderCount = useRef(0);7374useEffect(() => {75inputRef.current?.focus();76renderCount.current += 1;77});7879return (80<div>81<input ref={inputRef} type="text" />82<p>Component rendered {renderCount.current} times</p>83</div>84);85}86```8788### forwardRef8990Higher-order component that forwards refs to child components.9192```typescript { .api }93/**94* Forwards refs through components to child elements95* @param render - Render function that receives props and ref96* @returns Component that forwards refs97*/98function forwardRef<T, P = {}>(99render: (props: P, ref: React.Ref<T>) => React.ReactElement | null100): React.ForwardRefExoticComponent<React.PropsWithoutRef<P> & React.RefAttributes<T>>;101102type Ref<T> = RefCallback<T> | RefObject<T> | null;103type RefCallback<T> = (instance: T | null) => void;104```105106**Usage Examples:**107108```typescript109import React, { forwardRef, useRef } from "react";110111interface InputProps {112label?: string;113placeholder?: string;114}115116// Forward ref to the actual input element117const FancyInput = forwardRef<HTMLInputElement, InputProps>((props, ref) => {118return (119<div className="fancy-input">120{props.label && <label>{props.label}</label>}121<input122ref={ref}123placeholder={props.placeholder}124className="fancy-input-field"125/>126</div>127);128});129130function App() {131const inputRef = useRef<HTMLInputElement>(null);132133const focusInput = () => {134inputRef.current?.focus();135};136137return (138<div>139<FancyInput140ref={inputRef}141label="Name"142placeholder="Enter your name"143/>144<button onClick={focusInput}>Focus Input</button>145</div>146);147}148```149150### useImperativeHandle151152Hook for customizing the instance value exposed by a ref when using forwardRef (covered in detail in Hooks documentation).153154```typescript { .api }155/**156* Customizes the instance value exposed to parent components when using forwardRef157* @param ref - The ref object158* @param createHandle - Function that returns the handle159* @param deps - Optional dependency array160*/161function useImperativeHandle<T, R extends T>(162ref: React.Ref<T> | undefined,163createHandle: () => R,164deps?: React.DependencyList165): void;166```167168**Usage Examples:**169170```typescript171import React, { forwardRef, useImperativeHandle, useRef, useImperativeHandle } from "react";172173interface VideoPlayerHandle {174play: () => void;175pause: () => void;176getCurrentTime: () => number;177}178179interface VideoPlayerProps {180src: string;181}182183const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>((props, ref) => {184const videoRef = useRef<HTMLVideoElement>(null);185186useImperativeHandle(ref, () => ({187play: () => {188videoRef.current?.play();189},190pause: () => {191videoRef.current?.pause();192},193getCurrentTime: () => {194return videoRef.current?.currentTime ?? 0;195}196}));197198return <video ref={videoRef} src={props.src} />;199});200201function VideoApp() {202const playerRef = useRef<VideoPlayerHandle>(null);203204const handlePlay = () => {205playerRef.current?.play();206};207208const handlePause = () => {209playerRef.current?.pause();210};211212const showCurrentTime = () => {213const time = playerRef.current?.getCurrentTime();214alert(`Current time: ${time}s`);215};216217return (218<div>219<VideoPlayer ref={playerRef} src="/video.mp4" />220<button onClick={handlePlay}>Play</button>221<button onClick={handlePause}>Pause</button>222<button onClick={showCurrentTime}>Show Time</button>223</div>224);225}226```227228## Ref Patterns229230### Callback Refs231232```typescript233import React, { useState, useCallback } from "react";234235function CallbackRefExample() {236const [height, setHeight] = useState(0);237238const measuredRef = useCallback((node: HTMLDivElement | null) => {239if (node !== null) {240setHeight(node.getBoundingClientRect().height);241}242}, []);243244return (245<div>246<div ref={measuredRef}>247This div's height is {height}px248</div>249</div>250);251}252```253254### Ref Array Pattern255256```typescript257import React, { useRef, useEffect } from "react";258259function ListWithRefs() {260const itemRefs = useRef<(HTMLLIElement | null)[]>([]);261const items = ["Item 1", "Item 2", "Item 3"];262263useEffect(() => {264// Focus the second item265itemRefs.current[1]?.focus();266}, []);267268return (269<ul>270{items.map((item, index) => (271<li272key={item}273ref={(el) => itemRefs.current[index] = el}274tabIndex={0}275>276{item}277</li>278))}279</ul>280);281}282```283284### Conditional Refs285286```typescript287import React, { useRef, useState } from "react";288289function ConditionalRefExample() {290const [showInput, setShowInput] = useState(false);291const inputRef = useRef<HTMLInputElement>(null);292293const handleToggle = () => {294setShowInput(!showInput);295296// Focus input when it becomes available297setTimeout(() => {298inputRef.current?.focus();299}, 0);300};301302return (303<div>304<button onClick={handleToggle}>305{showInput ? "Hide" : "Show"} Input306</button>307{showInput && (308<input309ref={inputRef}310type="text"311placeholder="I will be focused"312/>313)}314</div>315);316}317```318319### Ref with Custom Hook320321```typescript322import React, { useRef, useLayoutEffect, useState } from "react";323324function useElementSize<T extends HTMLElement = HTMLDivElement>() {325const ref = useRef<T>(null);326const [size, setSize] = useState({ width: 0, height: 0 });327328useLayoutEffect(() => {329const element = ref.current;330if (!element) return;331332const updateSize = () => {333const rect = element.getBoundingClientRect();334setSize({ width: rect.width, height: rect.height });335};336337updateSize();338339const resizeObserver = new ResizeObserver(updateSize);340resizeObserver.observe(element);341342return () => resizeObserver.disconnect();343}, []);344345return { ref, size };346}347348function ResizableDiv() {349const { ref, size } = useElementSize<HTMLDivElement>();350351return (352<div353ref={ref}354style={{355width: "50%",356height: "200px",357backgroundColor: "lightblue",358resize: "both",359overflow: "auto"360}}361>362Size: {size.width} × {size.height}363</div>364);365}366```367368## Types369370### Ref-Related Types371372```typescript { .api }373type Ref<T> = RefCallback<T> | RefObject<T> | null;374375type RefCallback<T> = (instance: T | null) => void;376377interface RefObject<T> {378readonly current: T | null;379}380381interface MutableRefObject<T> {382current: T;383}384385interface RefAttributes<T> {386ref?: Ref<T>;387}388389interface ClassAttributes<T> extends Attributes {390ref?: Ref<T>;391}392393type ForwardRefExoticComponent<P> = NamedExoticComponent<P> & {394render: (props: P, ref: any) => ReactElement | null;395};396397type PropsWithoutRef<P> = P extends any ? ('ref' extends keyof P ? Pick<P, Exclude<keyof P, 'ref'>> : P) : P;398399type PropsWithRef<P> = P extends any ? P & { ref?: Ref<any> } : P;400```