HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptreactCritical

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

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
hooksmultipleuserefswithforelementscanhowarray

Problem

As far as I understood I can use refs for a single element like this:



const { useRef, useState, useEffect } = React;

const App = () => {
const elRef = useRef();
const [elWidth, setElWidth] = useState();

useEffect(() => {
setElWidth(elRef.current.offsetWidth);
}, []);

return (


Width is: {elWidth}


);
};

ReactDOM.render(
,
document.getElementById("root")
);








How can I implement this for an array of elements? Obviously not like that: (I knew it even I did not try it:)



const { useRef, useState, useEffect } = React;

const App = () => {
const elRef = useRef();
const [elWidth, setElWidth] = useState();

useEffect(() => {
setElWidth(elRef.current.offsetWidth);
}, []);

return (

{[1, 2, 3].map(el => (

Width is: {elWidth}

))}

);
};

ReactDOM.render(
,
document.getElementById("root")
);








I have seen this and hence this. But, I'm still confused about how to implement that suggestion for this simple case.

Solution

A ref is initially just { current: null } object. useRef keeps the reference to this object between component renders. current value is primarily intended for component refs but can hold anything.

There should be an array of refs at some point. In case the array length may vary between renders, an array should scale accordingly:
const arrLength = arr.length;
const [elRefs, setElRefs] = React.useState([]);

React.useEffect(() => {
// add or remove refs
setElRefs((elRefs) =>
Array(arrLength)
.fill()
.map((_, i) => elRefs[i] || createRef()),
);
}, [arrLength]);

return (

{arr.map((el, i) => (

...

))}

);


This piece of code can be optimized by unwrapping useEffect and replacing useState with useRef but it should be noted that doing side effects in render function is generally considered a bad practice:
const arrLength = arr.length;
const elRefs = React.useRef([]);

if (elRefs.current.length !== arrLength) {
// add or remove refs
elRefs.current = Array(arrLength)
.fill()
.map((_, i) => elRefs.current[i] || createRef());
}

return (

{arr.map((el, i) => (

...

))}

);

Context

Stack Overflow Q#54633690, score: 174

Revisions (0)

No revisions yet.