Rescript React SVG Components

Looking for the best way to use svg images inside a Rescript React app using Create React App.

Just use JSX? (and wrap them into a component).

I was wondering if there was a way to pack them all away into a svg file rather than using JSX.

Is there an elegant way to do so?

Usually webpack is configured to import svgs as url strings, just like other image media.

So you’d basically do this:

// ReScript

@module external mySvg: string = "./img/my-nice.svg";

let make = () => {
  <img src=mySvg/>

Please note that using svgs within img tags makes it impossible to do fancy stuff, such as changing the fill color, which is often needed for e.g. button hover effects. You’d copy the svg code into a React component then.


Thanks @ryyppy - So there is no way to get these simply bound to a react component from the binding? This would be considered the most elegant way to implement svg files?

Thanks again!

That’s mostly a JS ecosystem question. I am sure there is a webpack loader out there that would do the necessary convertion for you, but I am not sure if you want to add this extra indirection. In case you find a solution that converts .svg files into React components, you’d follow the ReasonReact instructions on importing existing React components from JS.

Gotcha, that makes perfect sense. I guess I was assuming something on the rescript binding side that would import the svg as a module, but I understand that there are build steps from webpack / create react app that convert these files into components first that is out of the rescript scope.

I appreciate you help @ryyppy

I’ve used react-from-svg to automatically create ReasonML components from SVGs. Not sure if there is support for ReScript yet though.

Not sure if this is relevant anymore. Just revisiting some old reasonml code and converting to ReScript; I stumbled on the same issue and my old hacky solution. Looks like my “solution” still works if you use react-scripts (create-react-app) in combination with rescript. You can import SVGs as components like so

module Logo = {
  @module("../../assets/logo.svg") @react.component
  external make: (~role: string=?, ~className: string=?) => React.element = "ReactComponent"

You can add more props if you need them but that’s the basic gist. Maybe some ReScript Guru can simplify the process, this seems to work well enough for me.

I looked into making a helper function to isolate the boilerplate into a single location, but I don’t know how you would dynamically generate the module name (or even take that as a param for a “helper” function); please feel free to point me towards resources that might help.

1 Like

In our project we use a script that watch assets folder and generate Icons module with bindings like that. It applies restriction that set of properties is limited and shared by all icons.

Helo :slight_smile: Can you share with us the script you use in your project ? Thx :wink: