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?
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.
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.
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.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With