Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React SVG not rerendering on attribute update

I'm updating an SVG filter attribute via a slider input control but it doesn't continuously update the rendered filter.

Here is the working code: https://codepen.io/dgwyer/pen/EXmqrb

If I use dangerouslySetInnerHTML to set the filter then it works but this hack isn't good enough to use in production code?

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { blur: 2 };
    this.blurChange = this.blurChange.bind(this);
  }

  blurChange(event) {
    this.setState({ blur: Number(event.target.value) });
  }

  render() {
    return (
      <div>
        <svg width="0" height="0" viewBox="0 0 0 0">
          <filter id="outline"
            dangerouslySetInnerHTML={{
              __html: `<feGaussianBlur result="blurOut" stdDeviation="${this.state.blur}" />`
            }}
          />
          <filter id="outline1">
            <feGaussianBlur result="blurOut" stdDeviation={this.state.blur} />`
          </filter>            
        </svg>
        <h1 className="fe">Working</h1>
        <div className="control"><input type="range" min="0" max="50" onChange={this.blurChange} value={this.state.blur} /><h3>Blur Slider</h3></div>
        <h1 className="fe1">Not Working</h1>
        <div className="control"><input type="range" min="0" max="50" onChange={this.blurChange} value={this.state.blur} /><h3>Blur Slider</h3></div>
        </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("app"));

Is there anyway to update an SVG filter attribute as you normally would with React without using the dangerouslySetInnerHTML hack?

like image 474
dgwyer Avatar asked Mar 29 '19 15:03

dgwyer


People also ask

Should you use SVG in react?

However, SVG is not without flaws: Texts inside SVG do not flow like in HTML. Break text manually into <tspan> works for one-off graphics, but it is not scalable. However, SVGs can enrich our React websites and applications with little effort with the right use case.

How do I import an SVG file as a component?

When importing an SVG as a component, we can inline SVGs directly in our markup & use them as a component. SVGR is the library that powers this ability. Setting it up could be a little hairy, thankfully many popular frameworks (Create React App, Gatsby) support this feature out of the box. JSX supports all SVG tags.

How do I customize the referenced text in SVG?

The referenced text can still be customized by adding attributes to the use tags. <use> is really cool & we'll see in the last example how it can be used to nest external SVGs. One of the pain points of using SVG is its coordinate system.

What are the disadvantages of using SVG?

However, SVG is not without flaws: Texts inside SVG do not flow like in HTML. Break text manually into <tspan> works for one-off graphics, but it is not scalable.


1 Answers

Interesting, apparently the <feGaussianBlur /> has to be re-mounted for changes to apply correctly and React doesn't re-mount it but only updates the stdDeviation attribute. To fix it use key prop additionally on <feGaussianBlur /> so that React re-mounts it each time this.state.blur changes:

<filter id="outline1">
  <feGaussianBlur key={this.state.blur} stdDeviation={this.state.blur} />
</filter>
like image 75
GProst Avatar answered Oct 22 '22 19:10

GProst