Sam Aryasa
Sam Aryasa

Reputation: 71

What's the proper way of showing multiple type of rows on a react-native list view?

So what we want is something like:

multiple-row-type

In iOS we could use multiple cellIdentifier for each cell type to create performant listview.

What I have now is something like

render() {
  const dataBlob = [
    { type: "address", data: { address, gotoEditAddress } },

    { type: "deliveryTime", data: {...} },

    { type: "cartSummary", data: {...} },

    ...[items.map(item => {{ type: "item", data: {...} }})],

    { type: "paymentInformation", data: {...} },
    { type: "paymentBreakdown", data: {...} },
    { type: "promoCode", data: {...} },
  ];

  this._dataSource = this._dataSource.cloneWithRows(dataBlob);

  return (
    <ListView ref="ScrollView"
        renderRow={this._renderRow}
        dataSource={this._dataSource} />
  );
)

and on the renderRow method

_renderRow = (rowData) => {
  const { type, data } = rowData;
  if (type === "address") return <AddressRow {...data} />;
  if (type === "deliveryTime") return <DeliveryTimeRow {...data} />;
  if (type === "menuItem") return <MenuItemRow {...data} />;
  if (type === "cartSummary") return <CartSummaryRow {...data} />;

  if (type === "promoCode") return <PromoCodeRow {...data} />;
  if (type === "paymentInformation") return <PaymentRow {...data} />;
  if (type === "paymentBreakdown") return <PaymentBreakdownRow {...data} />;

  return null;
};

The problem with the above code is that it's making the dataSource.rowHasChanged method to be really complicated to implement correctly.

and for some reason when I removed a row, in RN0.31 you will have some ui-defects as such:

ui-defects

Upvotes: 7

Views: 3653

Answers (1)

Mihir
Mihir

Reputation: 3902

I did not fully understand the question. But I'm going to attempt this one.

Instead of rendering multiple types of rows, you can render the same Row component but have different contents inside. It's going to be hard to manage and render different types of rows.

You can pass the type of row you want to render as a prop to a common Row component and have it rendered.

So your second code snippet would look like this -

_renderRow = (rowData) => {
  const { type, data } = rowData;
  switch(type) {
    case 'address':
      return <Row component={AddressRow} data={...data} />;
    case 'deliveryTime':
      return <Row component={DeliveryTime} data={...data} />;
    default:
      return null;
  }
};

Row would simply construct the supplied row and return the component. So on top level you'll have only Rows. Row will contain the particular component you want to render.

render of Row:

render() {
  const Component = this.props.component
  return <Component {...this.props.data} />;
}

Upvotes: 3

Related Questions