REACT: Bind function to run only on click [duplicate] - javascript

This question already has answers here:
onClick handler is triggered on each render cycle
(4 answers)
Closed 4 years ago.
Could someone please explain to me why when i am trying to bind onClick action to element it works good until i dont add brackets to pass arguments to function?
getUser(id) {
console.log(id);
}
renderResults(){
if (typeof this.props.results[0] == 'undefined') {
return null;
} else {
var results = this.props.results[0].payload;
var formatedResults = results.map((singleResult) => {
return (
<div className="col-md-4 single-result" key={singleResult.account_id} onClick={this.getUser(singleResult.id)}>
<div>{singleResult.nickname}</div>
</div>
)
});
return formatedResults;
}
}
that code works on load instead of on click and returns x console logs just when page is loaded not when i click element, but when i remove brackets and i am console logging static text in getUser function it works good.
Any help or helpful links? Thanks

onClick={(e) => this.getUser(singleResult.id)}
doc : https://reactjs.org/docs/handling-events.html#passing-arguments-to-event-handlers

We have different ways to bind events to your DOM elements in react.
One of the most commonly used way is using 'bind'
Another is using arrow functions.
Using public class fields syntax
In your scenario, you are calling your function directly by doing this.getUser(singleResult.id). This executes the method rather than binding it to your DOM element.
Try changing it to this.getUser.bind(this, singleResult.id) which should be passing your singleResult.id to your method.
Another way to do it is using arrow functions like onClick={(e) => this.getUser(singleResult.id)}
But be careful while using arrow functions because there are chances of unnecessary rendering of components in some scenarios.
Please make sure to take a look at the documentation to give more details on events handing in react

use constructor to bind the function. use inside your component. and all your codes as it is
constructor(props) {
this.getUser = this.getUser.bind(this);
}

It's because you're calling the function, instead of passing it to onclick.
You can bind the value to the function, with an arrow function, if you're not passing anything, then it will keep its state:
getUser = () => {
console.log(this);
}
onClick={this.getUser}
or in your case pass the function to the onclick:
onClick={(e) => this.getUser(singleResult.id)}
You can read all about it here

Related

I'm confused with Event Handler Callback function as a class method? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 2 years ago.
I know this may seems silly but I'm a beginner and I just need to make sure that I understand it well:
In JavaScript when I define an event listener, the callback function is called without () to prevent immediate execution, like the below example:
document.querySelector('#button').addEventListener('click',eventHandler)
function eventHandler() {
alert('clicked')}
my confusion is if implemented the above in a class and defined the eventHandler callback function as a method, I have to use () when I call it, like the below example:
class home {
constructor(){
this.button = document.querySelector('#button')
this.clickEvent()
}
//events
clickEvent(){
//here i have to use eventHandler() not eventHandler
this.button.addEventListener('click',()=>this.eventHandler())
}
//method
eventHandler(){
alert('clicked')
}
}
new home()
In code snippet with class, you are passing a function to addEventListener function which then calls the eventHandler function.
() => this.eventHandler() is an arrow function which executes this.eventHandler() inside its body
if you remove the arrow function then you will have to pass the name of the function instead of calling it
this.button.addEventListener('click', this.eventHandler)
Edit:
keep in mind that if the eventHandler method uses this, then you may run into problems because of how value of this is set in different cases.
Currently, eventHandler function isn't using this but you should read how to access correct this inside callbacks.

How to pass event and other arguments inside an arrow function in ReactJs

I am a beginner in React and was held up with an issue:
This was my code inside the render function
let contnt = null;
if(this.state.showPersons)
{
contnt = (
<div >
{this.state.persons.map((ppl,index)=>{
return <Person name={ppl.name}
age={ppl.age}
changed={this.nameChange} // THE FOCUS POINT
click={()=>this.deletePerson(index)}
key={index}></Person>
}) }
</div>
)
}
The code above works fine the function nameChange reads event as well, without explicitly sending it as argument.
But I wanted to send index to my nameChange function as well, but if I define changed as :
changed={()=>this.nameChange(event, index)}
It gives error saying event not found...
How do I send event along with arguments to an arrow function definition inside render function?
I know this might seem to be a very basic question, but beginners who tend to start off haphazardly often face simple basic issues like this.
I was following a tutorial there after and found it, so thought it was worth sharing..
And event can be sent in the first parenthesis of the arrow function like this:
changed={(event)=>this.nameChange(event, index)}
and then event as well as index can be read in the nameChange function.

