使用 React-Virtualized AutoSizer 时,未在测试中渲染子级

Posted

技术标签:

【中文标题】使用 React-Virtualized AutoSizer 时,未在测试中渲染子级【英文标题】:When using React-Virtualized AutoSizer, children not being rendered in test 【发布时间】:2020-09-24 15:07:36 【问题描述】:

我有一个使用 react-virtualized AutoSizer 的组件,在这个组件内部有一个 react-virtualized List。它的呈现方式是:

<AutoSizer>
  (width, height) => (
    <List ref=(ref) => (this.refVirtualizedList = ref)
      width=width
      height=height
      playlistLoading=playlistLoading
      playlistPlayingTrackId=playlistPlayingTrackId
      rowCount=rowCount
      deferredMeasurementCache=this.cellMeasurerCache
      overscanRowCount=12
      scrollToIndex=trackGroupToGo - 1
      scrollToAlignment="center"
      rowHeight=this.cellMeasurerCache.rowHeight
      updateTrackListFlag=updateTrackListFlag
      noRowsRenderer=this.renderNoRowsResult
      rowRenderer=this.renderTrackGroupRow
      onRowsRendered=this.handleOnRowsRendered />
  )
</AutoSizer>

它运行良好,但在测试中不起作用。我在列表中看不到任何内容,并且永远不会调用函数 rowRenderer。我正在使用 Jest 和 React 测试库。当使用logDOM 方法检查组件内部的内容时,我看到的是:

<div
  aria-label="grid"
  aria-readonly="true"
  class="ReactVirtualized__Grid ReactVirtualized__List"
  role="grid"
  style="box-sizing: border-box; direction: ltr; height: 0px; position: relative; width: 0px; will-change: transform; overflow-x: hidden; overflow-y: auto;"
  tabindex="0"
/>

List 组件永远不会被渲染。有什么想法吗?

【问题讨论】:

【参考方案1】:

或者,在您的全局设置中,您可以像这样定义 jsDom 属性:

// jsDom does not implement offset* methods.  This will break tests 
// for components that use react-virtualized-auto-sizer 
// (https://github.com/jsdom/jsdom/issues/135#issuecomment-68191941)
Object.defineProperties(window.htmlElement.prototype, 
    offsetLeft: 
        get: function () 
            return parseFloat(window.getComputedStyle(this).marginLeft) || 0;
        
    ,
    offsetTop: 
        get: function () 
            return parseFloat(window.getComputedStyle(this).marginTop) || 0;
        
    ,
    offsetHeight: 
        get: function () 
            return parseFloat(window.getComputedStyle(this).height) || 0;
        
    ,
    offsetWidth: 
        get: function () 
            return parseFloat(window.getComputedStyle(this).width) || 0;
        
    
);

【讨论】:

【参考方案2】:

感谢 GitHub 上的这个问题:https://github.com/bvaughn/react-virtualized/issues/493

我需要做的就是设置测试来“模拟” AutoSizer 的某些行为:

复制您可以在问题中找到的相同解决方案:

describe("My Test", () => 
  const originalOffsetHeight = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight');
  const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth');

  beforeAll(() => 
    Object.defineProperty(HTMLElement.prototype, 'offsetHeight',  configurable: true, value: 50 );
    Object.defineProperty(HTMLElement.prototype, 'offsetWidth',  configurable: true, value: 50 );
  );

  afterAll(() => 
    Object.defineProperty(HTMLElement.prototype, 'offsetHeight', originalOffsetHeight);
    Object.defineProperty(HTMLElement.prototype, 'offsetWidth', originalOffsetWidth);
  );
  // Your tests
)

现在正在渲染 List 组件!

【讨论】:

以上是关于使用 React-Virtualized AutoSizer 时,未在测试中渲染子级的主要内容,如果未能解决你的问题,请参考以下文章

如何滚动到通过 react-virtualized 呈现的 React 元素?

react-virtualized 中的粘性标题

React-virtualized 中对 registerChild 的 CellMeasurer 支持

React-virtualized 动态高度列表呈现最初堆叠的所有内容

React-virtualized - 是不是可以在窗口调整大小时更新 rowHeights?

react-virtualized WindowScroller 性能问题