Reputation: 4331
I have some Svg files which i want to load as react components in remix run app. for example in create-react-app your could do something like this
import { ReactComponent as Logo } from './logo.svg';
function App() {
return (
<div>
{/* Logo is an actual React component */}
<Logo />
</div>
);
}
is there any similar way in remix-run do achieve the same ?
Upvotes: 9
Views: 9952
Reputation: 166
Remix's official documentation suggests using SVGR to transform your SVGs to React Components. After that it's pretty straight-forward, just import those components and use them the same way we use any React components.
I find this solution safe and clean since there will be no typescript or import problems. Also it's easy and officially recommended.
Upvotes: 2
Reputation: 6758
You can just import them as described in the documentation:
import type { LinksFunction } from "@remix-run/node"; // or "@remix-run/cloudflare"
import styles from "./styles/app.css";
import banner from "./images/banner.jpg";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
};
export default function Page() {
return (
<div>
<h1>Some Page</h1>
<img src={banner} />
</div>
);
}
Upvotes: -2
Reputation: 81
I created a workflow to convert the icons to react components in development using svgr
and npm-watch
. For good measure you will probably want to run the icons
script before building for production too.
Install dependencies:
npm install -D @svgr/cli @svgr/plugin-svgo @svgr/plugin-jsx @svgr/plugin-prettier npm-watch npm-run-all
Update package.json
scripts:
{
//...
"scripts": {
//...
// task to convert icons to components
"icons": "npx @svgr/cli --out-dir app/icons -- ./icons",
// watch task
"icons:watch": "npm-watch icons",
// compile once and start watching for changes
"dev:svg": "run-s icons icons:watch",
// remix dev
"dev:remix": "remix dev",
// run all dev: scripts including `dev:svg` (depending on the remix template you might need to replace the default `dev` script)
"dev": "run-p dev:*"
},
// npm-watch configuration
"watch": {
"icons": {
"patterns": [
"icons"
],
"extensions": "svg",
"quiet": false
}
},
//...
}
The svg
icon files are located in the project root in icons/
and the react components are generated in the app/icons/
folder.
svgr.config.js
(optional)
module.exports = {
plugins: ["@svgr/plugin-svgo", "@svgr/plugin-jsx", "@svgr/plugin-prettier"],
typescript: true, // optional
};
svgo.config.js
module.exports = {
plugins: [
{
name: "preset-default",
params: {
overrides: {
removeViewBox: false,
},
},
},
],
};
Upvotes: 8
Reputation: 121
For me, it only worked by creating a component with the SVG tag and then importing it
const HomeLogo = () => {
return (
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
<g fill="none" fill-rule="evenodd">
<circle cx="24" cy="24" r="24" fill="#FFF"/>
<path fill="#0B0D17" d="M24 0c0 16-8 24-24 24 15.718.114 23.718 8.114 24 24 0-16 8-24 24-24-16 0-24-8-24-24z"/>
</g>
</svg>
</div>
)
}
export default HomeLogo
Upvotes: 0
Reputation: 2996
Unfortunately there is no way currently to import an SVG file in your component file directly like in create react app.
And maintainers do not allow currently manipulating the esbuild config to add features like that via plugins (cf. the discussion in this merge request).
If you don't need to style your SVG, you could simply put it in the public/
folder and include it with an img
element in your component.
Smaller JS bundles, faster page hydration, and immutable .svg's over the network that are only ever downloaded once. (cf. this message)
function App() {
return (
<div>
<img src="/logo.svg" alt="My logo" />
</div>
);
}
You could also create yourself a JSX component and put your SVG code inside it (with some manual conversion for prop names), or even put your SVG file in a folder, and use an external automatic conversion tool like SVGR to generate optimized JSX component from it with a simple CLI command.
In that case you have a component that you can import like any other component:
import Logo from './Logo.svg';
function App() {
return (
<div>
<Logo />
</div>
);
}
Upvotes: 9