I pass 2 values to a child component:
List of objects to display
delete function.
I use a .map() function to display my list of objects(like in the example given in react tutorial page), but the button in that component fires the onClick function, on render(it should not fire on render time). My code looks like this:
module.exports = React.createClass({
render: function(){
var taskNodes = this.props.todoTasks.map(function(todo){
return (
<div>
{todo.task}
<button type="submit" onClick={this.props.removeTaskFunction(todo)}>Submit</button>
</div>
);
}, this);
return (
<div className="todo-task-list">
{taskNodes}
</div>
);
}
});
My question is: why does onClick function fire on render and how to make it not to?
Because you are calling that function instead of passing the function to onClick, change that line to this:
<button type="submit" onClick={() => { this.props.removeTaskFunction(todo) }}>Submit</button>
=> called Arrow Function, which was introduced in ES6, and will be supported on React 0.13.3 or upper.
Instead of calling the function, bind the value to the function:
this.props.removeTaskFunction.bind(this, todo)
MDN ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
The Problem lies in how you pass your function
At the moment you are not passing the function but Calling it instead:
<Button onClick={yourFunction()} />
You can Fix this in two ways:
<Button onClick={() => yourFunction(params)} />
Or if you dont have any params:
<Button onClick={yourFunction} />
The value for your onClick attribute should be a function, not a function call.
<button type="submit" onClick={function(){removeTaskFunction(todo)}}>Submit</button>
you need to use an arrow function with onClick in order to prevent immediately invoke.
so if your button looks like this :
<button onClick={yourfunctionname()} />
it must be like this :
<button onClick={() => yourfunctionname(params)} />
JSX is used with ReactJS as it is very similar to HTML and it gives programmers feel of using HTML whereas it ultimately transpiles to a javascript file.
Writing a for-loop and specifying function as
{this.props.removeTaskFunction(todo)} will execute the functions
whenever the loop is triggered .
To stop this behaviour we need to return the function to onClick.
The fat arrow function has a hidden return statement along with the bind
property. Thus it returns the function to OnClick as Javascript can
return functions too !!!!!
Use -
onClick={() => { this.props.removeTaskFunction(todo) }}
which means-
var onClick = function() {
return this.props.removeTaskFunction(todo);
}.bind(this);
For those not using arrow functions but something simpler ... I encountered this when adding parentheses after my signOut function ...
replace this <a onClick={props.signOut()}>Log Out</a>
with this <a onClick={props.signOut}>Log Out</a> ... ! 😆
JSX will evaluate JavaScript expressions in curly braces
In this case, this.props.removeTaskFunction(todo) is invoked and the return value is assigned to onClick
What you have to provide for onClick is a function. To do this, you can wrap the value in an anonymous function.
export const samepleComponent = ({todoTasks, removeTaskFunction}) => {
const taskNodes = todoTasks.map(todo => (
<div>
{todo.task}
<button type="submit" onClick={() => removeTaskFunction(todo)}>Submit</button>
</div>
);
return (
<div className="todo-task-list">
{taskNodes}
</div>
);
}
});
I had similar issue, my code was:
function RadioInput(props) {
return (
<div className="form-check form-check-inline">
<input className="form-check-input" type="radio" name="inlineRadioOptions" id={props.id} onClick={props.onClick} value={props.label}></input>
<label className="form-check-label" htmlFor={props.id}>{props.label}</label>
</div>
);
}
class ScheduleType extends React.Component
{
renderRadioInput(id,label)
{
id = "inlineRadio"+id;
return(
<RadioInput
id = {id}
label = {label}
onClick = {this.props.onClick}
/>
);
}
Where it should be
onClick = {() => this.props.onClick()}
in RenderRadioInput
It fixed the issue for me.
It is possible to achieve this even in more readable way than:
<button onClick={() => somethingHere(param)}/>
const Comp = () => {
const [triggered, setTriggered] = useState(false);
const handleClick = (valueToSet) => () => {
setTriggered(valueToSet);
};
return (
<div>
<button onClick={handleClick(true)}>Trigger</button>
<div>{String(triggered)}</div>
</div>
);
};
That way it won't fire the state setter and won't cause too many re-renders compared to <button onClick={setTriggered(true)}/>
which is okay if you don't have any params to pass to the function.
That's because you are calling the function directly instead of passing the function to onClick
If you have passed down onClick={onClickHandler()} then, the function onClickHandler() will be executed during the time of rendering too, the () instructs to execute the function as soon as it is rendered , which is not desired here , instead we use onClick={onClickHandler} , this will execute the onClickHandler only when the specified event occurs. But if we want to pass down a argument along with the function then we can make use of ES6 arrow function.
For your Case :
<button type="submit" onClick={() => this.props.removeTaskFunction(todo)}>Submit</button>
Bit late here but here is the simple answer.
direct approach will trigger by itself due to JS DOM rendering
onClick={this.props.removeTaskFunction(todo)}
anonymous arrow function approach. it will trigger on click
onClick={()=>this.props.removeTaskFunction(todo)}
You are not passing the function as an argument you are calling it directly that why it launches on the render.
HOW TO FIX IT
there are two ways:
First
<Button onClick={() => {
this.props.removeTaskFunction(todo);
}
}>click</Button>
OR
Just bind it
this.props.removeTaskFunction.bind(this,todo);
Related
I have a material-ui button and am trying to pass some parameter to my callback function on click.
For some reason, the below way is not working.
const myApi = async (param) => {
}
<Button onClick={myApi('text')}
data-testid='my-field'>
<Icon accessibleText="__label__search" name="search" size={12} />
</Button>
Use
onClick = {() => myApi("text")}
I am using the ButtonGroup and Button from ReactStrap. I have set an onClick function when you click one of the buttons:
< ButtonGroup >
<Button>Edit</Button>
<Button onClick={console.log("Print some text")}>Print text</Button>
<Button>Set as default</Button>
</ButtonGroup >
But when I load the page this is what I get:
Before I have even clicked the button. And if I do click it, nothing comes out in the console. Any ideas?
Onclick must be function. You just set onlick as result of console.log("Print some text")
Try this
<Button onClick={() => {console.log("Print some text")}}>Print text</Button>
onClick parameter is evaluated as a callback, so if you pass something that is not a function, is evaluated and executed in the runtime.
Instead, you should pass a function to the onClick parameter:
<Button onClick={() => { console.log("Print some text"); }}>Print text</Button>
Be careful with the inline functions because they are evaluated each time that render is executed, that can be multiple times, each functions is more memory used by the browser.
If you has a class, you can use a arrow fat method:
/* ... */
handleOnClick = () => {
console.log("Print some text");
}
render() {
return (
<ButtonGroup>
<Button>Edit</Button>
<Button onClick={this.handleOnClick}>Print text</Button>
<Button>Set as default</Button>
</ButtonGroup >
);
}
/* ... */
To make it clearer
On any event trigger (onClick, onChange , etc) you must specified a function to call when the event occur
not calling the function right away
Consider this function
ES5:
function callMe() {
console.log("Some text");
}
ES6:
const callMe = () => {
console.log("Some text");
}
if you want to call this function when clicking the button you can't do this
<Button onClick={callMe()}>Print text</Button>
This will call the fuction callMe when the button is loaded once.
What you need to do to make it works is
<Button onClick={callMe}>Print text</Button>
Notice that there is no parenthesis after the function name which indicate that the function is not yet called.
I have a button and i want to call a particular function if a particular situation is true , if it is not true then i want to call other function .
But i want to handle above scenario in one onClick event .
I have tried this
<button onClick= {addTodo , handleClickOpen}> Add Todo </button>
I thought that first it will check addTodo function and if addTodo doesn't complete its work then handleClickOpen function will be called .
But Button doesn't perform like this.
Would you please suggest some other way ?
Thank you
You can do a simple inline if:
<button onClick= {e => myBooleanCondition ? addTodo(e) : handleClickOpen(e)}> Add Todo </button>
As far as I understood, you can simply call one function on onClick that contains the if/else statement.
const onClick = () => {
if () { //some condition
addTodo();
} else {
handleClickOpen();
}
}
<button onClick= {onClick}> Add Todo </button>
The above syntax can vary as per your code standards/structure.
The way i would do it is using ternary operator
<button onClick= {event => condition ? addTodo(event) : handleClickOpen(event)}> Add Todo </button>
and you can also call the second function which decides which function to operate
<button onClick= {event => handleClick(event)}> Add Todo </button>
now in your js file use this function
handleClick(event){
if(event){
addTodo();
}else{
handleClickOpen();
}
}
I am new to React and learning click events. But the issue I faced is that one button click I get "Cannot GET /[object%20Object]". Here is the code I am using:
class Engine extends React.Component {
render() {
let types = ["Diesel", "Gazoline"];
return (
<div>
<Car type={types} />
</div>
);
}
}
class Car extends React.Component {
open() {
console.log("You have clicked");
}
render() {
return (
<div>
<h1>
{this.props.type.map((item, index) => {
return <p key={index}>{item}</p>;
})}
</h1>
<button onClick={open}>Remove all</button>
</div>
);
}
}
const box = document.querySelector(".mir");
ReactDOM.render(<Engine />, box);
You need to use this.open, since it doesn't know exactly what you're referring to by open :
<button onClick={this.open}>Remove all</button>
If you were to have named the function, say, foo instead of open, then it wouldn’t have worked at all.
The reason why you're seeing the functionality is because it is using the default open command built into JavaScript, which opens a new page. Under the hood, clicking the button is calling open(e) where e is the button event. So it's trying to open a new page, but instead of it receiving a URL, it's receiving an object, and thus you're seeing the error you received.
Instead, you want to use the open that is defined in the class. In order to do that, you need to use this.open.
In addition, if you want to pass something to the function as an argument, you'll need to change it a bit.
You can change open to:
open = (myparam) => {
console.log("You have clicked");
console.log(myparam);
}
In order to bind this. Then you can do something like:
<button onClick={_ => this.open("foo")}>Remove all</button>
You need to bind the open function to component and also call it with 'this'.
Or you can make the arrow function.
<button onClick={this.open.bind(this)}
or
open = () => { ... }
<button onClick={this.open}
I am using the ButtonGroup and Button from ReactStrap. I have set an onClick function when you click one of the buttons:
< ButtonGroup >
<Button>Edit</Button>
<Button onClick={console.log("Print some text")}>Print text</Button>
<Button>Set as default</Button>
</ButtonGroup >
But when I load the page this is what I get:
Before I have even clicked the button. And if I do click it, nothing comes out in the console. Any ideas?
Onclick must be function. You just set onlick as result of console.log("Print some text")
Try this
<Button onClick={() => {console.log("Print some text")}}>Print text</Button>
onClick parameter is evaluated as a callback, so if you pass something that is not a function, is evaluated and executed in the runtime.
Instead, you should pass a function to the onClick parameter:
<Button onClick={() => { console.log("Print some text"); }}>Print text</Button>
Be careful with the inline functions because they are evaluated each time that render is executed, that can be multiple times, each functions is more memory used by the browser.
If you has a class, you can use a arrow fat method:
/* ... */
handleOnClick = () => {
console.log("Print some text");
}
render() {
return (
<ButtonGroup>
<Button>Edit</Button>
<Button onClick={this.handleOnClick}>Print text</Button>
<Button>Set as default</Button>
</ButtonGroup >
);
}
/* ... */
To make it clearer
On any event trigger (onClick, onChange , etc) you must specified a function to call when the event occur
not calling the function right away
Consider this function
ES5:
function callMe() {
console.log("Some text");
}
ES6:
const callMe = () => {
console.log("Some text");
}
if you want to call this function when clicking the button you can't do this
<Button onClick={callMe()}>Print text</Button>
This will call the fuction callMe when the button is loaded once.
What you need to do to make it works is
<Button onClick={callMe}>Print text</Button>
Notice that there is no parenthesis after the function name which indicate that the function is not yet called.