【问题标题】:React.memo component re-rendering without checking isEquals when expectedReact.memo 组件重新渲染而不在预期时检查 isEquals
【发布时间】:2019-12-06 08:55:31
【问题描述】:

编辑:这是一个工作示例:https://codesandbox.io/s/gracious-silence-5n4pv 为什么按下按钮会重新渲染所有单元格,但滚动不?

我正在尝试提高性能,因此我将一个组件提取到具有更简单的道具的东西中 React.memo 友好:


interface DataTableCellProps {
  header: string;
  value: string;
  isRepeatedValue: boolean;
  width: number;
}

const DataCell = styled.div<{ width: number; isRepeatedValue: boolean }>`
  padding-left: 0.5rem;
  padding-right: 0.5rem;
  width: ${props => props.width}px;
  color: ${props => (props.isRepeatedValue ? grey : lightGrey)};
  display: flex;
`;

/** Data table cells. A pure component that can be memoised easily (all props are simple types) */
const DataTableCell = React.memo(
  (props: DataTableCellProps) => {
    console.log("Rendering");
    return (
      <DataCell
        role="cell"
        area-header={props.header}
        width={props.width}
        isRepeatedValue={props.isRepeatedValue}
      >
        <Tooltip title={props.value} placement="bottom-start" enterDelay={500}>
          <span className="text-truncate">{props.value}</span>
        </Tooltip>
      </DataCell>
    );
  },
  (a, b) => {
    console.log("Are props equal?");
    return true;
  }
);

它只接受字符串、布尔值和数字作为输入。但是我已经添加了一个 cusom isEqual 支票来记录,现在强迫它总是说它是平等的。根据我的理解,它应该始终返回缓存的组件,并且永远不会重新渲染,除非它们改变了键。

这里是它被渲染的地方,去掉了所有不起作用的东西:

const DataTableBody = (props: DataTableBodyProps) => (<FixedSizeList
          width={300}
          height={300}
          itemCount={props.rows.length}
          itemSize={35}
          outerRef={props.containerRef}
          outerElementType={CustomScrollbarsVirtualList}
        >
          {({ index, style }) => {
            const row = props.rows[index];
            props.prepareRow(row);
            return (
              <div
                style={{
                  ...style,
                  transform: `translate(${props.horizontalScroll}px, 0)`,
                  display: "flex"
                }}
              >
                {row.cells.map((cell: any) => (
                  <DataTableCell
                    key={cell.getCellProps().key}
                    value={cell.value}
                    header={cell.column.Header}
                    width={
                      props.widths[cell.column.Header] ||
                      props.defaultColumnWidth
                    }
                    isRepeatedValue={cell.isRepeatedValue}
                  />
                ))}
              </div>
            );
          }}
        </FixedSizeList>);

我记录了密钥(来自react-tables),它是每个单元格唯一的稳定字符串。

当上面示例中的 prop horizontalScroll 发生变化时,这将改变 div 的渲染,但不应该影响 DataTableCell,因为它没有传入 props,并且 key 没有改变 -我将控制台日志Rendering 打印了数百次。我没有收到Are props equal?

但是,它可以很好地滚动组件!垂直滚动时,style 会发生变化,它会重新渲染,我看到一大堆Are props equal?,但只有少数Rendering 日志。我非常有信心正在渲染具有新密钥的密钥,并且正在检查现有密钥是否相等而不是被渲染。

那么为什么它不适用于horizontalScroll

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    找到了解决办法。这是反应窗口。遵循他们的指南并将 itemData 属性传递到列表中,并避免在 RenderRow 中使用外部值阻止它重新创建组件:

    https://react-window.now.sh/#/examples/list/memoized-list-items

    【讨论】:

      猜你喜欢
      • 2021-06-17
      • 2023-02-26
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 2018-08-12
      • 2021-10-23
      • 2023-01-28
      相关资源
      最近更新 更多