小编典典

避免使用react-redux重新渲染大量项目

reactjs

我正在为我的应用程序使用带有React和Typescript的redux。我正在处理应用程序不同地方使用的许多项目。我的状态如下所示:

{
    items: {42: {}, 53: {}, ... }, //A large dictionary of items
    itemPage1: {
        itemsId: [ 42, 34, 4 ],
        ...
    },
    itemPage2: { ... 
    },
    ...
}

用户可以修改items调度的某些操作的某些属性。发生这种情况时,我需要重绘每页中已修改的组件。问题是我的物品很大,每次修改时我都无法重绘所有物品。我想知道这种方法是否行得通:

  • 我有一个拳头组件<ItemPage1>,它连接到商店以获取所有存储在树中的状态,itemPage1例如ID:的列表下itemsId
  • 在内部<ItemPage1>,我遍历该itemsId属性以生成多个FilterItem组件:itemsId.map( itemId => return <FilterItem id=itemId>);
  • 最后,每个Item连接都ownProps用于获取状态的正确部分:
        const mapStateToItemProps = (state, ownProps) => {
        return {
            item: state.items[ownProps.id],
        }
    }
    const mapDispatchToItemProps = (dispatch, ownProps) => {
        return null;
    }
    const FilterItem = connect(
        mapStateToItemProps,
        mapDispatchToItemProps
    )(Item)

您能否确认或驳斥,如果我更新ID 42的项目,那么只有该项目将被重新渲染?


阅读 610

收藏
2020-07-22

共1个答案

小编典典

呈现大列表时,您需要考虑以下几点:

  • 减少您需要呈现的DOM元素总数(通过不呈现在屏幕上实际不可见的项,也称为虚拟化)
  • 不要重新渲染未更改的项目

基本上,您要避免的是当用户编辑一行时完全重新呈现列表(或页面)。这可以完全按照您的操作来实现,即:通过仅将需要呈现的项的id传递到列表容器,并connect通过使用将这些ID映射到每个组件ownProps。如果您有转储<Item/>组件,则<ItemPage/>组件将创建连接的connect(<Item/>)组件。

这将起作用,如果您console.log('item rendered')<Item/>组件类中添加了一个,您将注意到只有一个调用。

但是 (但很大),使用时并不明显的react-redux是,如果 状态的任何部分发生变化
,则依赖于它们的所有连接组件ownProps始终重新 呈现
。在您的情况下,即使<Item/>不重新渲染组件,它们的包装组件connect(Item)也会!如果您有几十个项目,那么在需要快速分派操作时(例如,在输入中键入内容时),可能会遇到一些延迟。如何避免呢?使用工厂函数ownProps作为初始道具:

    const mapStateToItemProps = (_, initialProps) => (state) => {
        return {
            item: state.items[initialProps.id],  // we're not relying on the second parameters "ownProps" here, so the wrapper component will not rerender
        }
    }
    const mapDispatchToItemProps = (dispatch, ownProps) => {
        return null;
    }
    const FilterItem = connect(
        mapStateToItemProps,
        mapDispatchToItemProps
    )(Item)

您可能也对这些出色的幻灯片感兴趣:大列表高性能React和Redux

最后,您应该确定要进行反应虚拟化以执行列表的虚拟化(即,仅显示用户实际可以看到的项目)。

2020-07-22