Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 790
Sam Aryasa Avatar asked Sep 15 '16 09:09

Sam Aryasa


1 Answers

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} />;
}
like image 122
Mihir Avatar answered Oct 02 '22 17:10

Mihir