Zeusox
Zeusox

Reputation: 8448

React: Cannot read property 'times' of undefined Although "times" is defined?

There is a strange behavior going on with my application. I have the following DatePicker as follows:

  <DatePicker
  inline
  minDate={moment().add(1, "day").utc().toDate()}
  maxDate={moment().add(7, "day").utc().toDate()}
  selected={selectedDate ? selectedDate : moment().utc().toDate()}
  onChange={this.onDateSelect}/>

If I leave the code as such, the application runs fine, but if I change the minDate from 1 to -say- 25 and then maxDate from 7 to 35, then I get the above error on this line of code:

The following is in the reducer with an initialState defined as:

const initialState = {
    days: [],
    times:[],
    schedule: {},
    rescheduled: false
};

  > let times = dayList.find(day => Boolean(day.selected) === true).times.filter(time => Boolean(time.available) === true);

I am just not sure why times becomes undefined if it is clearly defined in here?

Any feedback or help would be much appreciated.

Upvotes: 0

Views: 216

Answers (4)

Aprillion
Aprillion

Reputation: 22304

You may be confusing ReferenceError that happens in strict mode when you forget to declare a variable, e.g. console.log(iDontExist).

However, the Property accessor (dot operator in obj.property) returns value undefined when the property of an object does not exist, e.g.

const obj = {property: 1}
console.log(obj.iDontExist) // undefined

The problem is, undefined itself does not behave the same, it throws an error when you try to access undefined.property, e.g.:

const obj = {property: 1}
console.log(obj.iDontExist.whatever) // ???

The error is different in different JS implementations though, e.g. in Firefox:

TypeError: obj.iDontExist is undefined

In Chrome and Node.js:

Uncaught TypeError: Cannot read property 'whatever' of undefined

In Edge:

Unable to get property 'whatever' of undefined or null reference

Upvotes: 1

Always Learning
Always Learning

Reputation: 5581

The error is not saying that times is undefined. It's saying that it can't read the times property of an undefined object. If you had a variable called entry and then you say entry.times that will work only if entry is defined as an object. But you'll get this error if you do this:

let entry;
entry.times = [];  // <-- fails because entry is undefined

Looking at your code, you have this:

dayList.find(day => Boolean(day.selected) === true).times.filter(time => Boolean(time.available) === true);

So I'm guessing that the part before .times is evaluating as undefined. By this I mean

dayList.find(day => Boolean(day.selected) === true)  ===  undefined

You didn't give enough information to know what kind of objects are in the dayList array, but if dayList.find() could not find anything, it will return undefined and then your attempt to access undefined.times will cause the error you see.

I recommend splitting this line up into separate parts so you can only try to access data that you know is present. For example:

const item = dayList.find(day => Boolean(day.selected) === true);
if (item) {
  const times = item.times;
  // do something with the times array...
}
else // report that no day could be found, or whatever is appropriate

Upvotes: 1

kind user
kind user

Reputation: 41893

If Array#find function does not "find" anything - it returns undefined.

Apparently that's why you are getting the error:

dayList.find(day => Boolean(day.selected) === true).times
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> undefined

I would suggest to you make sure that times is not undefined:

const getTimes = (dayList) => {
   const time = dayList.find(day => Boolean(day.selected) === true);

   if (time && Array.isArray(time.times)) {
      return time.times.filter(n => Boolean(n.available) === true);
   }
};

Note: You should also check if time.times is an array, to properly use Array#filter on that.

Upvotes: 2

  > let x = dayList.find(day => Boolean(day.selected) === true).times.filter(time => Boolean(time.available) === true);

Here you chain properties left and right. It would be much easier to answer if you said which property is giving you trouble instead of saying 'X'.

Probably the .find() method is not finding anything at some point and when you access .times it says the result of .find() is undefined, or maybe .times.filter().

Every time you use .find() you should store the result in a variable and check that it has a value before trying to do anything with it.

Upvotes: 0

Related Questions