OnClick Event binding in React.js
viewMore = (i,j) => () => {
console.log(i,j)
}
To pass parameters to event handlers we need to use currying. With the above method no new functions created all the time while render is called.
OnClick Event binding in React.js while code is in variable
Use
render() {
var sidebarpagedata = this.state.allServices.companies.map((sidebarpagedata, index) => {
<Button type="button" className="default pull-right" onClick={this.addCompnay} >Apply Now</Button>
})
return (
{sidebarpagedata}
);
}
Use of onClick event handler in React
In your code, onClick is both event handler and prop. Do not use onClick as a prop.
Yes the onClick() is also passed down to child components like any other prop.
You have again passed the onClick you received in the Menu component as a prop on to the RenderMenuItem component. When Menu component is clicked, props.onClick function will be called with click event. Check the following example code
function Welcome(props) {
return <h1 onClick={props.onClick}>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" onClick={(id)=>{ console.log(id) }}/>;
ReactDOM.render(element, document.getElementById('root'));
But you cannot pass an actual prop to that function in this state, for that you have to wrap it within an arrow function, which is exactly what you have done in RenderMenuItem component.function Welcome(props) {
return <h1 onClick={() => {props.onClick(12)}>Hello, {props.name}</h1>;
}
If your intention is just to pass the function to child component, use a different prop name other than onClick.const menu = props.dishes.map((dish) => {
return (
<div key={dish.id} className="col-12 col-md-5 mt-5 m-1">
**<RenderMenuItem dish={dish} clickHandler={props.onClick} />**
</div>
)
});
P.s. Do not use arrow functions in render, it will create new function on each render. Bind a function with the class controller and use it in render. class Example extends Component {
constructor(props, context) {
super(props, context);
this.clickHandler = this.clickHandler.bind(this);
}
clickHandler(id) { // Use curried function if you need event clickHandler = (id) => (event) => {}
// do something
}
render() {
return (
<div onClick={this.clickHandler(2)}></div>
);
}
}
React Js best practice - onClick event
Using an arrow function in render creates a new function each time the(From React documentation: https://reactjs.org/docs/faq-functions.html)
component renders, which may break optimizations based on strict
identity comparison.
Thus, you should go 1st scenario.
Adding click event to React.Js
Both the ways of calling handler function is incorrect in your code.
In your code handleClick is an arrow function hence manual binding is not required.
If it is not an arrow function then the manual binding should be done always in constructor only. Never do binding anywhere else like you did in render.
When you use onClick={() => this.handleClick} this is wrong. It should be onClick={()=> this.handleClick()}. If no Paranthesis then this is correct onClick={this.handleClick}
So change
<div onClick={this.handleClick.bind(this)}>
Alert 1
</div>
<div onClick={() => this.handleClick}>
Alert 2
</div>
To <div onClick={()=> this.handleClick()}>
Alert 1
</div>
<div onClick={() => this.handleClick()}>
Alert 2
</div>
The reason you should not do binding anywhere else in the component except constructor because for eg you did binding directly in render so what happens in this case is it creates a new function in webpack bundle file every time the component renders and re renders again hence bundle file grows large. Hence it is recommended to bind it only in constructor React JS onClick event inside a tag
Try:
onClick={(e) => { e.preventDefault(); e.stopPropagation(); changeOrder(stage.id, stage.title, stage.order - 1); }}
React Typescript fire onClick button event using .bind
Focussing on this line of your error chain:
Type '((id: string) => void) | undefined' is not assignable to type 'MouseEventHandler<HTMLButtonElement> | undefined'.
This error is stating that what you have configured as the type of the onAdd
hook, is incompatible with an onClick
handler that accepts a MouseEvent<...>
object as the first argument.However, because you are binding your id
and item
inside of the Cart
element, you are actually passing functions with the type () => void
down to CartItem
instead, which is different to your interface declaration anyway. These () => void
functions are compatible with onClick
handlers because they ignore any arguments passed to them.
Therefore, you can fix the issue by updating your interface to just:
export interface CartItemProps {
id: string;
name: string;
amount: number;
price: number;
onAdd?: () => void;
onRemove?: () => void;
}
This allows you to continue using the following pieces as-is:// Cart
onRemove={cartItemRemoveHandler.bind(null, item.id)}
onAdd={cartItemAddHandler.bind(null, item)}
// CartItem
<button onClick={props.onRemove}>-</button>
<button onClick={props.onAdd}>+</button>
However, if in the future cartItemAddHandler
or cartItemRemoveHandler
have more parameters added to them, and you don't bind all of the arguments of the function handlers properly, you will start getting MouseEvent<...>
objects passed through to your function unexpectedly.// Cart
cartItemRemoveHandler = (id: string, quantity: number) => { ... }
/* ... */
onRemove={cartItemRemoveHandler.bind(null, item)}
// CartItem
export interface CartItemProps
/* ... */
onRemove?: () => void;
/* ... */
}
/* ... */
<button onClick={props.onRemove}>-</button>
At runtime, when onAdd
is fired, quantity
here would be given the MouseEvent<...>
, not a number
.You can prevent mistakes like this by updating the interface to accept MouseEventHandler<HTMLButtonElement>
objects so that TypeScript appropriately reports the error when you don't bind the handlers properly.
export interface CartItemProps {
id: string;
name: string;
amount: number;
price: number;
onAdd?: MouseEventHandler<HTMLButtonElement>;
onRemove?: MouseEventHandler<HTMLButtonElement>;
}
In addition, you can swap the following lines to prevent the MouseEvent being passed in the wrong spot:cartItemRemoveHandler.bind(null, item)
for:() => cartItemRemoveHandler(item)
// or
(ev: MouseEvent<...>) => cartItemRemoveHandler(item) // no need to explicitly type the `ev` as a MouseEvent here, it will be inferred from the interface.
Side note: Even with these changes, the handler you use for onAdd
is accepting an item object, but onRemove
receives a string. This is backwards in comparison to your original interface.
Related Topics
Domnodeinserted Equivalent in Ie
Accessing JSON Object Keys Having Spaces
Why How to Not Throw Inside a Promise.Catch Handler
React Doesn't Reload Component Data on Route Param Change or Query Change
Prevent JavaScript Keydown Event from Being Handled Multiple Times While Held Down
JavaScript Call Nested Function
What's "This" in JavaScript Onclick
How to Show Current Time in JavaScript in the Format Hh:Mm:Ss
Javascript: How to Detect If a Word Is Highlighted
Decompress Gzip and Zlib String in JavaScript
Read a Text File Using Node.Js
JavaScript Timestamp to Relative Time
How to Catch Jquery $.Getjson (Or $.Ajax with Datatype Set to 'JSONp') Error When Using JSONp
Getusermedia() in Chrome 47 Without Using Https
When Do I Need to Specify the JavaScript Protocol
Gmail Extension, Sendmessage to Background from Page Context
Passing Data to a Jquery UI Dialog
How to Randomly Generate HTML Hex Color Codes Using JavaScript