I have a component that loads SVG files using styled-components
and ReactSVG
. I need to add click event listeners to the anchor tags that are in the SVGs. It seems pretty straighforward and I've thought I had it working several times. The issue I am having is that programmatically, the listeners appear to be working. However, in the browser, clicking an anchor does not fire the event. If I inspect the element, the event listeners are not present. I have even created a button with a function that finds the anchors in the SVG and dispatches the events. This works as one would expect. So what is confusing me is why it doesn't work in the browser when the user clicks the anchor.
Here's the code in question. I'm obviously leaving out things that aren't relevant to the part I'm having trouble with.
const IconStyled = styled(ReactSVG)`{/* stuff and things */}`;
const SvgThingy: React.FC<SvgThingyProps> = ({ svgPath, svgWidth }) => {
const svgElementReference = useRef(null);
let anchors: NodeList | null = null;
useEffect(() => {
const svg = (svgElementReference.current as unknown) as ReactSVG;
anchors = ((svg as unknown) as HTMLElement)?.querySelectorAll('a');
anchors.forEach(anchor => {
const a = anchor as HTMLAnchorElement;
a?.addEventListener('click', (e) => {
console.log('clicked', e);
});
});
});
return (
<IconStyled
ref={svgElementReference}
src={svgPath}
width={svgWidth}
wrapper="span"
/>
);
};
Like I said, clicking the links in the browser does nothing. In the click handler for the button I created, I have this code:
const tempButtonClickHandler = (e: MouseEvent) => {
e.preventDefault();
if (anchors) {
anchors.forEach(anchor => {
const a = anchor as HTMLAnchorElement;
a.dispatchEvent(new Event('click'));
});
}
};
When I click this temp button, the events for each of the anchor tags fire as expected. I'm at a loss why this is not working in the browser and any help would be very much appreciated.
Thank you
CodePudding user response:
If you are trying to attach some events after rendering the svg
element, I would recommend you to use afterInjection
callback:
export default function App() {
const attachClickEvent = (elements = []) => {
elements.forEach((element) => {
element.addEventListener('click', (e) => {
console.log('clicked', e);
});
});
};
return (
<ReactSVG
src={'/example.svg'}
afterInjection={(error, svg) => {
if (!error) {
const anchors = svg?.querySelectorAll('a') || [];
attachClickEvent(anchors);
}
}}
/>
);
}
Working example: https://stackblitz.com/edit/react-ap41hv?file=src/App.js