reactjs - React.memo 组件重新渲染而不在预期时检查 isEquals
问题描述
编辑:这是一个工作示例: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;
}
);
它只需要字符串、布尔值和数字作为输入。但是我添加了一个自定义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
),它是每个单元格唯一的稳定字符串。
当horizontalScroll
上面示例中的道具发生变化时,这会改变div
' 的渲染,但不应该影响 ,DataTableCell
因为它没有传入道具,并且密钥没有改变 - 我得到控制台日志Rendering
打印了数百次。我不明白Are props equal?
但是,它可以很好地滚动组件!垂直滚动时,style
会发生变化,它会重新渲染,我看到一大堆Are props equal?
,但只有少数Rendering
日志。我非常有信心正在渲染具有新密钥的密钥,并且正在检查现有密钥是否相等而不是被渲染。
那么为什么它不起作用horizontalScroll
呢?
解决方案
找到了解决方案。这是反应窗口。遵循他们的指南并将itemData
prop 传递到列表中,并避免在RenderRow
阻止它重新创建组件中使用外部值:
https://react-window.now.sh/#/examples/list/memoized-list-items
推荐阅读
- wix - ICE03:无效的语言 ID。不抑制文件信息检索的解决方案
- c# - 根据日期从 Sqlite 数据库中调出数据
- ios - facebook登录错误,react-native ios expo
- c++ - 在构造函数代码之前禁用默认类成员初始化
- r - 在ggplot2中将误差条与每组不同数量的条对齐
- python - 使用条件和排名进行分组的 Python/Pandas 实现
- c# - 如何创建 IOptions
来自 T 的自定义实例(不是通过 DI) - ios - 为自定义视图调用 NSBundle(使用 loadNibName)后访问 IBOutlets 的最佳方法
- amazon-s3 - 我可以使用 AWS S3 + Cloudflare 为我的移动应用程序托管静态 JSON 文件吗?
- css - 如何设置自定义字体以在邮件中显示文本