MarkyDD
MarkyDD

Reputation: 272

Using Lodash with create-react-app results in "Uncaught TypeError: _this.reduce is not a function"

I'm new to React and create-react-app and I'm attempting to use Lodash in my App.js file and I'm running into an error. Uncaught TypeError: _this.reduce is not a function. I've added

import _ from 'lodash';
import shuffle from 'lodash/shuffle';
import random from 'lodash/random';
import find from 'lodash/find';

to the top of my App.js and

import Lodash from 'lodash';

in my index.js file.

For testing I've used this reduce example from MDN, which works:

  var total = [0, 1, 2, 3].reduce(function(sum, value) {
    return sum + value;
  }, 0);

But the line that uses lodash throws the error above:

  var books = _.shuffle(this.reduce((p, c, i) => {
    return p.concat(c.books);
  }, [])).slice(0, 4);

In this case this is an array like this:

var data = [
  {
    name: 'Mark Twain',
    imageUrl: 'images/authors/marktwain.jpg',
    books: ['The Adventures of Huckleberry Finn']
  }
];

Upvotes: 4

Views: 2951

Answers (2)

Joseph Ditton
Joseph Ditton

Reputation: 1028

Looking at your code its very unlikely that the keyword this actually refers to the array. Near impossible I would say. You could maybe write a whole book on how the this keyword behaves in Javascript. The _this value is a how babel handles the different behaviors of this. Consider this example:

console.log(this)

function someFunction(){
  console.log(this);
  const someSubFunction =  function() {
    console.log(this)
  }
  someSubFunction();

  const someOtherFunction =  () => {
    console.log(this)
  }

  someOtherFunction();
}

someFunction();

This code is transpiled by babel to:

"use strict";

console.log(undefined);

function someFunction() {
  var _this = this;

  console.log(this);
  var someSubFunction = function someSubFunction() {
    console.log(this);
  };
  someSubFunction();

  var someOtherFunction = function someOtherFunction() {
    console.log(_this);
  };

  someOtherFunction();
}

someFunction();

Notice how the this value is reassigned to a variable called _this.

In this example, all of the log statements print out undefined. If you use the keyword this at the root scope then it will (almost) certainly be undefined. In fact if you look at line 3 of the transpiled example, babel literally just replaces this with undefined. Inside a function on the global scope, this is also undefined.

Inside a class this refers to the instance of the class if you are directly inside a method defined by the class, or in the constructor.

Anyway long story short, you need figure out what this is actually referring to. Most likely you just need to assign your array to a variable and do:

var books = _.shuffle(data.reduce((p, c, i) => {
  return p.concat(c.books);
}, [])).slice(0, 4);

If you are going to do lodash though, you could also be consistent and just use lodash like this:

var books = _.chain(data)
   .reduce((p,c,i) => _.concat(c.books), [])
   .shuffle()
   .slice(0,4)
   .value();

Slightly easier to read in my experience.

Upvotes: 0

Pytth
Pytth

Reputation: 4176

As per the comments section, your this reference is not pointing to what you expect.

Change it to data and it should work.

Upvotes: 3

Related Questions