React - render imported .svg file - reactjs

I need to render .svg files. I do not want to use dangerouslySetInnerHTML. I am able to successfully render an svg if I copy the svg contents directly and render it from a component.
However, this is not very reusable. I don't want to copy the contents from each .svg file. I would like to be able to import an svg file and pass that into my component that will then render the contents.
Here's what I have done so far, but it is not rendering my svg.
I have created a component that accepts an imported svg file, like this:
import React from "react";
class SvgComponent extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
props.svg // this works if I copy my .svg contents here (<svg>....</svg>)
);
}
};
SvgComponent.propTypes = {
svg: React.PropTypes.string.isRequired,
};
export default SvgComponent;
And here is how I am using that component:
import mySvg from './images/mySvg.svg';
const Icon = (props) => {
return (
<svgComponent svg={mySvg} />
);
};
Icon.propTypes = {
icon: React.PropTypes.string.isRequired,
};
export default Icon;
This does not work -- it does not show my svg on the webpage, or even in the dom. When I inspect the page, all I see is an empty svgComponent:
<svgComponent />
Any help on getting .svg files to display in react would great!

I created a module to solve this problem. With it you can load the svg and manipulate its elements using JSX without having to paste the svg code.
Npm package:https://www.npmjs.com/package/react-samy-svg
Check an example on Glitch: https://fossil-transport.glitch.me
It's simple to use
<Samy path="path to your svg file">
<Proxy select="#Star" fill="red"/>
</Samy>
Whenever you need to change some SVG attribute just create a Proxy element and use the 'select' prop (accepts CSS selectors). All props set on Proxy will be forwared as attributes to the SVG element(s)

Related

dynamically render svg icons in react

so I have around 40 svgs in my frontend in seperate files,
and I have an api route that gives me the name of the svg on request to I can import it, but I'm not quite sure how to dynamically import these svgs in react right now
I tried this but it means I can't change styles of svgs if I render them in img tag
export const renderIcon = ({ name, folder }) => {
return <img src={`/${folder}/${name}.svg`} alt="" />;
};
is there a better way of doing this?
context:
basically name just returns the name of the svg and folder is only either "outline" or "filled", I was trying to find a way to return the svg from this file but i couldn't so i was trying the img instead.

Custom webcomponent from library in React

I have a React application which should use the following library:
MICO-grapheditor
And I want to write this code:
render() {
var webgraph = require("#ustutt/grapheditor-webcomponent");
GraphEditor.
return (
<network-graph classes="red blue" mode="layout" zoom="both">
<style slot="style">
svg {width:100%; height: 100%}
</style>
<svg slot="graph"></svg>
</network-graph>
)
}}
But I get the following:
TS2339: Property 'network-graph' does not exist on type 'JSX.IntrinsicElements'.
How can I resolve this error?
At least the expression
var webgraph = require("#ustutt/grapheditor-webcomponent");
should come up before the rendering. Also, doing CSS in HTML and Node.js/React is not pretty much the same. Or is it?
React is likely assuming that network-graph is a React component, thus it expects that the attributes you are using (mode and zoom) are defined in a React component. Also React uses className instead of classes.
When you write between <network-graph> tags this content is considered as a group of child nodes that can be used by the network-graph component in the following way:
import React, { Component } from "react";
class NetworkGraph extends Component {
render() {
const {mode, zoom, children} = this.props;
return (
<>{children}</>
); // children would contain the <svg>
}
}
When you require MICO-grapheditor, you are not importing a React component, but a web component instead, even though React tries to interpret it...
Also, avoid shoving in <style> tags in the render's return. CSS styles in React may be imported to components like so import './my-styles.css';.

React redirect on click of svg element

I have a single page React App that is d3 and SVG heavy, and I would like to be able to redirect from one page to another when a user clicks on an svg rect on one of my pages. I am familiar with this.props.history.push() as well as the <Link> component from the react-router-dom library, however neither of these seem to help in this instance.
The svg element of relevance here is deep in a graphing component of mine that is 3-4 children down from the front-end's main App.js file that does all of the routing, and when I run console.log(this.props) in my component with the svg, there is no history object on the props. I'm not sure if a reproducible example is needed here, as I just need direction.
In short, I have no idea what should go into the on-click function that is associated with my svg rect, to enable redirect in my app. Any thoughts on this would be greatly appreciated!
Edit: obviously this is wrong but i tried to return a Redirect component in on-click handler and it didn't work:
...
...
function handleMouseClick() {
console.log('clicked')
return <Redirect to='/stats' />;
}
myRect.on('click', handleMouseClick)
...
Edit2: should i put the rect elements inside of components in the svg? is that even possible?
You can add the history prop from react-router to a component by wrapping it with withRouter. Just make sure whatever is mounting your component is using the wrapped version (usually by only exporting the wrapped component).
import React from 'react';
import { withRouter } from 'react-router';
class MyComponent extends React.Component {
render() {
return (
<button onClick={() => this.props.history.push('/newpage')}>
Click me
</button>
);
}
}
export default withRouter(MyComponent);

React - Component not updating after props change

I have a very simple react component to show FontAwesome Icons. It looks like this:
import React from 'react';
export default class FasIcon extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log("rendering FasIcon ");
const spanClass = ["icon is-", this.props.size, " is-", this.props.side].join("");
let component = "";
if (this.props.icon) {
component = (
<span className={spanClass}>
<i className={["fas fa-", this.props.icon].join("")} />
</span>
);
}
return component;
}
}
I am using this on an email field that does email validation:
Initially the prop icon is empty. This works.
When starting to check if the address is used (an async server call) I update the icon to a value spinner and the icon displays correctly.
When the check is completed i plan to change it to either times or check. This is correctly reflected in the props in the React Dev Tools, but it is not reflected in the actual site.
Update
The issue was that I was importing the svg library which substituted the icon element for an svg. Once the SVG was placed, react was not able to substitute the icon in the DOM.
I've used the fortawesome prerelease plugins for react and it now works.
The render method was correctly called at all times.
To fix this you have to add a key prop to the i tag like this:
<i key={this.props.icon} className={["fas fa-", this.props.icon].join("")} />

How to pass Markdown file as this.props in React?

I'm building a site in React using Redux, and my goal is to have a /pages folder full of markdown files that'll represent a pages content.
I have a React Container (smart) and a React Component (dumb) that'll be used to render the content. My thinking is that I'll import the markdown files to the parent container and pass them down to the child component to render them in the browser. I know I'll need to use something like markdown-it to convert the MD to HTML and maybe I'll need to use that in the child component.
My questions are:
1) How do I pass in markdown files from parent to child using this.props?
2) Am I on the right track? Is this the right way to go about it?
Here are my components:
Page Parent Container
import React from 'react'
import SamplePage from './../components/SamplePage'
export default class Page extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<section>
<SamplePage />
</section>
)
}
}
SamplePage Child Component
import React from 'react'
import { Link } from 'react-router'
export default class SamplePage extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div className="page-container">
<Link to="/" className="previous-link">Go Back Home</Link>
// I want to render the MD here using {this.props.markdown}
</div>
)
}
}
A few things:
1) I recommend using a Markdown to JSX parser to keep your templating safe (otherwise you'd likely have to use dangerouslySetInnerHtml)
2) I'd run this parser during build time, so everything is already ready to go. If you're using webpack or browserify, you can add a custom loader/transformer function to look for *.md files being required and run it through the parser.
3) The parsed markdown is then simple JSX and can be required & dropped into your existing component as you've done above.

Resources