DEV Community

Cover image for Callback Refs vs. useEffect: When to use which
Stefan Simic
Stefan Simic

Posted on

Callback Refs vs. useEffect: When to use which

In React, managing side effects and interacting with the DOM are crucial aspects of component development. Two powerful tools for this are useEffect and callback refs. While useEffect is a versatile hook for handling various side effects, callback refs offer a more direct and potentially more performant approach in specific scenarios.

Understanding Callback Refs

Callback refs provide a way to access the actual DOM element directly within a functional component. You pass a callback function to the ref attribute of an element. This callback function receives the DOM element as an argument, allowing you to:

  • Directly manipulate the DOM: Set focus, resize elements, apply styles, and more.
  • Interact with third-party libraries: Integrate with libraries that work directly on DOM elements (e.g., map libraries, canvas libraries).

When to Use Callback Refs

  • Direct DOM Manipulation:

    • When you need to set up or clean up DOM-related logic (e.g., focus management, resizing elements). -Callback refs provide direct access to the DOM element, allowing for precise and efficient manipulations.
  • Third-party Libraries:

    • When initializing or interacting with libraries that work directly on DOM elements (e.g., integrating with a map library, handling canvas interactions). -Callback refs enable you to pass the DOM element directly to the library's API.
  • Avoiding Re-render Dependencies:

    • When useEffect dependencies can cause unnecessary re-renders, potentially impacting performance.
    • By using callback refs, you can avoid including the DOM element itself in the useEffect dependency array, reducing the number of re-renders

Example: Focus Management

import React, { useRef } from 'react';

function InputWithFocus() {
  const inputRef = useRef(null);

  const handleRef = (element) => {
    if (element) {
      element.focus();
    }
  };

  return <input type="text" ref={handleRef} />;
}
Enter fullscreen mode Exit fullscreen mode

Scroll to Bottom Example

Callback Ref:

import React, { useState, useRef, useCallback } from 'react';

function Chat() {
  const [messages, setMessages] = useState([]);
  const messagesEndRef = useRef(null);

  const scrollToBottom = useCallback(() => {
    if (messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [messages]); 

  const handleSendMessage = () => {
    setMessages([...messages, "New Message"]); 
    scrollToBottom(); 
  };

  return (
    <div style={{ height: '300px', overflowY: 'auto' }}>
      {messages.map((message, index) => (
        <div key={index}>{message}</div>
      ))}
      <div style={{ float: "left", clear: "both" }} 
           ref={messagesEndRef} /> 
    </div>
    <button onClick={handleSendMessage}>Send</button>
  );
}
Enter fullscreen mode Exit fullscreen mode

useEffect:

import React, { useState, useEffect, useRef } from 'react';

function Chat() {
  const [messages, setMessages] = useState([]);
  const messagesEndRef = useRef(null);

  useEffect(() => {
    scrollToBottom();
  }, [messages]);

  const scrollToBottom = () => {
    if (messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  };

  const handleSendMessage = () => {
    setMessages([...messages, "New Message"]); 
  };

  return (
    <div style={{ height: '300px', overflowY: 'auto' }}>
      {messages.map((message, index) => (
        <div key={index}>{message}</div>
      ))}
      <div style={{ float: "left", clear: "both" }} 
           ref={messagesEndRef} /> 
    </div>
    <button onClick={handleSendMessage}>Send</button>
  );
}
Enter fullscreen mode Exit fullscreen mode

Choosing the Right Approach

  • For direct DOM manipulations and when avoiding unnecessary re-renders is crucial, callback refs are generally preferred.
  • For simpler scenarios or when performance is not a primary concern, useEffect can be a suitable choice.

By understanding the strengths of both callback refs and useEffect, you can make informed decisions about how to manage side effects and interact with the DOM in your React components effectively.

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs