Apparently you can't store React refs in an array. For some reason they get wiped out, so if you need to store a collection of refs, you have to do something like this (forgive me lord, for I hath sinned):
import React from 'react'
const collection = ["label 1", "label 2"]
class SinFactory extends React.Component {
constructor(props) {
super(props)
this.ref0 = React.createRef()
this.ref1 = React.createRef()
}
render() {
return (
<div>
{collection.map((label, i) => {
return <div key={label}
ref={this[`ref${i}`]}>{label}
</div>
})}
</div>
)
}
}
It's truly filthy, but it works.
☝️ Be sure to check out Sharesecret, which makes it easy to securely share sensitive data.
Top comments (8)
I tried just now, setting
this.myRef = [];
and using callbacksref={(ref) => { this.myRef[someval] = ref; return true; }}
- everything worked perfectly.Thanks, this was helpful. If anyone else out there wants to do this with TypeScript and hooks, this worked like a charm for me:
const tentRefs = useRef<(HTMLDivElement | null)[]>([])
<div className="name-tent" key={studentId} ref={(ref) => { tentRefs.current.push(ref) }}>
It worked for me as well. This is really cool. I have never used ref in loop and was facing issues, but with your help it rocked. Thanks!!
hello, how can i access stored values in myRef, like say what if i want to access next myRef value on currnet myRef, what should i do there? myRef.nextItem ?
How about using a combination of
useRef
andcreateRef
?The first rule of hooks states we can't call hooks (
useRef
) in a loop, but we can callcreateRef
in a loop.The array of refs (from
createRef
) will not trigger renders and stay in place between renders because it's safely stored in the.current
created byuseRef
.Using this way, we don't need to know how many refs we need to create upfront and it's a bit less noise (perhaps at the price of a little less clarity). Any downsides with this?
I used callback refs by creating an empty array in the parent
elementRefs = [];
and then while iterating over the child components, I passed a function to the ref attributeref={el => this.elementRefs[index] = el}
. This way, it executes the function in the child, but it has elementRefs in its scope and add itself to the array. So at the end, you end up with an arrayelementRefs
with all the ref elements in it.Really? I have a bunch (50+) of buttons to scroll to and I wanted to use refs for those. What a pain.
There's a solution with hooks: stackoverflow.com/a/56063129/7982963