0

Hi I have been trying to pass values to es6 arrow function in my React app, but not successful so far. Here is what I am doing

var data = [];
for (var i=1; i<=5; i++) {
  data.push(<li><a href="#" onClick={(e) => this.getData(e, i)} >{i}</a></li>);
}

and code for getData is

getData (e, page){
 e.preventDefault();
 //here I am calling an api to get data as per page params
}

but actually when the click happens i get nothing. Any help!

h_h
  • 1,201
  • 4
  • 28
  • 47

3 Answers3

2

I have tested this code. It works ok - getData method is invoked when I click a link.

You just need to change var to let to get right value of i param.

var data = [];
for (let i=1; i<=5; i++) {
  data.push(<li><a href="#" onClick={(e) => this.getData(e, i)} >{i}</a></li>);
}
Stanislav Mayorov
  • 4,298
  • 5
  • 21
  • 44
  • Shouldn't change anything, let and var are basically the same. Also I think it's not good to have `var` and `let` mixed – gisderdube May 08 '17 at 08:40
  • @gisderdube var and let have different scopes. – Stanislav Mayorov May 08 '17 at 08:42
  • true, but in this context i don't see where that would make a difference. – gisderdube May 08 '17 at 08:44
  • @Stanislav Mayorov yes it worked with e. but I am not getting the right value of i. now trying to debug, what can be the issue – h_h May 08 '17 at 08:45
  • @gisderdube every click using `var` will get 6 value. – Stanislav Mayorov May 08 '17 at 08:45
  • @gisderdube The different is that cycle will be finished when handler will be invoked. https://jsbin.com/tohalemoma/1/edit?html,js,console,output – Stanislav Mayorov May 08 '17 at 08:57
  • You're right. I didn't expect that. However, isn't this result caused by setting a Timeout? I think adding setTimeout will delay the function call by some ms (because it gets added to the callstack), whereas without it gets executed immediately. Therefore, var is 6 by the time the function gets executed (because it gets overwritten), whereas let has the expected value (because always a new instance). In OPs example, he doesn't set a Timeout, so it shouldn't make a difference, right? – gisderdube May 08 '17 at 09:01
  • setTimeout will not be executed immediately. It will go to callback queue and will be executed after callstack will be empty. – Stanislav Mayorov May 08 '17 at 09:16
  • @gisderdube No, he doesn't set a Timeout, but handler will work the same. – Stanislav Mayorov May 08 '17 at 09:19
  • @StanislavMayorov This is probably off-topic now, but I'm really curious! Check this: http://jsbin.com/hipupadaxo/edit?html,js,output – gisderdube May 08 '17 at 09:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/143671/discussion-between-stanislav-mayorov-and-gisderdube). – Stanislav Mayorov May 08 '17 at 09:41
  • yeah, I am getting 6. Any solution? – h_h May 08 '17 at 10:07
  • @h_a86 Use let like I suggested in my answer. – Stanislav Mayorov May 08 '17 at 10:40
  • @Stanislav Mayorov thanks dear! You solved my problem. `let` worked for me. Really appreciated! – h_h May 08 '17 at 11:54
  • @h_a86 You are welcome. The solution using bind is ok too if you change arguments order in getData function. – Stanislav Mayorov May 08 '17 at 12:29
1

try this:

var data = [];
for (var i=1; i<=5; i++) {
  data.push(<li><a href="#" onClick={this.getData.bind(this, i)}>{i}
    </a></li>);
}

Here is a working example: http://jsbin.com/lokafas/edit?html,js,console,output

By the way, I also recommend using let and const when you use ES6 syntax anyways.

gisderdube
  • 477
  • 1
  • 3
  • 16
  • Hmm... could you please provide the whole class? Are you using React.createClass() or ES6 classes? Try logging the args in getData and provide the result – gisderdube May 08 '17 at 08:37
1

You have to bind this somewhere in order for your code to work. Best way is to do it in the constructor:

export default class SomeCoolName extends React.Component {

   constructor() {
      super();
      this.getData = this.getData.bind(this); // this is important!
   }

   getData(e, page) {
      // code
   }


   // somewhere in the code, in render() maybe
   var data = [];
   for (var i=1; i<=5; i++) {
      data.push(<li><a href="#" onClick={(e) => this.getData(e, i)} >{i}</a></li>);
   }

}
kaytrance
  • 2,657
  • 4
  • 30
  • 49
  • is there a way to pass e here along with param `onClick={this.getData.bind(this, i)}` by this way I am getting correct value of i inside getData function – h_h May 08 '17 at 08:52
  • but unable to pass e – h_h May 08 '17 at 08:52