In React, the concept of "Refs" provides a way to access and interact with DOM nodes directly. This is particularly useful for scenarios where you need to work with DOM elements directly, such as manipulating form elements, focusing on an input, or integrating with third-party libraries. This chapter will cover everything you need to know about Refs in React, from basics to advanced usage.
Refs (short for references) provide a way to access the underlying DOM nodes or React elements created in the render method. They are useful when you need to:
In functional components, we create refs using the useRef
hook. Here’s a basic example:
import React, { useRef } from 'react';
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
);
}
useRef
from React.useRef(null)
.input
element using the ref
attribute.When the button is clicked, the input field receives focus.
Refs can be used to directly access DOM elements and interact with them. This is useful for various tasks such as manipulating form elements or controlling media playback.
import React, { useRef } from 'react';
function VideoPlayer() {
const videoRef = useRef(null);
const playVideo = () => {
videoRef.current.play();
};
const pauseVideo = () => {
videoRef.current.pause();
};
return (
);
}
useRef
.play()
and pause()
methods.Clicking the “Play” button starts the video, and clicking the “Pause” button stops it.
Callback refs provide a more flexible way to handle refs. Instead of creating a ref with useRef
, you can define a function that React will call with the DOM element when the component mounts.
import React, { useState } from 'react';
function App() {
const [height, setHeight] = useState(0);
const measureHeight = (element) => {
if (element) {
setHeight(element.clientHeight);
}
};
return (
Measure my height
The height of the div is: {height}px
);
}
measureHeight
is defined to set the height of a div.ref
attribute.The paragraph below the div displays its height.
The useRef
hook is a fundamental part of managing refs in functional components. It returns a mutable object whose .current
property is initialized to the passed argument.
import React, { useRef, useEffect } from 'react';
function App() {
const timerRef = useRef(null);
useEffect(() => {
timerRef.current = setInterval(() => {
console.log('Timer tick');
}, 1000);
return () => clearInterval(timerRef.current);
}, []);
return Open the console to see the timer ticks.;
}
useRef
is used to store a reference to the timer.useEffect
sets up a timer on mount and cleans it up on unmount using the ref.A message “Timer tick” appears in the console every second.
Ref forwarding allows you to pass refs through components to access a child component’s DOM node.
import React, { forwardRef, useRef } from 'react';
const FancyButton = forwardRef((props, ref) => (
));
function App() {
const buttonRef = useRef(null);
const handleClick = () => {
buttonRef.current.focus();
};
return (
Click me!
);
}
forwardRef
is used to pass the ref down to the button
element in FancyButton
.useRef
is used to create a ref in the App
component, which is then passed to FancyButton
.Clicking “Focus the Fancy Button” will focus the FancyButton
.
Refs can also be used to trigger methods in child components.
import React, { useRef } from 'react';
function ChildComponent({ name }, ref) {
React.useImperativeHandle(ref, () => ({
alertName() {
alert(`Hello, ${name}!`);
}
}));
return Child Component;
}
const ForwardedChildComponent = React.forwardRef(ChildComponent);
function App() {
const childRef = useRef(null);
const handleClick = () => {
childRef.current.alertName();
};
return (
);
}
React.useImperativeHandle
customizes the instance value that is exposed when using ref
.alertName
on the child component via the ref.Clicking “Alert Child Name” triggers an alert with the message “Hello, React!”.
You can use refs to manage focus dynamically in forms and other interactive elements.
import React, { useRef } from 'react';
function LoginForm() {
const usernameRef = useRef(null);
const passwordRef = useRef(null);
const handleLogin = () => {
if (!usernameRef.current.value) {
usernameRef.current.focus();
} else if (!passwordRef.current.value) {
passwordRef.current.focus();
} else {
// Perform login
}
};
return (
);
}
useRef
is used to reference the username and password input fields.handleLogin
function checks the input values and sets focus accordingly.Focus will shift to the empty input field when the “Login” button is clicked.
When working with third-party libraries, refs can be used to access and manipulate DOM elements directly.
import React, { useRef, useEffect } from 'react';
import Chart from 'chart.js';
function ChartComponent() {
const chartRef = useRef(null);
useEffect(() => {
const ctx = chartRef.current.getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}, []);
return ;
}
useRef
is used to get a reference to the canvas
element.useEffect
initializes a Chart.js bar chart on the referenced canvas
element.A bar chart is rendered using Chart.js.
In this example, we’ll use refs to manage focus dynamically in a login form.
import React, { useRef } from 'react';
function App() {
const usernameRef = useRef(null);
const passwordRef = useRef(null);
const handleLogin = () => {
if (!usernameRef.current.value) {
usernameRef.current.focus();
} else if (!passwordRef.current.value) {
passwordRef.current.focus();
} else {
// Simulate login logic
alert(`Logged in as ${usernameRef.current.value}`);
}
};
return (
Login Form
);
}
export default App;
useRef
is used to create two refs, usernameRef
and passwordRef
, which are attached to the username and password input fields respectively.handleLogin
function, we check if either the username or password fields are empty. If so, we use the focus()
method on the respective ref to focus the input field.In this example, we’ll integrate Chart.js into a React component using refs to access the canvas
element.
import React, { useRef, useEffect } from 'react';
import Chart from 'chart.js/auto';
function App() {
const chartRef = useRef(null);
useEffect(() => {
const ctx = chartRef.current.getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}, []);
return (
Bar Chart Example using Chart.js
);
}
export default App;
useRef
for the canvas
element (chartRef
).useEffect
hook initializes a new Chart.js instance inside it, using the ctx
obtained from chartRef.current.getContext('2d')
.canvas
element is rendered using the chartRef
.datasets
.Refs are a powerful feature in React that allow you to interact with the DOM directly. They are essential for managing focus, integrating with third-party libraries, and handling imperative actions that are not covered by React's declarative approach. By understanding how to create and use refs, forward them, and manage their lifecycle, you can unlock a new level of interactivity and control in your React applications. Happy coding !❤️