简体   繁体   English

如何滚动到通过反应虚拟化呈现的反应元素?

[英]How to scroll to React element which is rendered via react-virtualized?

I am using react-virtualized to prevent items in a long list being loaded when out of view port.我正在使用react-virtualized来防止在超出视口时加载长列表中的项目。 However, I have a button at the top of the page that when clicked, scrollsTo an item that is rendered with react-virtualized.但是,我在页面顶部有一个按钮,单击该按钮时,它会滚动到使用 react-virtualized 呈现的项目。

It uses React.createRef() to link the button with the list item but because the rendered item doesn't exist in the dom, the ref is null (It works for the first few items that get rendered but not the rest of the items).它使用React.createRef()将按钮与列表项链接,但由于渲染的项目不存在于 dom 中,ref 为null (它适用于呈现的前几个项目,但不适用于项目的 rest ).

For example, if I click button 20, then I get the error Cannot read properties of null (reading 'getBoundingClientRect') because the ref of the button is null because it's counterpart ref doesn't exist例如,如果我单击按钮 20,则会收到错误Cannot read properties of null (reading 'getBoundingClientRect')因为按钮的引用是 null 因为它的对应引用不存在

Is there a way to scrollTo items that have been rendered within react-virtualized?有没有办法滚动到已在反应虚拟化中呈现的项目?

I have created a code sandbox here to show case what I mean.我在这里创建了一个代码沙箱来展示我的意思。

Otherwise, here is the code snippet:否则,这里是代码片段:

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>
  );
}

Add a reference to your <List> , and use that to scroll to the item's index.添加对您的<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}
    /* ... */
  />
  /* ... */
)

Let's use the List component to render the list in a virtualized way:让我们使用 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>

Notice two things.注意两件事。

First, the List component requires you to specify the width and height of the list.首先,List 组件需要您指定列表的宽度和高度。 It also needs the height of the rows so it can calculate which rows are going to be visible.它还需要行的高度,以便计算哪些行将是可见的。

The rowHeight property takes either a fixed row height or a function that returns the height of a row given its index. rowHeight 属性采用固定行高或 function 返回给定行高的索引。

Second, the component needs the number of rows (the list length) and a function to render each row.其次,组件需要行数(列表长度)和 function 来呈现每一行。 It doesn't take the list directly.它不直接获取列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM