What is React.createRef()?
React's createRef() method is a built-in function that creates a reference object capable of holding a reference to a DOM element or a class component instance. Introduced with React 16.3, createRef() provides a way to access React components and DOM elements directly, bypassing the typical React data flow. Unlike state management that triggers re-renders, refs provide direct access without causing updates, making them ideal for imperative operations.
The reference object returned by createRef() contains a single property called current. When you attach a ref to a React element using the ref attribute, React sets the current property to the corresponding DOM node or component instance. This enables direct manipulation of the underlying element through the ref object.
The Evolution of References in React
Before refs were introduced, developers had to use string refs (like ref="myInput") which had several limitations including difficulty with type checking and issues with passing refs through higher-order components. React 16.3 introduced the callback ref pattern and createRef() as a more robust solution. The introduction of React Hooks later brought useRef(), which serves a similar purpose but is designed for functional components.
Syntax and Return Value
The createRef() function accepts no parameters and returns a new ref object with an initial current value of null. When called, createRef() always returns a brand new reference object with its own current property. This behavior differs from useRef(), which returns the same object on every render. Teams working on React application development should understand these differences when choosing between class and functional component patterns.
1import React, { createRef } from 'react';2 3class MyComponent extends React.Component {4 myRef = createRef();5 6 render() {7 return <input ref={this.myRef} />;8 }9}Creating and Attaching Refs
Basic Ref Creation Pattern
In class components, refs are typically created as class properties using class field syntax. This ensures the ref is available throughout all lifecycle methods of the component. The pattern works because class properties are initialized when the class is instantiated, before render() is called. This means the ref is ready to receive the DOM element when the component mounts.
Multiple Refs in a Component
When a component needs to reference multiple elements, create a separate ref for each. This approach provides clear, named references to each element, making the code self-documenting and easy to maintain.
Refs in Constructor
For projects not using class field syntax, refs can be created in the constructor. Both patterns are valid; the choice depends on project configuration and coding style preferences.
1import React, { createRef, Component } from 'react';2 3class AutoFocusInput extends Component {4 inputRef = createRef();5 6 componentDidMount() {7 this.inputRef.current.focus();8 }9 10 render() {11 return (12 <input13 type="text"14 ref={this.inputRef}15 placeholder="Auto-focused on mount"16 />17 );18 }19}Practical techniques for direct DOM access
Focus Management
Automatically focus form elements on mount, validate fields, and guide users through forms with precise focus control.
Element Measurements
Access element dimensions, positions, and viewport information for responsive designs and layout calculations.
Scroll Control
Programmatically scroll elements into view, implement auto-scroll features, and create smooth scrolling experiences.
Media Control
Control audio and video playback, manage volume, seek to positions, and sync media with other components.
Understanding useRef vs createRef
Key Differences
Both useRef() and createRef() create ref objects, but they behave differently across renders. The useRef() hook returns the same ref object on every render, making it more memory-efficient for functional components. When you call createRef() in a class component, it creates a brand new ref each time.
When to Use Each
Use createRef() when:
- Working with class components
- You explicitly need a new ref each render (rare)
- Integrating with legacy code that uses class components
Use useRef() when:
- Working with functional components
- You want a stable reference across renders
- Storing any mutable value that shouldn't trigger re-renders
- Implementing performance optimizations
For teams modernizing their React applications, migrating from class components to functional components with hooks typically involves replacing createRef() with useRef() to maintain reference stability across renders. Our web development services team specializes in React migration and modernization projects.
| Aspect | useRef() | createRef() |
|---|---|---|
| Component Type | Functional components | Class components |
| Object Identity | Same object on every render | New object each call |
| Use Case | Persistent values, DOM refs | DOM refs, instance refs |
| Memory Efficiency | Higher (reuses object) | Lower (creates new objects) |
Common Use Cases
Timer and Interval Management
Refs are ideal for storing timer IDs that need to be cleared. Using a ref to store the timer ID ensures it persists across renders and can be properly cleaned up when the component unmounts.
Third-Party Library Integration
Many third-party libraries require direct DOM access. Refs provide the bridge between React's virtual DOM and the imperative APIs of libraries like D3.js, Chart.js, or map libraries. This pattern is essential for integrating React with visualization tools in modern web applications that require sophisticated data presentation.
Imperative Animations
When using animation libraries or CSS animations that need imperative triggers, ref-based animation triggers give you precise control over when animations occur. Building interactive user interfaces often requires these imperative patterns to deliver polished user experiences.
1class TimerComponent extends Component {2 timerRef = createRef();3 state = { elapsed: 0 };4 5 componentDidMount() {6 this.timerRef.current = setInterval(() => {7 this.setState(prevState => ({8 elapsed: prevState.elapsed + 19 }));10 }, 1000);11 }12 13 componentWillUnmount() {14 clearInterval(this.timerRef.current);15 }16 17 render() {18 return (19 <div>20 <p>Time elapsed: {this.state.elapsed} seconds</p>21 </div>22 );23 }24}Best Practices and Patterns
Null Safety
Always verify that current is not null before accessing it, as refs may not be assigned immediately. Refs are only assigned after the component mounts and the element is rendered. During initial render and before mount, current will be null.
Cleanup in componentWillUnmount
Always clean up refs in componentWillUnmount to prevent memory leaks. Clear intervals, remove event listeners, and destroy third-party instances to ensure resources are released when components unmount. Proper cleanup ensures resources are released when components unmount, preventing memory leaks and unexpected behavior.
Avoiding Overuse of Refs
Refs should be a last resort when React's declarative approach won't work. Avoid using refs for anything that can be done declaratively with state, transforming data, or accessing component props. The React documentation emphasizes that refs are an "escape hatch" for cases where you need to work outside the normal React data flow. Our frontend development team follows these best practices to build maintainable React applications that leverage React's declarative model wherever possible.
Ref Forwarding with Class Components
While forwardRef is typically used with functional components, class components can participate in ref forwarding patterns through composition, allowing parent components to control child component internals through refs.
Frequently Asked Questions
Sources
- LogRocket: How to use React createRef - Comprehensive tutorial covering createRef() for DOM manipulation in React class components
- Hygraph: React useRef() - A complete guide - In-depth guide covering useRef hook with createRef comparison
- TutorialsPoint: React createRef() method - Clear explanation of createRef() syntax and class component examples