Recently, I had a requirement to create lines using SVG for my home page design. I couldn't hard code all the SVG line elements in my JSX since the number of lines were dynamic and I needed to do some positioning logic as well.
Failed code
So I ended up with a simple useEffect code that runs once after everything renders and append the SVG lines.
useEffect( () => {
const svgElm = document.querySelector("#svgHolder");
const lineElm = document.createElement("line");
lineElm.setAttribute("x1", "20");
// ... set other attributes
svgElm.appendChild(lineElm);
}, []); // run once
The above code added the line tags to the svg element. However, it did not render anything at all on screen. The nodes were present in DOM, but nothing shows up on screen.
document.createElementNS
It turns out I need to create the line element under a specified name space using the DOM API document.craateElementNS. SO once I change document.createElement with document.createElementNS and the right namespace, my SVGs were rendering properly.
useEffect(() => {
const svgElm = document.querySelector("#svgHolder");
/* use proper namespace to create line element */
const lineElm = document.createElementNS(
"http://www.w3.org/2000/svg",
"line",
);
lineElm.setAttribute("x1", "20");
svgElm.appendChild(lineElm);
}, []);