DEV Community

Matthew Claffey
Matthew Claffey

Posted on • Originally published at Medium on

Storing an array of elements using the useRef hook

Storing an array of elements using the useRef hook
React refs are useful for when we have to set focus to an element after the user has interacted with it. In my case, I needed to use refs for setting focus to the correct accordion item when I selected/used arrow keys.

The problems I faced while doing this was a mixture of having issues with passing down refs into my components but also having one ref that represented an array of items just as you would in a none react app using document.querySelectorAll().

The problem

When there is only one ref we tend to simply assign our ref value with the variable that creates the useRef function.

const item = useRef(null)

<div ref={item}/>
Enter fullscreen mode Exit fullscreen mode

In my use case I could not simply assign my ref to the element because the ref was being assigned within a map during the render. This would mean that the very last item in the array would be the element assigned to item.current.

The solution

The ref prop gives us the element as a parameter which allows us to assign the element however we want. In the example, we push that element into the itemsEls.current array so it can be used further down the line.

const itemEls = useRef(new Array())

{items.map(item => (
 <p key={item} ref={(element) => itemEls.current.push(element)}>{item}</p>
))
Enter fullscreen mode Exit fullscreen mode

Note: The same approach applies for an object with ids as a key.

const itemEls = useRef({})

{items.map((item, index)) => (
 <p key={item} ref={(element) => itemEls.current[index] = element}>{item}</p>
))
Enter fullscreen mode Exit fullscreen mode

And thats it! We can now store an array of refs in one variable to use when the use case crops up.

Note: this example of assigning a ref to a p tag is purely for simplicity of the code. A good use case for this is when building things that need focus applying to them when the user interacts with the component like an Accordion/Tabs/Modal.

import React, { useRef, useEffect } from 'react'
export const Component = ({ items }) => {
  const itemsEls = useRef(new Array())

  return (
    {items.map((item) => {
      const getRef = (element) => (itemsEls.current.push(element))
      return <p key={getRef}>{item}</p>
    })}
  )
}
Enter fullscreen mode Exit fullscreen mode

Thank you for reading.

Top comments (1)

Collapse
 
pham profile image
pham

I was originally using useState(new Array()) to store elements, however it only stored the last element of my list, even after I had .pushed() multiple refs. Do you know why this happens?

Your post has helped me to solve my problem with useRef([]), thank you!