bassman21
bassman21

Reputation: 380

How to programmatically add SVG shapes to a SVG graphic within a React component?

How can I programmatically create SVG shapes that are rendered within a React component? In this example I create a string with 20 dots. However, putting {dots} between the tags <svg> and </svg> does not work. Just putting {dots} in the component's return function would just show it as a string.

What am I doing wrong? Any help and suggestion is highly appreciated!!!

import './SVGLayer.css';
import React from 'react';

const SVGLayer = () => {
  let dots: string = '';

  for (let i = 0; i < 20; i++) {
    dots += `<circle cx="${100 + i * 10}px" cy="100px" r="0.5px" stroke="black" />`;
  }

  return (
    <div className="svg-layer">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        version="1.1"
        width="800px"
        height="600px"
      >
        <circle cx="100px" cy="100px" r="1px" stroke="black" />
        {dots}
      </svg>
    </div>
  );
};

export default SVGLayer;

Upvotes: 0

Views: 716

Answers (1)

Brendan Bond
Brendan Bond

Reputation: 1890

You don't want to use template literals, because template literals are strings. React sees your {dots} and thinks, "OK, bassman21 is trying to render a string here."

If React sees JSX (fear not for your for loop, you can put a map() function into JSX), it will actually create the components that you want (its engine will replace JSX elements with calls to React.createComponent()), so why not try something like:

return (
    <div className="svg-layer">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        version="1.1"
        width="800px"
        height="600px"
      >
        <circle cx="100px" cy="100px" r="1px" stroke="black" />
        {/* There are much better ways to do this, but this should illustrate my point nicely */}
        {[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19].map((offset, idx) => <circle key={`circle-${idx}`} cx={`${100 + offset * 10}px`} cy="100px" r="0.5px" stroke="black" />}
      </svg>
    </div>
  );

This will render 20 actual elements with your data interpolated into the cx prop!

Upvotes: 1

Related Questions