How to use useRef to access items on a list

The useRef hook is a handy tool in React that lets you create references to elements or values within functional components. It allows you to access and modify DOM elements directly, store mutable values, or preserve data between renders without causing re-renders. It’s like having a special pointer that you can use to interact with specific parts of your user interface. Whether you want to work with form fields, manage focus, or cache values, useRef helps you take full control over certain elements or data in your React applications.

But, in this post, I am NOT going to show you how to use the useRef hook and the ref property in a form. We are going to explore how to use the useRef hook in a list. How you can access the DOM elements on a list with useRef and the ref property.

A typical useRef use case

If you have worked with useRef before, I am sure you must have applied it to access DOM elements. Most of the time, we use it to access input elements to get the value or set the focus.

import React, { useRef } from 'react';

function App() {
  const inputRef = useRef();

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

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={handleClick}>Focus Input</button>
    </div>
  );
}

export default App;

But, have you ever used the useRef hook to access items in a list? Yes, you can do that too. However, it is somewhat different in the way you use it. let’s explore it more.

How to apply useRef in a list

How you might attempt: It works, but…

Imagine we have a CRUD application in which we want the user to remove items in a list by clicking on the “delete” button. Let’s assume, you would have the following UI.

useRef-with-a-list

If you are already familiar with using useRef in a form, you might be tempted to use it and references as below in a list in React apps.

import { useState , useRef } from 'react'


function App() {
  const [ items, setItems] = useState(["United States","India","Germany"]);
  const listItem = useRef(); 
 
  return (<>{   
         items.map( ( item, index ) => <li  ref={ listRef} key={ index }>{ item }<span>
          <button onClick={ ()=> listItem.current.remove() }>delete</button></span></li>)       
      }  
    </>
  )
}

export default App

Will this work? Yes, It will, but not necessarily the way you want. 

The reason for this is that `useRef` does not create unique references for each item. It will create the same reference for all the items because the reference (itemRef) created with useRef is overwritten in each iteration of the items.map() function. As a result, the reference will only point to the last rendered <li> element. Thus, when you click on any item, it will delete only the last item.

How to use useRef in a list: The correct way

The basic idea when using useRef on a list is that you need to have references for each item on the list. So, how are we going to do this? We can create an array of references dynamically for each item on the list. After that, you can use this reference to access a particular item on the list.

import { useState , useRef } from 'react'


function App() {
  const [ items, setItems] = useState(["United States","India","Germany"]);
  const listRef= useRef(); 
 
  return (<>
      {
        items.map( ( item, index ) =><li  ref={ element => listRef.current[index] = element } key={ index } >
          { item }

          //remove list item on a button click.Not important to understand the main concept
          <span><button onClick={ ()=> listRef.current[index ].remove() }>delete</button></span>
        </li>)              
      }  
    </>)
}

export default App

In the above code, the most important part you should understand is bolded. Let us see what happens here.

take look at <li  ref={ element => listRef.current[index] = element  } key={ index } >

Here the element is a reference to the DOM element that is created for each item in the items array. The ref prop is used to set the value of the current property of the listRef` variable, which is an array. This means that the current property of listRef will be an array of DOM elements, one for each item in the items array.

You can breakdown the code above as follows (let’s say under the hood ) :

items.map( ( item, index ) => { 
 // Create a reference to the DOM element that will be created for this item. 
    const element = React.createRef();
         
 //Set the value of the current property of listRef to an array that contains the 'element' reference. 
    listRef.current[index] = element

// Return a li element with the item variable as its content. 
 return ( <li key={ index } ref={ element }> { item } </li> ); 
})

Wrapping up

I really hope this article can assist you in understanding how to effectively use useRef in lists. Basically, what you did was create an array of references for the list items. By doing so, you were able to easily access and manipulate those items using the array.


Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top