4

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']
  }
];
6
  • 1
    Why are you using this instead of just using the object pointer data? Commented Aug 24, 2017 at 16:51
  • could you try doing: const self = this; then use self inside of _.shuffle instead of this. like: self.reduce. Commented Aug 24, 2017 at 16:52
  • @Pytth because it's in a function definition for data.selectGame = () => {....}. So this should refer to data, right? Commented Aug 24, 2017 at 17:00
  • 1
    @MarkyDD: No; () => gives you the this of its definition. Commented Aug 24, 2017 at 17:04
  • I was not aware of that @SLaks. I changed all references of this to data and it works now. @Pytth or @SLaks, you should create an answer for this and I'll accept it. Thanks for your help! Commented Aug 24, 2017 at 17:07

2 Answers 2

3

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

Change it to data and it should work.

Sign up to request clarification or add additional context in comments.

1 Comment

To expand on this: using data.selectGame = function() {....} makes the use of this valid, while using an arrow function data.selectGame = () => {....} does not. This is because an arrow function does not bind its own this (source)
0

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.