0

While looping over an object using map() React can't find its own classes property!

Here is the class of the component,

import React, { Component } from 'react';
import './videolists.css';

export default class VideoLists extends Component {

  constructor() {
    super();
  }

  getDefaultLists() {
    return [
      {
        title: 'Iridescent (Official Video) - Linkin Park',
        url: 'https://www.youtube.com/watch?v=xLYiIBCN9ec',
        id: 'xLYiIBCN9ec' 
      },
      {
        title: 'Ed Sheeran - I\'m A Mess (x Acoustic Sessions)',
        url: 'https://www.youtube.com/watch?v=-t2CR9qZRj0',
        id: '-t2CR9qZRj0' 
      },
      {
        title: 'Ed Sheeran - Lego House [Official Video]',
        url: 'https://www.youtube.com/watch?v=c4BLVznuWnU',
        id: 'c4BLVznuWnU' 
      }
    ]
  }

  itemSelected(itemObject) {
    console.log(itemObject);
  }

  render() {
    return (
      <div>
        <div className='panel panel-default'>
          <div className='panel-heading'>

            <ul className='list-group'>
              {this.getDefaultLists().map(function(item, index){
                return <li 
                          key = { index } 
                          className='list-group-item'
                          onClick={ this.itemSelected.bind(this) }>
                          { item.title } <br/>
                          <small className='listurl'>{ item.url }</small>
                      </li>; 
              })}
            </ul>

          </div>
        </div>
      </div>
    );
  }

}

When a user would click on an item it should call the function called itemSelected and also binding the current this element with this.

But when the application is throughing and error.

Here is the error message:

Uncaught TypeError: Cannot read property 'itemSelected' of undefined(…)

How I can call this function in this case from the loop?

5
  • 1
    set this for .map callback - this.getDefaultLists().map(function(item,index){ ... }, this) Commented Nov 17, 2016 at 8:37
  • or just use a fat arrow Commented Nov 17, 2016 at 8:40
  • Thanks @AlexanderT. But its not sending the data object. Commented Nov 17, 2016 at 8:41
  • Possible duplicate to [this question][1] [1]: stackoverflow.com/a/40639996/2902660 Commented Nov 17, 2016 at 8:57
  • Possible duplicate of Accessing a method inside a ReactJS component Commented Nov 17, 2016 at 9:31

1 Answer 1

2

you are losing the this context because of your map function. not only do you need to bind that, to get the data object sent though you need to actually tell it to do that. like this.

<ul className='list-group'>
    {this.getDefaultLists().map( (item, index) => {
        return (
            <li key ={index} className='list-group-item' onClick={() => this.itemSelected(item)}>
                { item.title }
                <br/>
                <small className='listurl'>{ item.url }</small>
            </li>
         ); 
    })}
</ul>

you can try shadowing your this context, shouldn't be necessary, but worth a shot.

const self = this;
...
<ul className='list-group'>
    {self.getDefaultLists().map( (item, index) => {
        return (
            <li key ={index} className='list-group-item' onClick={() => self.itemSelected(item)}>
                { item.title }
                <br/>
                <small className='listurl'>{ item.url }</small>
            </li>
         ); 
    })}
</ul>
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, but when i click same error occurs: VideoLists.js:100 Uncaught TypeError: Cannot read property 'itemSelected' of undefined(…)
how're you building this? fat arrow functions bind your this context. so you shouldn't need to shadow your this

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.