With the following code, every time I click the button, "I was clicked" is outputted to the console, as expected.
function handleClick() {
console.log("I was clicked")
}
function App() {
return (
<div>
<img src="https://www.fillmurray.com/200/100"/>
<br />
<br />
<button onClick={handleClick}>Click me</button>
</div>
)
}
However, if I change handleClick to take in a parameter, the output is shown upon page load and any additional clicks don't produce additional output.
function handleClick(test) {
console.log(test + "I was clicked")
}
function App() {
return (
<div>
<img src="https://www.fillmurray.com/200/100"/>
<br />
<br />
<button onClick={handleClick("hello: ")}>Click me</button>
</div>
)
}
Why does the simple act of including a parameter change the behavior, here? I suspect it has to do with the event handler not passing along the event object in the second scenario, while automatically being passed in the first scenario, but I'm not sure what properties of the event object would be causing this behavior.
if you use () after the function; it means that the function executes. To assign values with this syntax, you can easily use
onPress={handleClick.bind(this, ...args)}
With this syntax, we bind the this of the current scope to the function and we did not execute it while assigning parameters. The way of assigning parameters and invoking the function immediately would be
handleClick.call(this, ...args)
Related
This question already has answers here:
What is the difference between a function call and function reference?
(6 answers)
Why does click event handler fire immediately upon page load?
(4 answers)
Closed 1 year ago.
I was transferring all my JavaScript code to external file :
One of the inline codes were like this :
onclick="nextPrev(-1)" ; onclick="nextPrev(1)"
The method I tried was :
document.getElementById("nextPrev").addEventListener("click", nextPrev(1))
document.getElementById("nextPrev").addEventListener("click", function(){nextPrev(1)})
The second line of code works fine, i.e, triggered on the click of button. While the first code is a type of automatic (means value is shown without any click event).
So wanted to know the difference between both method I used in external file. Also if there is any other method to write onclick="nextPrev(1)" in external file please feel free to point out.
Here is a working snippet :
function nextPrev(e){
document.getElementById("demo").innerHTML = e;
}
document.getElementById("nextBtn1").addEventListener("click", nextPrev1(1))
function nextPrev1(e){
document.getElementById("demo1").innerHTML = e;
}
document.getElementById("nextBtn2").addEventListener("click", function() {
nextPrev2(1)
})
function nextPrev2(e){
document.getElementById("demo2").innerHTML = e;
}
<button type="button" id="nextBtn" onclick="nextPrev(1)">onclick="nextPrev(1)"</button>
<div id="demo"></div>
<button type="button" id="nextBtn1">func(var)</button>
<div id="demo1"></div>
<button type="button" id="nextBtn2">function(){func(var)}</button>
<div id="demo2"></div>
Thanks for help in advance
document.getElementById("nextPrev").addEventListener("click", nextPrev(1))
This will call nextPrev(1) immediately (hence giving the impression that the event is executed immediately) and set its returned value as the event listener callback.
document.getElementById("nextPrev").addEventListener("click", function(){nextPrev(1)})
This will set the event listener callback to a function which calls nextPrev(1) whenever the event is executed. Whenever the event is fired, the function is called, and only then is nextPrev(1) called.
The difference is as simple as illustrated below:
function callme(){
console.log("hello");
}
//Does not run until callmeWrapper is executed
function callmeWrapper(){
callme();
}
//Runs automatically
callme();
The second argument of addEventListener has to be the function that is supposed to run.
In this case :
document.getElementById("nextPrev").addEventListener("click", function(){nextPrev(1)})
when you are wrapping in a function definition, the nextPrev function is not run. Here when this line is encountered in the code, the wrapper function is attached as an event handler.
In this case,:
document.getElementById("nextPrev").addEventListener("click", nextPrev(1))
you are not attaching anything.
Here as soon as this line is encountered in the code, the function is run. And the return value(undefined by default) is assigned as an event handler. That will do nothing on click.
Apologies if this is really simple but I have been researching this for a week now but can't find the right thing to type into google.
I have 3 buttons as shown below:
const playerSelection = document.querySelectorAll(".buttons").forEach(e => {
e.addEventListener('click', function() {
return e.innerHTML;
})
});
console.log(playerSelection);
<div>
<button class="buttons">Rock</button>
<button class="buttons">Paper</button>
<button class="buttons">Scissors</button>
</div>
When I console.log playerSelection it only returns undefined. I want the playerSelection variable to equal the innerHTML content of whichever button I click.
Help is appreciated.
You log the value of the button inside the click event.
Also you should set the type of your buttons to button, otherwise they are of type submit, which I guess you don't want here.
document.querySelectorAll(".buttons").forEach(e => {
e.addEventListener('click', function() {
console.log(e.innerHTML);
})
});
<div>
<button type="button" class="buttons">Rock</button>
<button type="button" class="buttons">Paper</button>
<button type="button" class="buttons">Scissors</button>
</div>
You're probably thinking of Array.prototype.map, which combines the returned results into an array.
This won't work in your case, though, as you are simply adding an event listener inside your loop. The event callback will only be triggered when the button is clicked. You'll need to write asynchronous code. For example, when a button is pressed, call a function pickedValue() with the result, which will then continue your program.
I have a newbie question that is probably really easily explained. I have an image that has an onClick property added to it. If I call an inline function to log something, it works as expected. It logs to the console whenever the image is clicked. However, whenever I have an outside function called there, it gets clicked every second which is because I have data coming in every second updating a part of the code.
My question is, why does the inline function work and the other way doesn't? What am I missing here?
inline version...
return(
<>
<SettingsButton src="./img/leaf.png" alt="" onClick={() => { console.log("button clicked");}}/>
</>
);
and the other way that doesn't work as intended...
function handleClick() {
console.log('The link was clicked.');
}
return(
<>
<SettingsButton src="./img/leaf.png" alt="" onClick={handleClick()}/>
</>
);
In your example, you are calling function as soon as the component is loaded by writing it as handleClick(), so the browser does not wait for you to click as it should be.
handleClick =()=> {
console.log('The link was clicked.');
}
return(
<>
<SettingsButton src="./img/leaf.png" alt="" onClick={handleClick}/>
</>
);
I'm useing Semantic-ui-react redux and react-router-dom. In my component I have navbar:
<Menu >
<Menu.Item as={Link} to="/" onClick = {this.onNavBarItemCLick()}>
home
</Menu.Item>
<Menu.Item as={Link} to="profile" onClick = {this.onNavBarItemCLick()}>
profile
</Menu.Item>
<Menu.Item as={Link} to="shop" onClick = {this.onNavBarItemCLick()}>
shop
</Menu.Item>
</Menu>
If I click on the one of nav items method onNavBarItemClick fires 3 times. Why it happens?
Because you call method immediately, instead you should only pas handler to onClick attribute:
as={Link} to="shop" onClick = {this.onNavBarItemCLick.bind(this)}>
Solution
You need to replace
onClick = {this.onNavBarItemCLick()}
with
onClick = {() => this.onNavBarItemCLick()} // perserving class's this
or if you prefer the bind notation
onClick = {this.onNavBarItemCLick.bind(this)} // perserving class's this
else
onClick = {this.onNavBarItemCLick} // not perserving class's this
Why it happens
It happens because when you click render() is called again.
React is very efficient in re-rendering, so it's what it's supposed to happen.
The issue with your implementation was that instead of passing a method reference, you were passing the returned value of such method.
Because you should not call it right away in the onClick prop. use this
<Menu.Item as={Link} to="/" onClick = {this.onNavBarItemCLick}>
What ends up happening, is the onNavBarItemCLick being called every time the render function is called when state changes
The onClick prop takes a function as value so what's the problem here ?
<MyComponent onClick={this.handleClick()} />
using this.handleClick() instantly call the function and gives its return value to onClick. What you want here is to give the function itself to onClick like so
<MyComponent onClick={this.handleClick} />
But you'll probably get another error there if this.handleClick uses this as it is not automatically bound in a React class. There are ways to fix this like binding this in the constructor, using an array function for handleClick or directly bind this when passing the function to onClick like
<MyComponent onClick={this.handleClick.bind(this)} />
Going a bit further, you could also return a function in handleClick which here is totally useless. It's only to illustrate :
class MyComponent extends React.Component {
handleClick () {
return () => { console.log('I am triggered on click') }
}
render () {
// We call this.handleClick() which returns the function
// that'll be actually called on click.
return <div onClick={this.handleClick()} />
}
}
I hope this helps
When you do this.onNavBarItemClick(), what happens is that the parenthesis execute the function at that point. Whereas this.onNavBarItemClick will treat it as a variable.
So in the above piece of code, when you do onClick = {this.onNavBarItemClick()}, the function is getting called there itself without the user clicking on it. Whereas if you do onClick = {this.onNavBarItemCLick} the function gets invoked only if you click on it.
You can also do onClick = {()=>this.onNavBarItemClick()}. By doing this you are creating an anonymous function and passing it to onClick.
So you can do either of onClick = {this.onNavBarItemClick} or onClick = {()=> this.onNavBarItemClick()}
I would expect that setting the disabled attribute on a react component would block the onClick handler for that element.
<a role="button"
className={`btn btn-block btn-info`}
disabled={!this.state.readyToView}
href={this.state.selectedObjectLink}
onClick={this.handleLink}
>View</a>
but although the element shows a "disabled" attribute it still registers a click event.
Edit: I should clarify - I handle the click event in handleLink, I want to know why the disabled attribute doesn't remove the handler? Sorry for any confusion.
The problem isn't with disabled; it's with the HTML element a. Anchor <a> cannot have a disabled property (what does that even mean?). Just because you've passed CSS to make the element look like a button, doesn't make it a button. It is still an anchor.
The solution would be either to use something else (like button):
<button
role="button"
className={`btn btn-block btn-info`}
disabled={!this.state.readyToView}
onClick={this.handleLink}
>
View
</button>
You can use this.state.selectedObjectLink inside handleLink if you want to redirect to a page
Or use one of the many other suggestions on this page.
Why not just handle this in handleLink?
handleLink () {
if (!this.state.readyToView) return
// ...
}
If you really want to bind/remove the handler dynamically, you can do something like this:
const clickHandler = this.state.readyToView ? this.handleLink : null
...
<a role="button"
...
...
onClick={clickHandler}
>View</a>
You can add a condition in your click handler, something like this
<a role="button"
className={`btn btn-block btn-info`}
disabled={!this.state.readyToView}
onClick={this.state.readyToView && this.handleLink}
>
View
</a>
jsfiddle
If you are using react version 16 and up
on onClick don't call the method directly use () => method instead like this
const handleRemoveBtnClick = () => {
...
}
<button ...onClick={() => handleRemoveBtnClick} />
Another trick to disable the click to any components is to use useState with boolean value either true to disable or false to resume the click functionality
example
export default const ElementComponent() =>{
//set the initial value of disable click to false
const [disableClick,setDisableClick] = useState(false)
const anotherFunction =() =>{
console.log("I've been run")
}
const handleClick()=>{
//if disableClick is false then run this if block, else don't do anything
if(!disableClick){
anotherFunction()
}
}
return(
<img src="..." onClick={handleClick}/>
)
}
the good thing about this is that we can pass the function as a props to another components and we can run it there, we can even let's say disable a click for let's say 1 second using setTimeout function, there are tons of way you can use this method, hope it helps anyone if you want to use onClick not only on the button element itself