Onclick Event Binding in React.Js

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.

  1. Yes the onClick() is also passed down to child components like any other prop.

  2. 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
component renders, which may break optimizations based on strict
identity comparison.

(From React documentation: https://reactjs.org/docs/faq-functions.html)

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



Leave a reply



Submit