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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With