14

How do I set a default value to a variable if array.find returns 'undefined'.

Here's the line that's causing me issues. In some instances this variable will populate but in others, it won't and in that case, I want it to default to 0.

this.statistics.creditAmount = response.data.find(t => t.paymentType == 'RF' && t.status == 1).amount || 0;
Dally
  • 1,281
  • 4
  • 18
  • 37
  • 3
    You could do this: `(response.data.find(t => t.paymentType == 'RF' && t.status == 1) || { amount : 0 }).amount`. But an if-else or a ternary operator check is much more readable IMO – adiga Mar 26 '19 at 19:44
  • 1
    No point in creating a snippet that can't run. –  Mar 26 '19 at 19:44
  • That worked like a charm @adiga although it's not very readable. What are the double pipes doing exactly? – Dally Mar 26 '19 at 19:51
  • 1
    `(data.find(t => t.paymentType == 'RF' && t.status == 1) || { amount : 0 })` block first checks if there is value in the found object. If it is `undefined`, the OR operator will use the second object `{ amount : 0 }`. Then get the `amount` property from the object returned. – adiga Mar 26 '19 at 19:58

4 Answers4

10

I see this has been answered but I thought this could contribute

const { amount = 0 } = response.data.find(t => t.paymentType === 'RF' && t.status === 1) || {};
this.statistics.creditAmount = amount;

Or you could use a reducer:

  this.statistics.creditAmount = response.data.reduce((amt, t) => t.paymentType === 'RF' && t.status === 1 ? t.amount : amt, 0);

The reducer would use more clock cycles as it traverses the entire array, whereas Array.prototype.find stops once it reaches the first match. This may cause the results to vary as well, since the way that reducer is written it will take the last item from the array that matches.

noahtkeller
  • 165
  • 2
  • 8
6

The problem with your code is that you're accessing .amount of undefined for cases where array.find returns undefined. You can solve it by adding a guard:

const credit = response.data.find(t => 
  t.paymentType == 'RF' && t.status == 1);

this.statistics.creditAmount = credit ? credit.amount : 0;

Dehli
  • 5,950
  • 5
  • 29
  • 44
1

Another approach is to use a closure and a destructuring with a default object/value.

const
    getAmount = ({ amount = 0 } = {}) => amount,
    credit = getAmount(response.data.find(t => t.paymentType == 'RF' && t.status == 1));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

Possible overkill, but you could create and implement a reusable null propagation method.

const response = {data: []};

const _try = (func, fallbackValue) => {
    try {
        var value = func();
        return (value === null || value === undefined) ? fallbackValue : value;
    } catch (e) {
        return fallbackValue;
    }
}


const result = _try(() => response.data.find(t => t.paymentType == 'RF' && t.status == 1).amount, 0);
console.log(result);

This was originally written by tocqueville as part of this answer.

Tyler Roper
  • 21,445
  • 6
  • 33
  • 56