我正在寻找一个解决方案,用react useRef()
钩子获取DOM元素数组。
例如:
const Component = () =>
{
// In `items`, I would like to get an array of DOM element
let items = useRef(null);
return <ul>
{['left', 'right'].map((el, i) =>
<li key={i} ref={items} children={el} />
)}
</ul>
}
我如何才能做到这一点?
8条答案
按热度按时间qvk1mo1f1#
useRef
只是部分类似于React的ref
(只是对象的结构,只有current
字段)。useRef
钩子的目标是在渲染之间存储一些数据,并且更改这些数据不会触发重新渲染(不像useState
那样)。也只是温柔的提醒:最好避免在循环或
if
中初始化钩子。这是钩子的第一条规则考虑到这一点,我们:
1.创建数组并在渲染之间保存它
1.我们通过
createRef()
初始化每个数组的元素1.我们可以使用
.current
表示法来引用列表这样我们就可以安全地修改数组(比如通过改变它的长度)。但是不要忘记,改变
useRef
存储的数据不会触发重新渲染。因此,为了改变长度以重新渲染,我们需要涉及useState
。另外,不要在第一次渲染时尝试访问
refs.current[0].current
-这将引发错误。说
所以你要么把它当作
或者在
useEffect
钩子中访问它。原因:ref
s是在元素渲染之后绑定的,所以在渲染期间第一次运行,它还没有初始化。edqdpe6u2#
我将对skyboyer's answer进行一点扩展。为了优化性能(并避免潜在的奇怪bug),您可能更喜欢使用
useMemo
而不是useRef
。因为useMemo接受回调函数作为参数而不是值,所以React.createRef
只会在第一次渲染后初始化一次。在回调函数中,您可以返回一个createRef
值的数组,并适当地使用该数组。初始化:
这里的空数组(作为第二个参数)告诉React只初始化一次refs。如果ref count改变了,您可能需要将
[x.length]
作为“一个deps数组”传递,并动态创建ref:Array.from({ length: x.length }).map(() => createRef()),
用法:
ahy6op9u3#
获取父引用并操纵子引用
我这样做,我认为这比其他建议的答案更简单。
toiithl64#
你可以将每个Map项分离到组件,而不是使用引用数组或类似的东西。当你把它们分开时,你可以独立使用
useRef
s:gxwragnw5#
如果你提前知道数组的长度,你可以简单地创建一个refs数组,然后通过它们的索引分配每个refs:
hl0ma9xz6#
我遇到了这样的问题,读了Joer的答案,意识到你可以循环使用索引动态设置querySelector类,只设置一个引用到整个父类。很抱歉代码的负载,但希望这对某人有所帮助:
yvt65v4c7#
我知道晚了,但我遇到了一个解决方案使用。我认为是天才的孩子节点。我不是100%确定它在你的用例中有效,但对我来说是完美的:
这里的关键是最后的
forEach
,其中每个引用都是基于navItem状态作为navBar的子节点来分配的,而不是静态分配的。我还应该注意这是NextJS/TypeScript的摘录。vojdkbi08#
在这种情况下,您需要创建一个空refs数组,并在React组件内部生成refs时推送它们。
然后使用useEffect处理相应的refs。
下面是一个例子: