The best way of rendering a collection of items in React/Redux


In short

The best way to render a collection in React, backed by Redux or other similar library: store a collection as an object where key is item id and value is item itself. That way when rendering collection, pass only item’s id to the item component. Than in item’s connected component query a collection by item’s id you passed early. So something like this.

//Item.js
import React from 'react'
import {connect} from 'react-redux'

const Item = ({item}) => {
    // use item to render markup
}

const mapStateToProps = state, {id} => ({
    item: state.collection.data[id]
})

export default connect(mapStateToProps)(Item)
// Collection.js
import React from 'react'
import {connect} from 'react-redux'
import Item from './Item'

const Collection = ({ids}) => (
    <div>{ids.map(id => <Item key={id} id={id} />)}</div>
)

const mapStateToProps = state => ({
    ids: state.collection.ids // actual collection is obtained with state.collection.data 
})

export default connect(mapStateToProps)(Collection)

Storing collection as an object also improves performance of querying and deleting an item from it.

Longer explanation

When I began developing in React a few years ago I was rendering a collection of items this way:

items.map(item => <Item {...item} key={item.id} />)

Then Flux/Redux came in my way and I realized storing items in state as a list of items is inefficient as noted. That’s because querying a list is O(n) operation but querying an object only O(1).

Given that performance boost I was still rendering a collection as before only now I had to turn an object into a ordered list because .map() only works on lists. Imagine doing that after every render! Using reselect can improve this by only converting it to list when collection changes. But we can still do better than that.

Satisfying solution came after reading a blog posts about making React and Redux more performant together. The point I think was “don’t be afraid of using connect often and breaking reducer into smaller reducers”.

You can build object of (id, item) pairs yourself or use library like normalizr which normalizes input data according to provided schema and returns entities and result (ids).

The reason why I prefer this method over previous is also because I love to use functional programming in react/redux. I think those two are brilliant couple. But to make functional programming easier, I use utility libraries. The two most known are lodash/fp and ramda. Lodash/fp might be superior to ramda when it comes to amount of functions included but I love ramda more because of the documentation. It’s easier to find what you are looking for (in lodash/fp I need to look at two places).

I was indecisive though which one to pick and stick with before discovering this new way of rendering collection because ramda doesn’t support iteration over an object.