避免使用react redux重新呈现大量项目



我的应用程序使用带有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>);
  • 最后,使用ownProps连接每个Item以获得状态的正确部分:

    const mapStateToItemProps = (state, ownProps) => {
        return {
            item: state.items[ownProps.id],
        }
    }
    const mapDispatchToItemProps = (dispatch, ownProps) => {
        return null;
    }
    const FilterItem = connect(
        mapStateToItemProps,
        mapDispatchToItemProps
    )(Item)
    

你能证实或反驳如果我更新id 42的项目,那么只有这个项目会被重新渲染吗?

在渲染大列表时,需要考虑以下几点:

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

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

这是可行的,如果在<Item/>组件类中放入console.log('item rendered'),您会注意到只有一个调用。

但是(这是一个很大的但是),当使用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)

我建议你看看另一个答案。

您可能还对这些优秀的幻灯片感兴趣:Big List High Performance React&Redux

最后,您应该明确地考虑虚拟化反应,以执行列表的虚拟化(即,只显示用户实际可以看到的项目)。

好的,我发现了这个讨论:https://github.com/reactjs/redux/issues/1303

在底部,它清楚地表明(来自多个主角):

[…]react redux解决了这个问题。它允许您指定您关心的状态的特定部分,并在相关部分没有更改时小心地退出更新React组件

[…]我只是想完全理解这里到底发生了什么,所以如果Redux商店更新了,但一个特定的组件状态没有改变,那么Redux不会触发该组件的forceUpdate()方法吗?[…]

React Redux的connect()函数生成的包装器组件会进行多次检查,以尽量减少实际组件必须重新渲染的次数。这包括shouldComponentUpdate的默认实现,以及对进入组件的道具(包括从mapStateToProps返回的道具)进行浅层相等性检查。所以,是的,通常情况下,连接的组件只有在从状态中提取的值发生变化时才会重新渲染

所以我相信我的实现是好的,它不会重新呈现所有项,因为只有一个项的属性会被修改。

相关内容

  • 没有找到相关文章

最新更新