React & React Native Internals - Understand <ListView />

🍱Framework
javascript
react
react-native
internals

Note: This documentation refers to an old version of ListView. now it is encouraged to use FlatList. This document can however be an in interesting read.


Let’s take a small look at React under the hood

Reconciliation algorithm

Understand React-Native ListView

In react-native/Libraries/CustomComponents/ListView/ListView.js, we find:

  1. renderRow should be passed to ListView as props:

    propTypes: {
        ...ScrollView.propTypes,
        dataSource: PropTypes.instanceOf(ListViewDataSource).isRequired,
        renderRow: PropTypes.func.isRequired,
        ...
  2. renderRow is a function where this is set to null and the values

    ...
    var row =
      <StaticRenderer
        key={'r_' + comboID}
        shouldUpdate={!!shouldUpdateRow}
        render={this.props.renderRow.bind(
          null,
          dataSource.getRowData(sectionIdx, rowIdx),
          sectionID,
          rowID,
          this._onRowHighlighted
        )}
      />;
    ...
    • StaticRenderer expects a React element in its props.render.

From React Native ListView docs:

ListView expects a renderRow callback which takes a blob from the data array and returns a renderable component.

Here bind works to curry the function renderRow.

See this my JS bin example.

So when calling:

<ListView
  dataSource={this.state.dataSource}
  renderRow={(rowData) => <Text>{rowData}</Text>}
/>

here rowData is a mere placeholder for its value is set inside the ListView implementation via bind() with the real data of the row. As we see in the code with bind(), we can also call ListView like this:

<ListView
  dataSource={this.state.dataSource}
  renderRow={(rowData, sId, rId, highlighted) => highlighted ? (<Text>{rowData} number {rId} in {sId}</Text>) : <Text>Not highlighted</Text>}
/>

So we see, the order in which I add the items is important! As a fifth argument to the function I could finally add something new to the row, e.g.

TOOD: Verify this!!!

<ListView
  dataSource={this.state.dataSource}
  renderRow={(rowData, sId, rId, null, someOtherData) => (<Text>{rowData} number {rId} in {sId}, {someOtherData.text}</Text>)}
/>

Here the <ListView /> call in vanilla JS:

"use strict";

React.createElement(ListView, {
  dataSource: undefined.state.dataSource,
  renderRow: function renderRow(rowData) {
    return React.createElement(
      Text,
      null,
      rowData
    );
  }
});

see this in the Babel REPL.

Discuss on TwitterImprove this article: Edit on GitHub

Discussion


Explain Programming

André Kovac builds products, creates software, teaches coding, communicates science and speaks at events.