How to use multiple refs for an array of elements with React Hooks

To understand how to use multiple references with React Hooks, we'll start with a simple example using a single reference.

Single reference

A simple <input/> element looks like:

jsx
import { useEffect, useRef, useState } from react;

const SimpleInput = () => {
    
    const inputRef = useRef(null);
    
    useEffect( () => {
    
        inputRef.current.focus();
    
    }, []);
    
    return(
        <div className = 'Input'>
            <input ref = {inputRef} placeholder = 'Name'></input>
        </div>
    );
    
}

export default SimpleInput;

The <input/> will focus after DOM is loaded. If you execute console.log(inputRef):

jsx
{current: input}

inputRef is an object with a single current property.

Multiple references

But what would happen with an undetermined array of <input/>?

We need to define inputRef as an array, so that current property becomes an array as well.

jsx
import { useEffect, useRef, useState } from react;

const ArrayInputs = () => {
    
    // The number of references is undetermined
    // After fetching data, we can determine array's length
    const inputRef = useRef([]);
    
    // Data is empty before fetching
    const [data, setData] = useState([]);
    
    useEffect( () => {
    
        // We will fetch data and receive an array
        // let data = fetchData();
        // To simplify, let's suppose that the array is:
        let data = ['Name', 'Age', 'Gender'];
        
        // We define the size of array after receiving the data
        inputRef.current = new Array(data.length);
        
        // We set state
        setData(data);
    
    }, []);
    
    useEffect( () => {
        
        // If data is filled -> focus
        if(data.length !== 0) {
            
            // Focusing the last <input></input>
            inputRef.current[data.length - 1].focus();
            
        }
        
    }, [data]);
    
    return(
        
        <div className = 'Inputs'>
            {data.map((element, i) => <input ref = {el => inputRef.current[i] = el} placeholder = {element}></input>)}
        </div>
    
    );

}

export default ArrayInputs;

The last <input/> will focus after DOM is loaded.

If you execute console.log(inputRef):

jsx
{current: [input, input, input]}

Now, inputRef is an object with an array as current property. We can access to a single reference by writing inputRef.current[i].

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.