Andrew Townsend
Andrew Townsend

Reputation: 3

Overriding onClick in React

This is somewhat of weird question. I'm working with event types in React, and we want to use onClick in some instances, and onPointerDownCapture in others (for reasons). But to make this more general, it could be any two different click-like events. The issue is that while we can assign whatever function handler on the right side of the expression, the left side has to be static, essentially. So,

<button onClick={handler} vs onPointerDownCapture={handler} vs onMouseDown={handler} />

I think just using onPointerDownCapture will be fine for most usecases, but in a perfect world, I'd be able to flip between these at runtime based on other variables. Is it possible to override the onClick on the button/div/whatever prototype or something to be whatever event type I want it to be?

Much googling. No success.

Upvotes: 0

Views: 1668

Answers (3)

Matija Sirk
Matija Sirk

Reputation: 960

I think best is @vera solution in comment. Pass extra prop to component (for example isOnClick), and based on it pass either callback or undefined to event handler prop:

function Component(props: { isOnClick: boolean; callback: () => void }) {
  return (
    <div
      onClick={props.isOnClick ? props.callback : undefined}
      onMouseDown={props.isOnClick ? undefined : props.callback}
    />
  );
}

Note that passing undefined to prop is same as not setting that prop.

Alternatively conditionaly return component:

function Component(props: { isOnClick: boolean; callback: () => void }) {
  if (props.isOnClick) {
    return <div onClick={props.callback}/>
  } else {
    return <div onMouseDown={props.callback}/>
  };
}

Upvotes: 0

hackape
hackape

Reputation: 19987

I didn’t fully understand what you mean by “overriding onClick”, but

The issue is that while we can assign whatever function handler on the right side of the expression, the left side has to be static, essentially.

This is not true, left hand side could be dynamic, here’s how:

<button {...({ [eventName]: handler })} />

I guess this solves your problem.


Ok above syntax is a bit terse and admittedly confusing. It’s the good old JSX spread props syntax, just over an inline object literal.

I’ll give you another equivalent form, hopefully it should be more readable.

const eventName = someCondition ? "onPointerDownCapture" : "onClick"

const props = { 
  [eventName]: handler
}

<button {...props} />

Upvotes: 2

AchiPapakon
AchiPapakon

Reputation: 324

You have to use those attribute names and you use the same function name for all 3 of them.

What these 3 attributes do is they register the associated event.

Maybe you could use a useEffect and add there conditionally an event listener instead of the proposed React attributes.

Upvotes: 0

Related Questions