Refs and DOM

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.

What are Refs?

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:

  • Manage focus, text selection, or media playback.
  • Trigger imperative animations.
  • Integrate with third-party DOM libraries.

Creating Refs

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 (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus the input</button>
    </div>
  );
}

				
			

Explanation

  • We import useRef from React.
  • We create a ref using useRef(null).
  • We attach this ref to an input element using the ref attribute.
  • On button click, we use the ref to focus the input.

Output

When the button is clicked, the input field receives focus.

Accessing DOM Elements using Refs

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 (
    <div>
      <video ref={videoRef} width="600">
        <source src="movie.mp4" type="video/mp4" />
        Your browser does not support the video tag.
      </video>
      <div>
        <button onClick={playVideo}>Play</button>
        <button onClick={pauseVideo}>Pause</button>
      </div>
    </div>
  );
}

				
			

Explanation

  • A video element is referenced using useRef.
  • The ref is used to control the video playback by calling play() and pause() methods.

Output

Clicking the “Play” button starts the video, and clicking the “Pause” button stops it.

Callback Refs

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 (
    <div>
      <div ref={measureHeight} style={{ height: '100px', background: 'lightblue' }}>
        Measure my height
      </div>
      <p>The height of the div is: {height}px</p>
    </div>
  );
}

				
			

Explanation

  • A function measureHeight is defined to set the height of a div.
  • This function is passed as the ref attribute.
  • When the div mounts, the function is called with the div as an argument, allowing us to measure and store its height.

Output

The paragraph below the div displays its height.

useRef Hook

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 <div>Open the console to see the timer ticks.</div>;
}

				
			

Explanation

  • 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.

Output

A message “Timer tick” appears in the console every second.

Forwarding Refs

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) => (
  <button ref={ref} className="fancy-button">
    {props.children}
  </button>
));

function App() {
  const buttonRef = useRef(null);

  const handleClick = () => {
    buttonRef.current.focus();
  };

  return (
    <div>
      <FancyButton ref={buttonRef}>Click me!</FancyButton>
      <button onClick={handleClick}>Focus the Fancy Button</button>
    </div>
  );
}

				
			

Explanation

  • 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.

Output

Clicking “Focus the Fancy Button” will focus the FancyButton.

Using Refs for Component Communication

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 <div>Child Component</div>;
}

const ForwardedChildComponent = React.forwardRef(ChildComponent);

function App() {
  const childRef = useRef(null);

  const handleClick = () => {
    childRef.current.alertName();
  };

  return (
    <div>
      <ForwardedChildComponent ref={childRef} name="React" />
      <button onClick={handleClick}>Alert Child Name</button>
    </div>
  );
}

				
			

Explanation

  • React.useImperativeHandle customizes the instance value that is exposed when using ref.
  • The parent component can call alertName on the child component via the ref.

Output

Clicking “Alert Child Name” triggers an alert with the message “Hello, React!”.

Advanced Ref Usage

Managing Focus

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 (
    <div>
      <input ref={usernameRef} type="text" placeholder="Username" />
      <input ref={passwordRef} type="password" placeholder="Password" />
      <button onClick={handleLogin}>Login</button>
    </div>
  );
}

				
			

Explanation

  • useRef is used to reference the username and password input fields.
  • The handleLogin function checks the input values and sets focus accordingly.

Output

Focus will shift to the empty input field when the “Login” button is clicked.

Integrating with Third-Party Libraries

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 <canvas ref={chartRef}></canvas>;
}

				
			

Explanation

  • useRef is used to get a reference to the canvas element.
  • useEffect initializes a Chart.js bar chart on the referenced canvas element.

Output

A bar chart is rendered using Chart.js.

Summary

  • Refs provide a way to access and manipulate DOM nodes directly.
  • useRef Hook is used to create refs in functional components.
  • Callback Refs offer a more flexible approach.
  • Forwarding Refs allows passing refs through components.
  • useImperativeHandle customizes the ref instance value.
  • Refs are crucial for managing focus, triggering component methods, and integrating with third-party libraries.

Example 1: Managing Focus in a Form

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 (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>Login Form</h2>
      <form>
        <input ref={usernameRef} type="text" placeholder="Username" /><br /><br />
        <input ref={passwordRef} type="password" placeholder="Password" /><br /><br />
        <button type="button" onClick={handleLogin}>Login</button>
      </form>
    </div>
  );
}

export default App;

				
			

Explanation

  • Refs: useRef is used to create two refs, usernameRef and passwordRef, which are attached to the username and password input fields respectively.
  • Handling Focus: In the 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.
  • Login Logic: Upon successful validation (for demo purposes, just checking if fields are not empty), an alert is shown with the username.

Output:

  • When the “Login” button is clicked without filling in the username or password fields, focus shifts to the respective empty field.

Example 2: Integrating with a Third-Party Library (Chart.js)

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 (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>Bar Chart Example using Chart.js</h2>
      <canvas ref={chartRef} width="400" height="400"></canvas>
    </div>
  );
}

export default App;

				
			

Explanation

  • Chart.js Integration: We import Chart.js and create a useRef for the canvas element (chartRef).
  • useEffect Hook: The useEffect hook initializes a new Chart.js instance inside it, using the ctx obtained from chartRef.current.getContext('2d').
  • Rendering: The canvas element is rendered using the chartRef.

Output

  • Upon rendering, a bar chart is displayed using the data provided in the 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 !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India