What is the difference between:
const handleChange = (event) => {
setValue(event.target.value);
};
and
const handleChange = (event, newValue) => {
setValue(newValue);
};
? The first seems to work in some cases, and the second in others.
First of all, I want to tell you that you are just passing a function for events like onChange or onClick, right? So, this is simple. We can pass any parameters to a function based on our needs. For those events, we basically use the following syntaxes:
const handleChange = (event) => {
setValue(event.target.value);
};
Here handle change is just a normal function, so it is not required that you only have to pass event as your parameter. It can be anything that you require to process that function. For the above use case, you needed input value that's why you passed the event object as the first param. But, maybe sometimes you will need extra data to work with that function. For example, you have multiple inputs, like below. You can add such inputs by clicking plus icon. And we might be storing data in an array of objects [{trait_type:'', value:''},{trait_type:'',value:''}], each array element represents a pair of those input. It will be efficient to use a change handler that accepts both (event and index) of input as params.
What is the main point is you are just passing functions to those events, and you can pass 0 or more parameters. It is not the rule that you have to pass Event for all event handlers. Yeah, sometimes you might require an Event object to stop propagating the event. Hope this explanation will help you. Make changes as you needed and best suited for you. Thank you.
Related
I'm using d3.js for an application, and in D3 (v7.6), event handlers get passed the event object and the data associated with the node receiving the event. I have some event handlers that don't actually use the event object but just need access to its data. For example:
selection.on('click', (event, d) => {
console.log(d)
})
In the above case, the handler doesn't need event. However, as far as I know, I still need to include event as the first argument passed to the function in order to access d. If I changed the function to d => console.log(d), d will actually be the event object and not the data I need.
I'm wondering what is considered best practice in this situation, where there's a function that only needs the second argument passed to it and not the first. Do I just keep event as the first argument, even though it won't be used? Or is there a better approach to this?
I have looked over a bit of textbooks and blog posts but most seem just mumble through without a clear explanation...
in a event handler in React, I was told to write,
onChange = {() => setValue(someValue)}
onChange = {() => this.props.someFunction(someValue)}
I just don't understand why I cannot simply write something like
onChange = {setValue(someValue)}
onChange = {this.props.someFunction(someValue)}
since in my understanding setValue is a function by itself already, "() =>" look absolutely redundant to me.
On the other hand, if the event is defined within a class then I am allowed to write like this
onChange = {this.someFunction}
How come I am not required to write as aarow function in this case then? Like
onChange = {() => this.someFunction}
Isn't that double standard???
Because this:
this.someFunction
and this:
this.someFunction()
are two very different things. The first one is a reference to the function itself, whereas the second one executes the function and evaluates to its return value.
So when you do this:
onChange = {this.someFunction}
you're telling it:
When the value changes, execute this.someFunction and pass it the change event.
But when you do this:
onChange = {this.someFunction()}
you're telling it:
Execute this.someFunction right now, passing it nothing. When the value changes, execute whatever this.someFunction returned (which probably isn't an executable function) and pass it the change event.
The purpose of the arrow function is to create a function where one doesn't already exist. So if you just have a simple function reference, pass it:
onChange = {this.someFunction}
But suppose you want to do two things, not just call that one function. In that case you'd wrap those two things in an anonymous function:
onChange = {(e) => {
this.someFunction(e);
somethingElse();
}}
Or even simpler, suppose you have a simple function reference but it exepcts the new changed value instead of the change event itself:
onChange = {(e) => this.someFunction(e.target.event)}
Basically you create a function if you don't already have one which does what you want.
Here's a function where it suppose to work when I click a "button
but surprisingly it immediately invoked without calling!
const show_card = (shopping_card_checkout) => {
console.log("ali el-deeb");
};
document.querySelector('.fa-shopping-cart').addEventListener('click', show_card()) ;
If I tried to redo the code after the event listener it says reference error as I called the function before declaration.
Help a beginner.
Saw your post request in JS FB group and thought I'd answer here.
First you need to use document.ready or make sure that all js is loaded as last cause else the element might not yet exist. This is not th cause of your problem btw. The problem I explain as last but some advice. You use a class and querySelector, querySelector will fetch the first element in the document and if you want all elements returned you need querySelectorAll and this is not unique or would you like to bind the same action and functionality to many elements? So better would be to use the unique id of an element and use something like:
const myElement = document.getElementById("idName");
myElement.addEventListener("click", myFynction);
const myFunction = () => console.log("Clicked");
The real cause of your issue
You bind the function to the click event and bind it with () behind it and that triggers the execution cause now you don't bind the function but the result of the bound function, you can't pass parameters like that to a bound event. You will need to fetch them inside the function cause only event and a callback can be triggered.
So your working code is:
const show_card = (shopping_card_checkout) => console.log("ali el-deeb");
document.querySelector('.fa-shopping-cart').addEventListener('click', show_card);
And if only one return or one statement inside an arrow function there is no need for the curly brackets and no need to use return since it will automatically return the result of the oneliner.
Apologies in advance as I have done some searching and this appears to be a fairly common question, but none of the answers I have found quite meet my needs. The closest I was able to find was How do I add and remove an event listener using a function with parameters?, but the answer there involves JQuery and I am trying to find a way to do this in just JS.
I am using anonymous functions to pass parameters through an event trigger which I believe is the correct way to do so. If temp is defined by some calculations based on the state at the time the event is added, I want to add the listener as follows:
item.addEventListener("click", function(){myOnClickFunction(temp)});
However, I want to be able to remove the event dynamically if certain conditions are met.
item.removeEventListener("click", function(){myOnClickFunction(temp)});
This does not work as the inline function is anonymous and cannot be referenced for matching up the event listener (plus temp is likely different anyway). Since temp is calculated at the time of the trigger, I cannot store a reference outside of the anonymous function with something like this:
var listener = function() {
var temp = calculate(arg1, arg2, event);
myFunction(temp);
};
window.addEventListener('click', listener, false);
so that I can later call:
window.removeEventListener('click', listener, false);
myOnClickEvent(temp){
//My code and calculations here
document.removeEventListener("keypress", arguments.callee);
}
is also not working, although I'm less confident as to how that method is supposed to work.
How can I remove this function dynamically? In some cases, I might be able to refactor my code so that all variables that need to be passed are stored globally and rewritten constantly, but that sounds like messy code. Plus, in some cases the trigger event is one of the arguments that needs to be passed so I don't think I could make that happen. Any ideas?
You can create an object, whose properties are the temp values, and whose values are myOnClickFunction bound to that temp. For example:
const boundFns = {};
// acquire temp somehow
const boundFn = () => myOnClickFunction(temp);
boundFns[temp] = boundFn;
item.addEventListener("click", boundFn);
Then, when you need to remove the listener, retrieve the appropriate bound function:
item.removeEventListener("click", boundFns[temp]);
If a temp may be used more than once, check if it exists in boundFns first:
const boundFns = {};
// acquire temp somehow
if (!boundFns[temp]) {
boundFns[temp] = () => myOnClickFunction(temp);
}
const boundFn = boundFns[temp];
boundFns[temp] = boundFn;
item.addEventListener("click", boundFn);
If temp cannot be be used reliably as a unique object key (for example, if it's an HTMLElement), you can use a Map instead, which is like an object, but whose keys can be anything, not just strings:
const boundFns = new Map();
boundFns.set(temp, boundFn);
// ...
item.removeEventListener("click", boundFns.get(temp));
Hi so I am just wanting to understand how javascript/react is handeling whats going on when I have a function triggered from an event . Im going to show three different code segements, 2 of which work, one of which didnt, and see if I am understanding them correctly. :)
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={() => this.setField()}>
this doesnt work because it is passing a null value to a function that expects a value, in this case e. however, if the function was just submitting something already in state, that would be reasonable way to do it.
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={(e) => this.setField(e)}>
this works because it is getting the event as e and then passes it to the function. How does it know to associate the event to e? does this functionality extent to other things when dealing with html?
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={this.setField}>
This one I really dont understand why it works, but it does. I am assuming that it inherently know to pass the event as default to the function. again does this inbuilt logic occur anywhere else, maybe not neccessarily for events?
Thanks again. Im new to javascript so it is interesting to learn all the idosyncracies of javascript. sadly most of then learning is through frustration of debugging!
All functions in javascript can be passed an arbitrarily large number of parameters, even if the function doesn't do anything with them. For example, the following is legal, if useless:
function thingThatExpectsZeroParams() {
console.log('hello');
}
thingThatExpectsZeroParams(1, 2, 3, 4, [5], 'six');
Six pieces of data were passed into the function, but nothing happened with them because the function didn't do anything with them. To get access to the values passed in, you just need to pick a name that you're going to call it. This name is local to your function and can be anything you want.
function callback(event) {
console.log(event);
}
// I could also just have easily called it something else, and the code would work just as well
// function callback(quesoBurrito) {
// console.log(quesoBurrito);
// }
callback('hello');
So when you set up a listener like this:
onChange={() => this.setField()}
Your function will be called, passing in the event object. But since your function doesn't give the first parameter a name, you have no way to access it, and then when you call this.setField, you pass nothing in there either.
In contrast, with this listener:
onChange={(e) => this.setField(e)}
Your function will again be called, passing in the event object. This time, you named that argument 'e', and can then do with it what you will, in this case forwarding it along to setField.
And when you do this:
onChange={this.setField}
You cut out the middleman. this.setField will get called directly, passing in the event object. Presumably, setField is expecting this, and does something with the object it was passed.
It's not complicated. Whatever Javascript function you assign to onChange will get called at the appropriate time and passed one single argument generally known as e. You can give that argument any name you want in your function (or not declare it at all), but the first argument will be there.
So, when you do this:
onChange={() => this.setField()}
You are ignoring the argument passed to your event handler and then inside that event handler you're calling this.setField() which to no surprise does not pass any argument to setField(). In reality, what's actually happening is this:
onChange={(e) => this.setField()}
How does it know to associate the event to e? does this functionality extent to other things when dealing with html?
The DOM specification says that when an onChange event handler is called, it will be passed the e object as the first argument (whether you declare it or not, it's there as the first argument to the function). This is just how callbacks work in Javascript. The caller of the callback decides what arguments they are going to pass the callback. It's up to you when you declare your callback whether you declare the argument and use it or not. Regardless of how you declare it, the caller passes it.
For this section of code:
onChange={this.setField}
You are say that the function you want to be the onChange event handler is your setField() method. So, no surprise, when the DOM calls that method, it will pass the event object as the first argument just like in the above example.
This one I really dont understand why it works, but it does. I am assuming that it inherently know to pass the event as default to the function. again does this inbuilt logic occur anywhere else, maybe not neccessarily for events?
As described earlier the DOM specification is where this event handler is specified. In the definition of that, it describes what arguments will or won't be passed to whatever callback function you register as this event handler. This is true of all callbacks in Javascript. The caller decides what it will pass to the callback. This is not specific to this type of event handler. Callbacks are used lots of places in Javascript. Even something like array.filter() takes a callback and it's the caller of the callback (the implementation of the Array object in that case) that determines what arguments are passed to the callback.