我在一个应用程序中有一个很大的项目列表,所以它是使用react-virtuoso提供的虚拟列表呈现的。列表本身的内容根据一个单独组件所做的API调用而改变。我试图实现的是,每当一个新项目添加到列表中时,列表会自动滚动到该项目,然后将其高亮显示一秒钟。
我设法想出的办法是让另一个组件将新创建项的id放在虚拟列表可以访问的上下文中。
function MyList(props) {
const { collection } = props;
const { getLastId } useApiResultsContext();
cosnt highlightIndex = useRef();
const listRef = useRef(null);
const turnHighlightOff = useCallback(() => {
highlighIndex.current = undefined;
}, []);
useEffect(() => {
const id = getLastId();
// calling this function also resets the lastId inside the context,
// so next time it is called it will return undefined
// unless another item was entered
if (!id) return;
const index = collection.findIndex((item) => item.id === if);
if (index < 0) return;
listRef.current?.scrollToIndex({ index, align: 'start' });
highlightIndex.current = index;
}, [collection, getLastId]);
return (
<Virtuoso
ref={listRef}
data={collection}
itemContent={(index, item) => (
<ItemRow
content={item}
toHighlight={highlighIndex.current}
checkHighlight={turnHighlightOff}
/>
)}
/>
);
}
我在这里使用useRef
而不是useState
,因为使用状态会破坏整个过程-我猜是因为Virtuouso在滚动时实际上不会重新渲染。使用useRef
,一切都运行良好。在ItemRow
中,高亮显示是这样管理的:
function ItemRow(props) {
const { content, toHighlight, checkHighligh } = props;
const highlightMe = toHighlight;
useEffect(() => {
toHighlight && checkHighlight && checkHighligh();
});
return (
<div className={highlightMe ? 'highligh' : undefined}>
// ... The rest of the render
</div>
);
}
在CSS中,我为highligh
类定义了一个1秒的动画,其中background-color
发生了变化。
到目前为止,一切都完全按照我的想法运行,除了一个我不知道如何解决的问题:如果列表滚动到帧外的一行,高亮显示会很好地工作,因为该行会被渲染。但是,如果该行已经在帧内,react-virtuoso不需要渲染它,因此,因为我使用的是ref而不是state,高亮显示永远不会被调用。正如我上面提到的,使用useState
破坏了整个过程,所以我最终使用useRef
。但我不知道如何在所需行已经在视图中时强制重新呈现它。
1条答案
按热度按时间7cwmlq891#
我“有点”解决了这个问题。我的解决方案不是最好的,在一些罕见的情况下,没有突出显示行,因为我想要的,但这是我能想出的最好的,除非有人在这里有更好的主意。
解决方案的核心是改变上下文公开的
getLastId
背后的思想。以前,只要useEffect
中的组件绘制了id,它就会将id重置回undefined
。现在,上下文公开了两个函数-一个函数用于获取id,另一个函数用于重置id。基本上,getLastId
和resetLastId
在幕后操纵一个ref对象,而不是一个状态,以防止不必要的渲染。现在,MyList
组件看起来像这样:现在,在
useEffect
中设置highlightIndex
处理视口之外的项,而将getLastId
调用提供给每个ItemRow
的属性处理视图中已经存在的项。