Why "TypeError: Cannot read property 'airline' of undefined" when it is defined?

Viewed 358

I'm trying to access the nested objects of my data array. It was working and all of a sudden, it started returning a "TypeError: Cannot read property 'airline' of undefined". I checked, I can't seem to find anything I touched anywhere.

I have this data, when I tried to access console.log(tempflights[0]), the data is returned, but when I do console.log(tempFlights[0].airline), or any other object property in the array, it returns a type error.

I'm also trying to compare the stored data with a received data to see if there's a match.

Can anyone help me figure out where I'm getting it wrong. Note: I'm very new to React and Js.

import logo1 from "./images/delta.png";
import img1 from "./images/w1.jpg";


export default [
  {
    sys: {
      id: "1"
    },
    fields: {
      from: {
        destination: "London",
        slug: "LHR",
      },
      to: {
        destination: "New York",
        slug: "LGA",
      },
      airline: {
        name: "Delta",
        airlineId: "DL 214",
        logo:
        {
          fields: {
            file: {
              url: logo1
            }
          }
        }

      },
      tripClass: "economy",
      direct: true,
      stopOver: {
        destination: "",
        slug: ""
      },
      minPrice: 900,
      departureDate: "2020-06-05",
      roundTrip: true,
      returnDate: "2020-07-05",
      luggageLimit: 50,
      totalDuration: "6h 30m",
      featured: true,
      images: [
        {
          fields: {
            file: {
              url: img1
            }
          }
        }
      ]
    }
  },
]


import React, { Component, createContext } from 'react'
import items from './data'



const DestinationContext = createContext();
// create context Provider

class DestinationProvider extends Component {
    //set up state
    state = {
        destinations: [],
        sortedDestinations: [],
        featuredDestinations: [],
        loading: true,
    }
 
    componentDidMount() {
        let destinations = this.formatData(items)
        let featuredDestinations = destinations.filter(destination =>
            destination.featured === true);

        this.setState({
            destinations,
            featuredDestinations,
            sortedDestinations: destinations,
            loading: false
        })
    }

    formatData(items) {
        let tempItems = items.map(item => {
            let id = item.sys.id
            let images = item.fields.images.map(image => image.fields.file.url);

            let destination = { ...item.fields, images, id }
            return destination;
        })
        return tempItems;
    }

    getFlights = (to, from, departureDate) => {
        let tempFlights = [...this.state.destinations];
        console.log(tempFlights[0].airline);

        const flight = tempFlights.filter(flight =>

            flight.to.destination.toLowerCase() === to.toLowerCase() &&
            flight.from.destination.toLowerCase() === from.toLowerCase() &&
            flight.departureDate >= departureDate
        );
        return flight;
    }
    render() {
        return (
            <DestinationContext.Provider value={{
                ...this.state,
                getFlights: this.getFlights
            }}>
                {this.props.children}
            </DestinationContext.Provider>
        );
    }
}
const DestinationConsumer = DestinationContext.Consumer;

export { DestinationProvider, DestinationConsumer, DestinationContext };

Error:

TypeError: Cannot read property 'airline' of undefined DestinationProvider.getFlights src/context.js:52 > 52 | console.log(tempFlights[0].airline); | ^ 53 | 54 | const flights = tempFlights.filter(flight => 55 | View compiled Flights.render src/pages/Flights.js:24 21 | const { getFlights } = this.context 22 | const slug = Object.fromEntries(new URLSearchParams(this.state.slug)) 23 | const { to, from, departureDate } = slug > 24 | const flights = getFlights(to, from, departureDate)

2 Answers

As it is i still don't know why I can't access those objects from within the function, but I finally figured out why my filter function suddenly started returning an empty array.

I'm trying to compare these three values in the filter function,

 const flights = tempFlights.filter(flight =>
            flight.from.destination.toLowerCase() === from.toLowerCase() &&
            flight.to.destination.toLowerCase() === to.toLowerCase() &&
            flight.departureDate >= departureDate
        );

but the last comparison was wrong. I was supposed to compare flight.departureDate <= departureDate.toString() Not flight.departureDate >= departureDate

You are getting tempFlights[0] is undefined because it is undefined (this.state.destinations is [] - initial state) at the moment you are trying to acsess (or log) it.

But note that it would be defined after a while i.e. when componentDidMount has executed and setState has been called.

  getFlights = (to, from, departureDate) => {
    let tempFlights = [...this.state.destinations]
    console.log(tempFlights[0].airline) // Error: tempFlights[0] is undefined

    const flight = tempFlights.filter(
      (flight) =>
        flight.to.destination.toLowerCase() === to.toLowerCase() &&
        flight.from.destination.toLowerCase() === from.toLowerCase() &&
        flight.departureDate >= departureDate
    )
    return flight
  }

If you initialize your state inside constructor like this, you should not see Error: tempFlights[0] is undefined inside getFlights. But I don't think you can do that as items would not really be a fixed / hardcoded value as you provide in this example. But I think your state will be set at componentDidMount and the changes would propagate correctly, so there should be no further error if you just remove console log in getFlight because at that moment it is really trying to read from undefined.

  constructor(props) {
    super(props)
    let destinations = this.formatData(items)
    let featuredDestinations = destinations.filter(
      (destination) => destination.featured === true
    )
    this.state = {
      destinations,
      featuredDestinations,
      sortedDestinations: destinations,
    }
  }
Related