Reputation: 2833
I have a component that contains a basic onClick function.
The function is called when the component is rendering (without any click), why is it happening?
import React, { Component } from "react";
class Some extends Component {
constructor(props) {
super(props);
}
someFunc = (message) => {
console.log(message)
}
render() {
return (
<p onClick={this.someFunc('hello')}>test</p>
)
}
}
Upvotes: 0
Views: 1423
Reputation: 3103
in React you need to pass unexecuted functions, so either
onClick = {this.someFunction}
or if you need to pass an argument
onClick = {() => this.someFunction('argument')}
Upvotes: 4
Reputation: 633
tl;dr: You are invoking this.someFunc('hello') when you render your class, not when you call your onClick property. To fix it, you should use an arrow function, as so:
<p onClick={() => this.someFunc('hello')}>test</p>
Now if you want to know why this happens, let me clarify what you are doing.
import React, { Component } from "react";
class Some extends Component {
constructor(props) {
super(props);
}
// You define a class method that when called will in turn call the
// console.log method, passing message as your argument.
// message will equal 'hello' in your example.
someFunc = (message) => {
console.log(message)
}
// You define a render method of your class, react will
// automatically call this method on render.
render() {
// Your render method (which again is called automatically) will return
// <p onClick={this.someFunc('hello')}>test</p>
// let's see what operations you are performing in this JSX return.
return (
// You first define a paragraph html element to be rendered.
// You then give your element an attribute called onClick.
// But oh no! You are assigning onClick with the value of:
// this.someFunc('hello')
//
// That is not good, as what you are in effect saying is:
// please call the method this.someFunc and pass a single argument: 'hello'
// then assign the return of that method call to my property named onClick.
// Therefore, every time you render this class, you are asking
// javascript to call this function and get its value (which is undefined).
// So while you think onClick is a function, it is not! it is only a value.
// A value which you are asking JavaScript to get for you on each render.
// This is because in JS, when you write functionName(),
// you are literally calling the function at that moment.
// See https://www.w3schools.com/js/js_function_invocation.asp
<p onClick={this.someFunc('hello')}>test</p>
// What you want to do instead is assign your onClick property
// a function! Not a value!
// You want to write, "When I click here, do: this.someFunc('hello')"
// to do that, you have some options, but the end goal will be the same
// What you need to do is assign onClick a value, which when called (onClick)
// will trigger your function! For instance:
// onClick={() => this.someFunc('hello')}
// Above we say "on each render, assign the onClick property a value which IS a function!"
// This is, an unnamed arrow function!
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
// Notice how we have defined an unnamed function that wraps our
// this.someFunc('hello') and we have NOT
// immediately called it (no parentheses following the wrapper function)
// # outer function \() => #inner function \functionName()\ \ <-- No trailing parentheses.
// Therefore, now the only way to execute your method named
// this.someFunc('hello') is by calling its wrapper function.
// And the only way to call that unnamed wrapper function?
// By invoking your onClick property of your p element.
)
}
}
Upvotes: 0
Reputation: 63
The reason is because you write
<p onClick={this.someFunc('hello')}>test</p>
instead of
<p onClick={this.someFunc}>test</p>
.
If you put there the ()
the function will be called right on rendering, else only if clicked.
Try this arrow function
<p onClick={() => this.someFunc('hello')}>test</p>
Not tested, but should work correctly this way.
Upvotes: 0
Reputation: 1933
You don't have to append your function like that. You just need to call it by other ways:
<p onClick={() => this.someFunc('hello')}>test</p>
By using this syntax you can call it by params
.
But your first solution was just passing the function
If your function had no argument
to pass you could just pass the function like below:
<p onClick={this.someFunc}>test</p>
Because you need to pass some arguments
the first one which I mentioned will be your desired one.
You can read their document for further details: React Handling Events
Upvotes: 3