2016-08-01 60 views
6

我正在为我的应用程序使用redux和react和typingcript。我正在使用在我的应用程序的不同位置使用的很多项目。我的状态是这样的:避免使用react-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的项目,那么只有这个项目将被重新渲染?

+1

也许它很适合你http://stackoverflow.com/questions/38493521/whats-the-best-way-to-deal-with-a-normalized-response/38499471#38499471 –

+0

你的评论现在有相关性,但问题是关于所有元素都被重新渲染或不是。 – user3091275

回答

6

当渲染大名单,你需要考虑考虑几件事情:

  • 低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) 

我建议你去看一下this other answer

您可能也有兴趣在这些优秀的幻灯片:Big List High Performance React & Redux

最后,你应该明确地看一看,以react-virtualized执行列表的虚拟化(即只显示用户可以实际看到的项目)。

0

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

在底部则明确指出(从多个主角):

[...]反应,终极版注意到了这一问题。它允许您指定您关心的状态的特定部分,并且在相关部分没有更改时注意更新React组件。

[...]只是想充分了解这是怎么回事引擎盖下,所以如果Redux的商店被更新,但一个特定组件的状态没有改变,终极版将不会触发forceUpdate( )该组件的方法? [...]

由作出反应,终极版的connect()函数生成做了几项检查,以尽量减少你的实际组件必须重新渲染的次数包装组件。这包括shouldComponentUpdate的默认实现,并对进入组件的道具(包括mapStateToProps返回的内容)进行浅层次的等式检查。所以是的,作为一般规则,连接组件只有在它从状态中提取的值发生改变时才会重新呈现。

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

+1

你几乎100%正确,使用'ownProps'只有一个问题,它会让你所有的包装组件每次都重新渲染。看看我的答案! – Pcriulan