walker1
walker1

Reputation: 361

Cannot read property of undefined in react native flat list when using react testing library

I'm trying to create a simple snapshot test in react native using react-testing-library, but I can't figure out why I am getting "cannot read property 'lines' of undefined". The flatlist is rendering the data fine with no issues, but the test wont pass.

I've also tried destructuring out the summary.lines, but that didn't work either.

 ● Single Collection Screen Renders

    TypeError: Cannot read property 'lines' of undefined

      47 |         <FlatList
    > 48 |           data={summary.lines}
         |                     ^
      49 |           renderItem={renderCollectionOrderLines}
      50 |           keyExtractor={(_item, i) => i.toString()}
      51 |         />

Mock data.js:

export const useSingleOrdersMock = [
  {
    order_number: 'ABC/1234',
    date: '25/06/20',
    order_status: 'Processing',
    order_total: '£1000.25',
    delivery_address: {
      name: 'John Doe',
      short_name: 'Example Address',
      line_1: 'Example Street',
      line_2: 'United Kingdom',
      line_3: null,
      line_4: null,
      line_5: null,
      postcode: 'ABC 123',
    },
    invoice_address: {
      name: 'Steve Smith',
      short_name: 'Example Address',
      line_1: 'Example Street',
      line_2: 'United Kingdom',
      line_3: null,
      line_4: null,
      line_5: null,
      postcode: 'ABC 123',
    },
    summary: {
      subtotal: '£1100.25',
      delivery: 'Free',
      vat: '£100',
      lines: [
        {
          product_id: 123456,
          part_code: 'ABC1234',
          stock_code: '01234-5678',
          description: 'Combi Oven',
          quantity: 1,
          price_including_vat: '10.20',
          price_excluding_vat: '8.50',
          vat: '1.70',
        },
        {
          product_id: 678910,
          part_code: 'ABC1234',
          stock_code: '01234-5678',
          description: 'Combi Oven',
          quantity: 1,
          price_including_vat: '5.10',
          price_excluding_vat: '4.25',
          vat: '0.85',
        },
      ],
    },
  },
];

export const SingleCollectionScreenAccountContext = {
  selectedCollectionOrder: useSingleOrdersMock,
  setSelectedCollectionOrder: jest.fn(),
};

Test.js:

test('Single Collection Screen Renders', () => {
  let tree;
  act(() => {
    tree = renderer.create(
      <ScreenRenderer
        additionalAccountContext={SingleCollectionScreenAccountContext}>
        <SingleCollectionScreen />
      </ScreenRenderer>,
    );
  });
  expect(tree.toJSON()).toMatchSnapshot();
});

Component.js

import React from 'react';
import { ScrollView, FlatList } from 'react-native';
import Row from '../../components/Account/Row';
import { useAccountContext } from '../../providers/AccountProvider';

const SingleCollectionScreen = () => {
  const { selectedCollectionOrder } = useAccountContext();

  const {
    order_number,
    order_total,
    summary,
  } = selectedCollectionOrder;

  // const { lines } = summary
  
  const renderCollectionOrderLines = ({ item }) => {
    const {
      description,
      part_code,
      price_excluding_vat,
      quantity,
      stock_code,
    } = item;
    return (
      <SummaryLine
        itemName={description}
        catalogue={part_code}
        priceExVat={price_excluding_vat}
        quantity={quantity}
        stockCode={stock_code}
      />
    );
  };

  return (
    <ScrollView>
      <ScreenContainer>
        <FlatList
          data={summary.lines}   <-- error occurring here
          renderItem={renderCollectionOrderLines}
          keyExtractor={(_item, i) => i.toString()}
        />
        <Row title="Subtotal" value={summary.subtotal} />
        <Row title="Delivery" value={summary.delivery} />
        <Row title="VAT" value={summary.vat} />
        <Row title="Total" value={orderTotal} highlight />
      </ScreenContainer>
    </ScrollView>
  );
};

export default SingleCollectionScreen;

Upvotes: 2

Views: 4023

Answers (2)

Rahman Haroon
Rahman Haroon

Reputation: 1145

It's because in the initial rendering summary.lines is getting undefined because of asynchronous call.

To get rid of this issue add a ? it will make a null check before executing

data={summary?.lines} 

Upvotes: 1

Akshay Shenoy
Akshay Shenoy

Reputation: 1248

Looks like the summary data you are getting, is from an asynchronous call, thus at the initial point, its undefined.

In such scenario adding a null check helps in resolving such issues. Instead of summary.lines, try summary?.lines.

Upvotes: 3

Related Questions