Reputation: 483
I am making a react application with some SVG icons within my components. For instance, I have a SearchBar component which includes the input element along with a button that has a Search Icon in it.
I am using inline SVG for all my SVG icons, by setting the xlinkHref attribute accordingly from a single sprite file.
Everything seems to work just fine, except that my SVG icons randomly disappear when I click on them. The button element that contains the icon does not disappear, just the SVG icon. I checked the DOM tree on the devtools, and it seems like that there is an issue with a node called "#shadow-root".
When my SVG icons are visible, they are placed as child nodes of the "#shadow-root". However, when they disappear, the DOM tree shows that "#shadow-root" node no longer has any child node, effectively making my SVG icons nowhere to be found.
It is heart-breaking to see my lovely SVG icons suddenly disappear...
Please advise!
-----EDIT----- Here is the code for the component that I am using to insert SVG icons:
import React from "react";
const Icon = ({ name }) => (
<svg>
<use xlinkHref={`img/icons/sprite.svg#icon-${name}`} />
</svg>
);
export default Icon;
Upvotes: 15
Views: 5306
Reputation: 3334
You can build the SVG element yourself. You can let React build the empty <svg>
element, then manually insert a <use>
element using a ref and an effect:
const Icon = React.memo(({ url }) => {
const [svgNode, setSvgNode] = React.useState(null);
React.useLayoutEffect(() => {
if (svgNode === null) {
return;
}
const useNode = document.createElementNS("http://www.w3.org/2000/svg", "use");
useNode.setAttributeNS("http://www.w3.org/1999/xlink", "href", url);
svgNode.appendChild(useNode);
return () => {
useNode.remove();
};
}, [type, svgNode]);
return <svg ref={setSvgNode} />;
});
Based on this implementation.
Upvotes: 0
Reputation: 1504
you can try another ways to include your SVG. I mentione three possibilities:
import logo from './logo.svg';
render() {...
<img src={logo} className="App-logo" alt="logo" />
...}
import InlineSVG from 'svg-inline-react';
const svgSource = `<svg xmlns="......</svg>`;
<InlineSVG src={svgSource} />
Good luck.
Upvotes: 2