Lists and Keys

Composi lets you use normal JavaScript to convert an array of items into a list.

The prefered way to create a list is to use map on the array:

const listItems = ['One','Two','Three', 'Four', 'Five']
class List extends Component {
  constructor(props) {
    super(props)
    this.container = 'section'
    this.state = listItems
  }
  render(listItems) {
    // Use map to output indivudal list items:
    return (
      <ul class='list'>
        {
          listItems.map(item => <li>{item}</li>)
        }
      </ul>
    )
  }
}

Rendering List Items Separately

You can create use map on an array to create list items. This will make our code a bit cleaner. In that case it doesn't make sense for our component to have state:

const listItems = ['One','Two','Three', 'Four', 'Five']

// Create list items from listItems:
const items = listItems.map(item => <li>{item}</li>)

class List extends Component {
  constructor(props) {
    super(props)
    this.container = 'section'
  }
  render() {
    // Use items created from array:
    return (
      <ul class='list'>
        {items}
      </ul>
    )
  }
}

The above works. If you don't like create the list items outside the class, you could move it inside the render function but before the return statement.

Keys

When you have a list created by a component, you may need to re-order them. When Composi deals with lists, it uses its virtual dom to see how to path the DOM. The nature of lists makes it very difficult to actually identify what needs to be changed in an efficient manner, resulting in whole scale re-rendering of a list. You can eliminate this problem by using keys on your lists. Keys are just unique values for each item in the list. Note: You should never use the array index as keys. This is because if you change the order of the array items, the index values remain the same. This would make the keys using the array index useless for discerning what changed. Key values need to be unique, but only to the array being parsed. You can reuse keys in other arrays. Keys are never output to the DOM, they are stored in the virtual dom.

You use keys by having a key value exist in the array you are using. And then you output that key value on each list item. You could import a uuid module from NPM, or you could come up with your own function to create a unique id. We'll do that with our list example from above:

See the Pen Composi Tuts - list-keys-1 by Robert Biggs (@rbiggs) on CodePen.

When you give list items a key property, this does not get rendered to the DOM. It only gets create on the virtual dom elements. The diff and patch algorithm can use those key values to determine what changed in the list and update it efficiently.

Bad Practices

As we already mentioned, it is a bad practice to use the array indeces as keys. These are useless when trying to determine a list whose item order has changed. Another bad practice is creating a key value directly on the list item. In our case, we could use our uid function on each list item:

import {uuid} from 'uuid'

// Bad practice - creating key on list item when it is created:
return (
  <ul class='list'>
    {
      listItems.map(item => <li key={uid()}>{item.value}</li>)
    }
  </ul>
)

The problem with the above approach is, each time the render function gets called, new key values get produced. This means the new virtual dom for the list will not match the previous version. This will cause the patch algorithm to completely re-render the list. Very wasteful. It is simply better to have the key values exist on the data.