Explain Codes LogoExplain Codes Logo

How can I use multiple refs for an array of elements with hooks?

javascript
prompt-engineering
useeffect
callback-refs
Anton ShumikhinbyAnton Shumikhin·Dec 23, 2024
TLDR

To handle multiple refs in a component array with hooks, employ the useRef hook and the .map() method. Initiate a unique ref for all elements as shown:

const MyComponent = () => { // Array of refs coming up! const elementCount = 10; // The amount of elements we're dealing with const refs = useRef([...Array(elementCount)].map(() => createRef())); return ( <> {refs.current.map((ref, index) => ( <div key={index} ref={ref}>Element {index}</div> ))} </> ); };

Each individual element obtains a unique ref, making these refs accessible later for any DOM operations.

Keeping dynamic ref arrays in check

When you have to tackle a dynamic array with a fluctuating number of items, useEffect steps in to ensure that your refs are synchronized:

useEffect(() => { // Let's make the refs array length match the items array like conjoined twins refs.current = refs.current.slice(0, items.length); }, [items.length]);

This chunk of code confirms that the refs array doesn't hoard unnecessary refs when your items array decides to shed some weight.

The ideal time to swing callback refs

Want to tug at the DOM right after rendering a component? Callback refs are your knights in shining armour in such battles:

const itemsRef = items.map(() => useRef(null)); // Initialize array of refs like giving out walkie talkies const setCallbackRef = (index) => (element) => { itemsRef[index].current = element; // Right here is the perfect spot to play around with DOM operations like a wizard }; // In JSX {items.map((item, index) => ( <div key={index} ref={setCallbackRef(index)}>...</div> ))}

Clearing up and reordering: how to manage refs

React kindly calls ref functions with null when components dismount. It’s crucial to tidy up:

useEffect(() => { return () => { // Time to clean the refs array. Grab your spray and cloth! refs.current.forEach(ref => { ref.current = null; }); }; }, []);

For cases involving potential reordering of items, the key prop becomes your best friend:

<ChildComponent key={item.uniqueId} ref={(el) => (itemsRef.current[index] = el)} />

Employing a unique id ensures that React can keep tabs on items even when they decide to play musical chairs.

Advanced techniques: stepping it up a notch

When managing an army of refs, these optimization strategies might come in handy:

  • Custom hooks: Wrap up the logic of managing refs for multiple elements, essentially tidying up repeated code.

  • Dealing with null refs: Post-render checks to sweep aside errors and rev up performance when you have optional elements:

// Invoke DOM operations only on non-null refs like skimming the cream off the top refs.current.filter(ref => ref.current).forEach(ref => { // Let's get those operations rolling! });

Styling, refs style

Styling based on index or refs can give you ironclad control over the look of each element:

{items.map((item, index) => ( <div key={index} ref={refs.current[index]} style={{ width: `${index * 10}%` }}>...</div> ))}

This will dynamically style each item with a width corresponding to its spot in the array.