Dynamic SVGs are a powerful way to build user interfaces, and they work in React with little fuss. For example, here is a language learning tool that I am working on:

Language learning editor

Every line is an SVG component that connects nodes, and moves along with them. However, moving a node causes every SVG element to re-render. This can grind your page to a halt. The key is to render only what you need using React.PureComponent and React.memo.

A test SVG. The two nodes control one of the lines.

This is a test SVG, with three lines and two nodes. The positions of the two nodes are used to control one of the lines:

onNodeMoved = () => {
    // Move the correct line when the node moves
}

render() {
    const lines = this.state.lines.map((line, idx) => {
        return (
            <Line
                key={idx}
                id={line.id}
                x1={line.x1}
                y1={line.y1}
                x2={line.x2}
                y2={line.y2}
            />
        );
    });

    return (
        <svg>
            <Grid />
            { lines }
            <Node
                onClick={this.onNodeMoved}
            />
            <Node
                onClick={this.onNodeMoved}
            />
        </svg>
    )
}

Inside the Line and Node components we log every time they render. After the initial render:

Log output after the initial render.

Everything renders, as expected. What happens if we move a node?

After moving a node, the line adjusts based on new props. Log output after moving a node.

Everything got re-rendered, not great.

Let’s change our Node component to a PureComponent, so it only renders when props actually change:

class Node extends React.PureComponent {
    ...
}

Log output after making Node a PureComponent.

That’s better, only the node that was moved got re-rendered. Let’s do the same thing to the Line component. Since it is a functional component, we export using React.memo instead of changing the parent class:

const Line = (props) => {
...
}

export default React.memo(Line); 

Log output after using React.memo.

Now only the node and the line are being re-rendered. As you add more and more SVG elements, this can save you a ton of renders.