反应虚拟化中的组件的异步加载?

问题描述 投票:0回答:1

我在组件中实现了一个反应虚拟化的砌体网格,如下所示:

const MasonrySubmissionRender = (media: InputProps) => {

    function cellRenderer({ index, key, parent, style }: MasonryCellProps) {
        //const size = (media.submissionsWithSizes && media.submissionsWithSizes.length > index) ? media.submissionsWithSizes[index].size : undefined
        //const height = size ? (columnWidth * (size.height / size.width)) : defaultHeight;
        function getCard(index: number, extraProps: any) {
            var Comp = media.cardElement ? media.cardElement : SubmissionCard

            return <Comp submission={media.media[index]} {...media.customCardProps} />
        }


        return (
            <div>
                <CellMeasurer
                    cache={cache}
                    index={index}
                    key={key}
                    parent={parent}>
                    <div style={style}>
                        {getCard(index, media.customCardProps)}
                    </div>
                </CellMeasurer>
            </div>
        );
    }

    return (
        <Masonry
            overscanByPixels={1000}
            autoHeight={false}
            cellCount={media.media.length}
            cellMeasurerCache={cache}
            cellPositioner={cellPositioner}
            cellRenderer={cellRenderer}
            style={{ backgroundColor: 'red' }}
            height={900}
            width={900}
        />
    );
};

它呈现了一个相当复杂的组件列表,其中包含一系列芯片,css动画等。

由于这种渲染即使使用反应虚拟化也非常慢。

我想在imgur.com中实现一个系统,其中组件本身不需要立即加载,只显示一个轮廓,而我可以让组件准备在后台渲染。

我知道有一种方法可以在滚动期间更换组件,但是他隐藏了所有组件,包括已经渲染的组件。

reactjs typescript react-virtualized
1个回答
1
投票

像所有反应虚拟化的单元格/行渲染器一样,masonry's cell render传递了isScrolling属性。当砖石滚动时,您可以渲染占位符而不是单元格内容:

if (isScrolling) return ( 
  <div>placeholder</div>
);

此外,每当无状态组件重新创建时,您将重新创建所有函数。这会导致垃圾收集器的额外开销,并且还可能导致组件不必要地重新渲染。

将组件转换为类组件。 cellRenderer应该是一个实例方法(在构造函数中使用类属性或绑定)。 getCard可以是类方法,或者您可以从组件中提取它,并在调用函数时传递media

你的代码应该是这样的(未经测试):

function getCard(media: InputProps, index: number) {
  var Comp = media.cardElement ? media.cardElement : SubmissionCard

  return <Comp submission = {
      media.media[index]
    } { ...media.customCardProps }
  />
}

class MasonrySubmissionRender extends React.Component {

  cellRenderer = ({
    index,
    key,
    parent,
    style,
    isScrolling
  }: MasonryCellProps) => {
    if (isScrolling) return ( 
      <div>placeholder</div>
    );

    return (
      <div>
          <CellMeasurer
              cache={cache}
              index={index}
              key={key}
              parent={parent}>
              <div style={style}>
                  {getCard(media, index)}
              </div>
          </CellMeasurer>
      </div>
    );
  }

  render() {   
    return (
      <Masonry
        overscanByPixels={1000}
        autoHeight={false}
        cellCount={media.media.length}
        cellMeasurerCache={cache}
        cellPositioner={cellPositioner}
        cellRenderer={this.cellRenderer}
        style={{ backgroundColor: 'red' }}
        height={900}
        width={900}
      />
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.