我正在尝试将多个引用转发到多个子DOM节点:
我需要引用这7个按钮,因此可以在它们之间进行集中管理。
我尝试使用React.createRef()
数组,然后使用 index 将此数组的每个元素附加到子级,但是所有引用都指向最后一个按钮。
为什么并且还有其他解决方案?
class RestaurantsList extends Component {
references = Array(7).fill(React.createRef());
render() {
return (
<ul
id="restaurants-list"
role="menu"
>
{
this.props.restaurants.map((restaurant, index) => {
return (
<Restaurant
ref={this.references[index]}
name={restaurant.name}
/>
);
})
}
</ul>
);
}
}
const Restaurant = React.forwardRef((props, ref) => {
return (
<li>
<button
ref={ref}
>
{name}
</button>
</li>
);
})
答案 0 :(得分:2)
正如注释中所讨论的,最好的方法是将引用列表保留为父组件内的数组或对象属性。
对于Array.prototype.fill()
,其参数仅计算一次。因此,您需要使用.map()
来获取唯一的引用对象。
references = Array(7).fill(0).map(() => React.createRef());
无论如何,在现实世界中,这宁愿发生在constructor()
或componentDidUpdate()
中。
但是我认为最好使用哈希图:
references = {};
getOrCreateRef(id) {
if (!this.references.hasOwnProperty(id)) {
this.references[id] = React.createRef();
}
return this.references[id];
}
render() {
return (
....
{
this.props.restaurants.map((restaurant, index) => {
return (
<Restaurant
ref={this.getOrCreateRef(restaurant.id)}
key={restaurant.id}
name={restaurant.name}
/>
);
})
}
此外,您将需要一些辅助方法来避免将this.references
暴露于外界:
focusById(id) {
this.references[id] && this.references[id].focus();
}
并特别注意清理对未安装元素的引用。否则,如果动态更改餐厅列表,则可能会发生内存泄漏(如果ref
停留在this.references
中,即使它已分离,它也会继续引用HTML元素)。实际需要取决于组件的使用方式。同样,一旦由于导航而将具有reference = {}
的容器自身卸载,此内存泄漏将得到修复。