我正在使用react-custom-scrollbar
并希望将其与FixedSizeList
集成。
我已经在react-virtualized
上检查了关于此问题的解决方案: https :
但是代码在此函数中抛出错误: Uncaught TypeError: Cannot read property 'handleScrollEvent' of undefined
滚动显示:
handleScroll = ({ target }) => {
const { scrollTop, scrollLeft } = target;
const { Grid: grid } = this.List;
grid.handleScrollEvent({ scrollTop, scrollLeft });
}
我在fixedSixe <List
组件上添加了ref={ instance => { this.List = instance; } }
。
该库和react-virtualized
是完全不同的实现。 您在react-virtualized
问题上看到的一般技术通常可以提供有关如何处理某事的有用提示,但是像这样的特定实现细节不适用。 (在react-virtualized
, List
装饰Grid
组件。在react-window
它们是独立的组件,以提高性能和尺寸。)
我不知道像react-custom-scrollbar
是否可以与react-window
因为我从未尝试过。 说实话,这并不是我很感兴趣的支持,因为我认为自定义滚动条通常是一个坏主意,因为它们会影响性能。 所以我要解决这个问题。
但是,如果您有后续问题,我们可以继续聊天😄
我会对此有所了解,我对使用react-window
感兴趣,因为它是轻量级的,可以解决我的问题。 即使我不喜欢使用自定义滚动条,但它不在我手中,我们需要滚动条的自定义设计。
在最坏的情况下,我将使用react-virtualized
。
谢谢 :)
@ Rahul-Sagore最后是否获得了与react-window
一起使用的自定义滚动条?
不,没有时间。 需要检查并弄清楚。
不知道@bvaughn是否批准了此方法,但它似乎可以工作: https : //codesandbox.io/s/00nw2w1jv
更好的方法是将Scrollbars
作为outerElementType
const CustomScrollbars = ({ onScroll, forwardedRef, style, children }) => {
const refSetter = useCallback(scrollbarsRef => {
if (scrollbarsRef) {
forwardedRef(scrollbarsRef.view);
} else {
forwardedRef(null);
}
}, []);
return (
<Scrollbars
ref={refSetter}
style={{ ...style, overflow: "hidden" }}
onScroll={onScroll}
>
{children}
</Scrollbars>
);
};
const CustomScrollbarsVirtualList = React.forwardRef((props, ref) => (
<CustomScrollbars {...props} forwardedRef={ref} />
));
// ...
<FixedSizeList
outerElementType={CustomScrollbarsVirtualList}
{...rest}
/>
我喜欢使用outerElementType
或innerElementType
可以进行多少高级操作
我正在尝试检测react-window底部的滚动位置。
是否可以? 您对此有什么想法吗? 我想要一个codeandbox示例。
您应该能够使用可用的ref道具向列表询问其scrollHeight
@rufoot。
我尝试在道具中使用scrollHeight
。 但我认为其中没有scrollHeight
属性。
@bvaughn您
scrollToRow200Auto = () => {
this.listRef.current.scrollToItem(200);
console.log("current position = ", this.listRef.current.props.scrollHeight)
};
当前位置=未定义
@rufoot这样的东西https://codesandbox.io/s/4zjwwq98j4吗?
https://codesandbox.io/embed/jzo2lool2y
当您向下滚动到反应窗口的底部时,您会看到一个警报。
@piecyk我已经用outerElementType
尝试了您的解决方案,但它太慢了,您是否经过了实战测试?:D
我已经尝试过react-scrollbars-custom
。 它不那么迟钝,但仍然很迟钝。 有人使用自定义滚动条有滞后问题吗?
@ jancama2尚未对它进行战斗测试😂当代码沙箱变得懒惰时,您可以共享它吗?
@rufoot这样的东西https://codesandbox.io/s/4zjwwq98j4吗?
我正在使用您的实现,但收到一条错误消息,指出forwardedRef不是函数。
我要解决的应用程序中的问题是,我有很多项,当我单击一个项目时,该应用程序将重定向到另一条路线,因此我需要跟踪滚动位置(可能在redux中),并且然后在更改路线后设置滚动位置。
@piecyk您是否尝试过将其与react-window-infinite-loader
的InfiniteLoader结合使用。
我正在使用react-scrollbars-custom
,它似乎正在打破无限加载器:(
我的代码:
<InfiniteLoader isItemLoaded={isItemLoaded} itemCount={items.total} loadMoreItems={loadMoreItems}>
{({
onItemsRendered,
ref,
}: {
onItemsRendered: (props: ListOnItemsRenderedProps) => any;
ref: React.Ref<any>;
}) => (
<List
height={TABLE_HEIGHT}
width={width}
itemCount={items.total}
itemSize={ROW_HEIGHT}
onItemsRendered={onItemsRendered}
itemData={{ items }}
ref={ref}
outerElementType={Scrollbar}
>
{Row}
</List>
)}
</InfiniteLoader>
更新:我不认为它与无限滚动组件有关。 我无法使其与自定义滚动条一起使用。
如果有人可以与我共享react-scrollbars-custom的实现,我将不胜感激
@ranihorev是否需要使用该软件包? 上面共享的代码笔@piecyk使用react-custom-scrollbars并运行良好(创建引用时除外,由于某种原因,该引用在我的代码中为null)
好的,我需要再问一遍。 @piecyk我正在从上面使用代码示例(在这里您回复了@simjes )。 我没有使用固定大小的列表,而是使用自动大小调整器来包装VariableSizeList并指定externalElementType。 像这样的东西:
<TreeRoot
onDragOver={e => this.onDragOver(e)}
>
<AutoSizer>
{({ height, width }) => (
<List
treeRef={this.props.treeRef}
width={width}
height={height}
itemSize={index => rowHeights[index]}
itemCount={nodeTree.length}
itemData={{
nodeTree,
expandedNodes,
nodesFetching,
nodesFetchingFailed,
selectedNode,
selectedNodeId,
resetRowHeight: this.resetRowHeight,
}}
outerElementType={TreeScrollbar}
outerRef={this.props.outerRef}
onScroll={({ scrollOffset, scrollUpdateWasRequested }) => {
if (scrollUpdateWasRequested) {
console.log('scrollOffset: ', scrollOffset);
}
}}
>
{Node}
</List>
)}
</AutoSizer>
</TreeRoot>
我以与您相同的方式实现CustomScrollbars和CustomScrollbarsVirtualList,但是ref始终为null。 我尝试在正在使用AutoSizer的组件以及它的父组件中创建引用,但是它始终为null。 我真的很感谢能帮助理解原因。 如上所述,我需要跟踪滚动位置并能够在应用程序的路线更改中对其进行设置,以便列表不会跳回到顶部。
@ChristopherHButler我已经在代码中多次使用了该程序包,因此我宁愿继续使用相同的程序包。 我的解决方案非常相似,但是它不会ptoperly获取新数据
如果没有该问题的任何代码沙箱示例,
这里的基本思想是从react-custom-scrollbars设置ref,以便react-window
在此示例中,AutoSizer或VariableSizeList将使用此方法
https://codesandbox.io/s/react-window-custom-scrollbars-t4352
@ranihorev您还可以分享代码沙箱示例吗?
@piecyk我创建了一个简单的示例(已损坏):
https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-64kzh?fontsize=14
我还尝试了其他变体(例如,将ref设置为滚动包装器),但没有成功...
谢谢!
无论自定义滚动实现如何, @ ranihorev的方法都是相同的。 他们需要设置对负责滚动并处理该滚动事件的同一元素的引用。
react-scrollbars-custom
使用渲染道具模式提供了更好的api,因此您可以执行类似https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-pjyxs的操作
没有做任何分析,希望对您有帮助👍
@ChristopherHButler我认为您最好的选择是使用上下文传递道具,例如
https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-v2-usi1m
-编辑
如果在路由更改时卸载整个列表,则可以调度操作,最后的scrollOffset可以存储在ref上,并使用VariableSizeList中的onScroll: function
在每次滚动更改时进行更新,那么您无需将道具传递给Scrollbars
@piecyk太棒了,谢谢!
顺便说一句,似乎您所需要的只是onScroll
函数(我错过了),根本不需要转发ref。
https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-99dn1
@piecyk对不起,我应该提到我的VariableSizeList的实现包装在AutoSizer中,而呈现它的组件是基于类的组件,因此我不确定我可以使用上下文。 也许这就是为什么我无法在onScrollStop上正常工作的原因?
快速更新:
我添加了组件状态并将其设置为onScroll。
`
类BaseTree扩展了Component {
...
状态= {scrollPosition:0,};
...
listRef = React.createRef();
externalRef = React.createRef();
...
使成为 {
const {节点,nodesFetching,nodesFetchingFailed,expandedNodes,selectedNode} = this.props;
返回 (
{({高度,宽度})=>( ref = {this.listRef}
className =“列表”
outsideRef = {this.outerRef}
outsideElementType = {TreeScrollbar}
宽度= {宽度}
身高= {身高}
onScroll = {{{scrollOffset})=> this.setState({scrollPosition:scrollOffset})}
itemSize = {index => rowHeights [index]}
itemCount = {nodeTree.length}
itemData = {{
nodeTree,
expandNodes,
nodesFetching,
nodesFetchingFailed,
selectedNode,
selectedNodeId,
resetRowHeight:this.resetRowHeight,
}}
>
{节点}
)}
);
}}
const mapStateToProps =状态=>({
scrollPosition:selectors.getTreeScrollPosition(state),
});
const mapDispatchToProps = dispatch =>({
setTreeScrollPosition:位置=> dispatch(actions.setTreeScrollPosition({位置})),
});
导出默认的connect(mapStateToProps,mapDispatchToProps)(BaseTree);
`
然后在componentWillUnmout上,我分派操作以在redux中设置位置,如下所示:
componentWillUnmount() {
this.props.setTreeScrollPosition(this.state.scrollPosition);
}
我现在唯一的问题是能够在重新安装组件时设置滚动位置。 我试图像这样访问this.listRef上的scrollTop方法:
this.listRef.current.scrollTop()
但出现错误,它不是函数。 我不确定我可以使用哪个属性(this.listRef或this.outerRef)来设置滚动位置或使用哪种方法。 我以为可以在BaseTree的componentDidMount中设置它,如下所示:
componentDidMount() {
const { scrollPosition } = this.props;
if (this.listRef.current) {
// console.log('initializing scroll position to : ', scrollPosition);
this.listRef.current.scrollTop(scrollPosition);
}
}
任何帮助使这项工作将不胜感激!
编辑:非常抱歉,但是我的代码在此编辑器中似乎未正确格式化,因此我为此表示歉意:(
@ranihorev forward ref
可以像scrollTo, scrollToItem
这样的功能来响应窗口
@ChristopherHButler上下文应该与从文档中构建的内容完全一样
上下文提供了一种通过组件树传递数据的方法,而不必在每个级别手动传递道具。
但是,是的,如前所述,如果您在更改路线时卸下整个组件,则无需传递道具。 不会在状态下存储scrollPosition
,因为在滚动发生时您不需要它,减少重新渲染,将其存储在ref上。
onScroll={({ scrollOffset }) => this.setState({ scrollPosition: scrollOffset })}
// to
lastScrollOffsetRef = React.createRef(0);
<List
onScroll={({ scrollOffset }) => {
this.lastScrollOffsetRef.current = scrollOffset
}}
// ...rest
/>
// then in
componentWillUnmount() {
this.props.setTreeScrollPosition(this.lastScrollOffsetRef.current);
}
关于outerRef
,在您的情况下不需要。 listRef.current.scrollTo
是您要使用的正确方法。 嗯,您想在componentDidMount
调用方法的想法是正确的,应该可以,
https://codesandbox.io/s/bvaughnreact-window-fixed-size-list-vertical-80zo7
似乎在设置引用时出现一些计时问题,可能是AutoSizer延迟了List的渲染,从而使this.listRef.current不确定,
hacky选项是,使用setTimeout打破反应生命周期,并在下一个刻度上调用ref
componentDidMount() {
window.setTimeout(() => {
if (this.listRef.current) {
this.listRef.current.scrollTo(this.props.scrollPosition);
}
}, 0);
}
@piecyk非常感谢您的帮助,我真的很感激:)
谢谢@piecyk似乎可行。 更改路线后,安装时会出现一点闪烁,但我可以忍受它:)我还尝试了另一种方法,即使用className传递scrollPosition并在CustomScrollbars的refSetter中设置scrollTop:
if (scrollbarsRef) {
forwardedRef(scrollbarsRef.view);
// HACK
scrollbarsRef.scrollTop(className);
}
看来运作良好。
再次感谢您的所有帮助,不胜感激!! 🙌🏻
不幸的是,此问题中的所有示例均无法正常工作(有时鼠标停止响应滚动)。
但是这个例子做得很完美!
无论自定义滚动实现如何, @ ranihorev的方法都是相同的。 他们需要设置对负责滚动并处理该滚动事件的同一元素的引用。
react-scrollbars-custom
使用渲染道具模式提供了更好的api,因此您可以执行类似https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-pjyxs的操作
我已经尝试过
react-scrollbars-custom
。 它不那么迟钝,但仍然很迟钝。 有人使用自定义滚动条有滞后问题吗?
完成了吗? 最终的解决方案是什么?
如果这对任何人有帮助,我都可以使其与OverlayScrollbars一起
const Overflow = ({ children, onScroll }) => {
const ofRef = useRef(null);
useEffect(() => {
const el = ofRef.current.osInstance().getElements().viewport;
if (onScroll) el.addEventListener('scroll', onScroll);
return () => {
if (onScroll) el.removeEventListener('scroll', onScroll);
};
}, [onScroll]);
return (
<OverlayScrollbarsComponent
options={options}
ref={ofRef}
>
{children}
</OverlayScrollbarsComponent>
);
};
然后,在您的虚拟化组件中:
<FixedSizeGrid
{...props}
outerElementType={Overflow}
>
我将它与FixedSizeGrid
但对于列表它应该起作用。
希望能帮助到你。
最有用的评论
更好的方法是将
Scrollbars
作为outerElementType
示例https://codesandbox.io/s/vmr1l0p463