Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using React, how can I attach a click event to a class or ID?

I've got an SVG with hundreds of <circle> elements that I would like to attach a click event to. Using jQuery, that's really easy:

$('circle').on('click', function(e) {
  alert('clicked');
});

How can I do this in React?

Normally I would attach an event listener to the element directly:

<circle onClick={(e) => handleClick()} />

Seeing as there are hundreds of elements, this would be very tedious. Is there a way I can attach a single event listener to all circle elements?

My working solution uses vanilla JS, but it involves interacting with the DOM directly:

useEffect(() => {
  const circles = document.querySelectorAll('circle');
    for (const trigger of circles) {
      trigger.addEventListener('click', (e) => {
        alert('clicked');
    });
  }
}, []);

I don't get any errors and this does work, but it doesn't feel like React. Am I missing something? Is there a better approach?

like image 833
Michael Lynch Avatar asked Oct 07 '19 15:10

Michael Lynch


Video Answer


1 Answers

I don't think you should worry for with vanilla JS DOM manipulation in such cases, but if you want to make it react-ish you can use Context.

First define your context:

const CircleContext = React.createContext();

then wrap your app (or part of app where circles will be used) with CircleContext.Provider and set it's value to desired callback:

function App() {
  return (
    <CircleContext.Provider
      value={e => {
        console.log("Circle clicked!");
      }}
    >
      <div className="App">
        <Circle />
      </div>
    </CircleContext.Provider>
  );
}

And consume that context in your circle component (I used useContext hook):

function Circle() {
  const context = useContext(CircleContext);
  return <button onClick={context}>My Button</button>;
}

With this implementation every Circle component will use same onClick handler defined in CircleContext.Provider.

Example code.

like image 87
zhuber Avatar answered Nov 01 '22 17:11

zhuber