如何滚动到通过 react-virtualized 呈现的 React 元素?
Posted
技术标签:
【中文标题】如何滚动到通过 react-virtualized 呈现的 React 元素?【英文标题】:How to scroll to React element which is rendered via react-virtualized? 【发布时间】:2021-11-27 17:20:24 【问题描述】:我正在使用react-virtualized 来防止在超出视图端口时加载长列表中的项目。但是,我在页面顶部有一个按钮,单击该按钮时,将滚动到使用 react-virtualized 呈现的项目。
它使用React.createRef()
将按钮与列表项链接,但由于渲染的项目在 dom 中不存在,所以引用是 null
(它适用于被渲染的前几个项目,但不适用于其余项目项目)。
例如,如果我单击按钮 20,则会收到错误 Cannot read properties of null (reading 'getBoundingClientRect')
because the ref of the button is null because it's counterpart ref doesn't exist
有没有办法滚动到在 react-virtualized 中渲染的项目?
我创建了一个代码沙箱here 来说明我的意思。
否则,这里是代码sn-p:
export default function App()
const onClick = (item) =>
window.scrollTo(
top: item.ref.current.getBoundingClientRect().top,
behavior: "smooth"
);
;
const items = arr.map((el) => (
ref: createRef(),
id: el.id
));
return (
<div className="App">
items.map((item) => (
<button onClick=(e) => onClick(item)>Scroll to item.id</button>
))
<WindowScroller>
( height, scrollTop, registerChild ) => (
<div ref=registerChild>
<AutoSizer disableHeight>
( width ) => (
<>
<List
autoHeight
width=width
height=height
rowHeight=100
rowRenderer=( index ) =>
return (
<div
ref=items[index].ref
id=`item-$items[index].id`
key=items[index].id
>
items[index].id
</div>
);
scrollTop=scrollTop
rowCount=items.length
overscanRowCount=100
/>
</>
)
</AutoSizer>
</div>
)
</WindowScroller>
</div>
);
【问题讨论】:
【参考方案1】:让我们使用 List 组件以虚拟化的方式呈现列表:
const listHeight = 600;
const rowHeight = 50;
const rowWidth = 800;
//...
<div className="list">
<List
width=rowWidth
height=listHeight
rowHeight=rowHeight
rowRenderer=this.renderRow
rowCount=this.list.length />
</div>
注意两件事。
首先,List 组件要求您指定列表的宽度和高度。它还需要行的高度,以便计算哪些行是可见的。
rowHeight 属性采用固定的行高或返回给定索引的行高的函数。
其次,组件需要行数(列表长度)和渲染每一行的函数。它不直接取列表。
【讨论】:
也许我遗漏了一些东西,但我不是已经在我的示例中提供了宽度、高度和列表长度吗?【参考方案2】:添加对您的<List>
的引用,并使用它滚动到项目的索引。
const listRef = React.createRef<List>();
function scrollToItem(item)
const index = calculateIndex(item) // figure out what index the item should have
listRef.current.scrollToItem(index) // second parameter here could be 'auto', 'smart', 'center', 'end', 'start'
return (
/* ... */
<List
ref=listRef
/* ... */
/>
/* ... */
)
【讨论】:
calculateIndex(item)
会返回什么?另一个参考?
不,应该是数字。你的 items 数组在 List 中呈现,我假设你有办法找出你想要的 item 所在的索引。
看来 scrollToItem 不是一个函数,因为我收到了错误 listRef.current.scrollToItem is not a function
。您确定从 createRef 创建的 ref 具有该方法还是应该来自其他地方?
这可能是您正在考虑的 react-native 方法吗?我在示例中使用的 List 组件是一个 Web 组件,它来自我在原始问题中链接的 react-virtualized 库
也许有点不同。我在我的项目中使用 react-virtualized 并且已经完成了你想做的事情。看起来我的列表是在“react-window”包中定义的。事实上,它是一个 FixedSizeList,我已将其别名为 List,所以我有点搞混了。但是查看 react-window 列表,看看是否对您有帮助?以上是关于如何滚动到通过 react-virtualized 呈现的 React 元素?的主要内容,如果未能解决你的问题,请参考以下文章
在我滚动之前,react-virtualized 列表项不会使用更改的道具重新渲染
react-virtualized WindowScroller 性能问题