How to call a class method from inside same class method? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 3 years ago.
I've created a class and I'm trying to call a method from inside that class from another method inside that same class. I've seen online that some people say use 'this' keyword, but as you can see from the example, that doesn't work. Can someone please explain in simple terms how to call a class method from inside another method in that same class? Thanks!
class Form {
constructor() {
}
fn1 () {
console.log('fn1 calling fn2 now:')
this.fn2();
}
fn2 () {
console.log('fn1 called me')
}
}
let myForm = new Form();
myForm.fn1();
Example can be found here
The error I keep getting is this: Uncaught TypeError: this.fn2 is not a function
There's nothing wrong with the code you show embedded into your question - that should work just fine. The issue arises when you pass a method to .addEventListener() as a callback (which shows in the code you have a link to).
Change this:
document.getElementById('call-func').addEventListener('click', this.fn1);
to this:
document.getElementById('call-func').addEventListener('click', this.fn1.bind(this));
The problem is that passing this.fn1 loses the value of this so when the listener calls the callback later, the object that it belongs to is lost and then this inside of fn1() is wrong. In addition, .addEventListener() explicitly sets the this value to the DOM element that triggered the event (which is not your object).
The same thing would happen if you did this:
let f = this.fn1;
f();
Using .bind(this) rebinds the value of this when the listener calls it.
FYI, you could also do it this way with a fat-arrow function:
document.getElementById('call-func').addEventListener('click', () => this.fn1());
Or, an older way of doing it:
var self = this;
document.getElementById('call-func').addEventListener('click', function() {
self.fn1();
});
My preference is to use .bind(this).
More explanation on event listeners and this here: "This" within es6 class method
More explanation on the general concept of how this gets set when a function is called here: When you pass 'this' as an argument

How do I reference the containing class from within a static method when "this" is already taken by the calling object?

Using ES6/ES2015 and webpack, I am trying to wrap my head around the little monster that is the keyword this.
I have a class Edit containing a static method change(event) and within that method I am trying to make a recursive call to the method itself (depending on a given variable).
In most cases I could just call this.change(event) but here the keyword this is already occupied by the jquery object that was calling the function instead of the containing class.
The easiest solution would be to just call Edit.change(event) instead, but there must be a cleaner solution. Every programming language I have encountered so far has had some reference to its containing class built in.
I promise I have checked the docs and other threads on stackoverflow, but no one I found seems to address this particular problem.
// main.js
'use strict';
const $ = require('jquery');
const Edit = require('./Edit');
$(document).ready(() => {
let thingsToAddToData = {
whatToDo: // defined here depending on context
someVariable: //defined here depending on context
};
$('table :input').change(thingsToAddToData, Edit.change);
}
and here the Edit class is defined
// Edit.js
class Edit {
static change(event) {
if(event.data.whatToDo === 'do_nothing'){
return false;
}
if(event.data.whatToDo === 'do_this_important_thing'){
// here some important stuff is done
return true;
}
if(event.data.someVariable === 'special_case'){
event.data.whatToDo = 'do_this_important_thing'
// THIS IS THE LINE THAT GIVES ME HEADACHES
return this.change(event);
}
// here some default stuff is done
}
}
module.exports = Edit;
The easiest solution would be to just call Edit.change(event) instead, but there must be a cleaner solution
No, this is indeed what you need to use to always refer to the Edit class. There's nothing messy with it, just use it.
You could also use this.change(event) if you weren't using the method as an event handler. Make sure to call it as a method:
$('table :input').change(thingsToAddToData, Edit.change.bind(Edit));
// or
$('table :input').change(thingsToAddToData, e => Edit.change(e));
Either of the answers by #Bergi, should work (using Function.prototype.bind or () => {}). However I think your problem is more structural. Since Edit.change is an event handler it doesn't make sense to call it directly, since it is supposed to be fired through events.
I would suggest firing the event again with some parameter changes (http://api.jquery.com/trigger/):
replace Edit.change(event); with this.trigger(event);
That way there is no need for calling the handler directly, and you don't need to change the this context, thus keeping the code more transparent.
Static methods operate on the class instead of instances of the class, they are called on the class. There are two ways to call static methods:
<ClassName>.methodName()
or
<class-instance>.constructor.methodName()
In static methods, the this keyword references the class. You can call a static method from another static method within the same class with this.

Vuejs Arrow Function not triggering second statement [duplicate]

This question already has answers here:
Use arrow function in vue computed does not work
(6 answers)
Closed 5 years ago.
I am using a lambda expression within the methods section of a Vuejs component.
The example is below
I trigger alertyou() and get the alert, click okay. Then in the vue developer tools I see this.activated becomes true.
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App',
activated: false
}
},
methods: {
alertme: () => { alert('Clicked'); this.activated = false; },
alertyou() {
alert('Alert You');
this.activated = true
}
}
}
However, when I click the button that triggers the alertme lambda. I get the alert message, click okay. But then this.activated stays true!
What is going on here is this a limitation with lambdas? Can you only trigger one statement per lambda? Or does this have to deal with scope once an alert is fired?
What is going on here is this a limitation with lambdas? Can you only trigger one statement per lambda? Or does this have to deal with scope once an alert is fired?
It’s neither.
An arrow function keeps this bound to the context it was when the arrow function was created. In this case, this is not the vue instance. It’s probably window
A function declared on an object using the function keyword (or the ES6 object shorthand style) will normally have this bound to the object on which the function is declared.
That’s why you can access this.activated on alertyou but not alertme
You’ll want to use the same syntax as alertyouto declare the alertme method.
Change alertme: () => { alert('Clicked'); this.activated = false; } to alertme() { alert('Clicked'); this.activated = false; }. You can see a working example here

Categories

Resources