67

I am trying to distinguish between left and right clicks in an onClick function:

const App = () => {
  const handleClick = (e) => {
    // detect a left click
    if (e.which == 1){ 
      // do something
    }
  };
  return <p onClick={handleClick}>Something</p>;
};

Turns out e.which is undefined for Synthetic Events. How can I distinguish between left and right clicks here?

Matthemattics
  • 9,577
  • 1
  • 21
  • 18
Bhargav Ponnapalli
  • 9,224
  • 7
  • 36
  • 45

5 Answers5

120

In modern versions of React (v16+), both onClick and onContextMenu props need to be passed to detect both left- and right-click events:

return <p onClick={handleClick} onContextMenu={handleClick}>Something</p>

You can either check against e.nativeEvent.button (as the other answer implies), or check e.type on the synthetic event itself.

Using e.type

const handleClick = (e) => {
  if (e.type === 'click') {
    console.log('Left click');
  } else if (e.type === 'contextmenu') {
    console.log('Right click');
  }
};

Using e.nativeEvent

const handleClick = (e) => {
  if (e.nativeEvent.button === 0) {
    console.log('Left click');
  } else if (e.nativeEvent.button === 2) {
    console.log('Right click');
  }
};

Here's an updated demo demonstrating how this works.

You may also want to read the React documentation for SyntheticEvent.

(original demo)

Matthemattics
  • 9,577
  • 1
  • 21
  • 18
Dhiraj
  • 33,140
  • 10
  • 61
  • 78
25

The property you're looking for is e.button or e.buttons.

The button number that was pressed when the mouse event was fired: Left button=0, middle button=1 (if present), right button=2.
MDN:Web/Events/click

However, with or without react, I'm only getting click events with the left mouse button (trackpad). You could use onMouseDown which works for me.

Here's a demo using e.buttons. You may want to preventDefault in onContextMenu also.

Brigand
  • 84,529
  • 20
  • 165
  • 173
7

Use:

if (e.button === 0) { // or e.nativeEvent.which === 1
    // do something on left click
}

Here is a DEMO

marcel
  • 2,967
  • 1
  • 16
  • 25
4
onContextMenu={e => console.log("right-click")}


onClick={e => console.log("left-click")}

I found this solution on React's official documentation in the "Mouse Events" section.

Here's the TypeScript definition of onContextMenu's synthetic event.

  • Please read "[answer]". It helps more if you supply an explanation why this is the preferred solution and explain how it works. We want to educate, not just provide code. – the Tin Man Mar 11 '22 at 05:54
  • See "[Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem. – the Tin Man Mar 22 '22 at 05:11
1

The approach that I use to distinguish between left and right click:

const buttons = {
  left: 0,
  middle: 1,
  right: 2,
};

export const App = () => {
  const handleChange = (e) => {
    if (e.button === buttons.left) {
      console.log('left');
    } else if (e.button === buttons.middle) {
      console.log('middle');
    } else if (e.button === buttons.right) {
      console.log('right');
    }
 };

 return (
    <div onContextMenu={(e) => e.preventDefault()} onMouseDown={handleChange}>
      Click me!
    </div>
 );
};
darjan97
  • 11
  • 1