ReactSVG like component in Solid

Hey, I recently was remaking my portfolio website in astro with some solid.js. I wanted to make an interactive carousel which basically displays some items. The problem is I need to dynamically get the SVG's (vite-plugin-solid-svg doesn't work in my case). I remember I used react-svg for that thing that exposed a ReactSVG component with a src prop. I would like to know if this is possible in solid, and if it is, has someone already done it?
2 Replies
Alex Lohr
Alex Lohr13mo ago
Why doesn't vite-plugin-solid-svg work for your case? You could combine it with await import(), no?
kalempster
kalempster13mo ago
I don't really know what you mean. Could you show an example? I was trying to replicate what I thought ReactSVG's component looks like but I only came up with this.
import { JSX, createEffect, createSignal } from "solid-js";

export const Svg = (props: { url: string } & JSX.HTMLAttributes<HTMLDivElement>) => {
const [content, setContent] = createSignal("");

createEffect(async () => {
setContent(await (await fetch(props.url)).text());
}, []);

return (
<div {...props}>
<div innerHTML={content()}></div>
</div>
);
};
import { JSX, createEffect, createSignal } from "solid-js";

export const Svg = (props: { url: string } & JSX.HTMLAttributes<HTMLDivElement>) => {
const [content, setContent] = createSignal("");

createEffect(async () => {
setContent(await (await fetch(props.url)).text());
}, []);

return (
<div {...props}>
<div innerHTML={content()}></div>
</div>
);
};
And vite-plugin-solid-svg doesn't work for me because it crashes in Astro. I have the component <Projects client:visible /> like this. Inside there's an imported svg as a component. I get an error message TypeError: Comp is not a function every time the component is initialized (I can give you the full stack trace if you want). Well, if anyone finds this post by searching svg here's what I came up with
import { createSignal, JSX } from "solid-js";

const svgCache: { [url: string]: string | null } = {};

async function fetchSVG(url: string) {
try {
const response = await fetch(url);
return await response.text();
} catch (error) {
return null;
}
}

export function Svg({ url, ...rest }: { url: string } & JSX.HTMLAttributes<HTMLDivElement>) {
let [cachedSVG, setCachedSVG] = createSignal<string | null>(null);

if (!svgCache[url]) {
(async () => {
const svgContent = await fetchSVG(url);
svgCache[url] = svgContent;
setCachedSVG(svgContent);
})();
}
//Overriding typescript because we know the item exists based on the if above
else setCachedSVG(svgCache[url]!);

return <div {...rest}>{cachedSVG() !== null ? <div innerHTML={cachedSVG()!} /> : <></>}</div>;
}
import { createSignal, JSX } from "solid-js";

const svgCache: { [url: string]: string | null } = {};

async function fetchSVG(url: string) {
try {
const response = await fetch(url);
return await response.text();
} catch (error) {
return null;
}
}

export function Svg({ url, ...rest }: { url: string } & JSX.HTMLAttributes<HTMLDivElement>) {
let [cachedSVG, setCachedSVG] = createSignal<string | null>(null);

if (!svgCache[url]) {
(async () => {
const svgContent = await fetchSVG(url);
svgCache[url] = svgContent;
setCachedSVG(svgContent);
})();
}
//Overriding typescript because we know the item exists based on the if above
else setCachedSVG(svgCache[url]!);

return <div {...rest}>{cachedSVG() !== null ? <div innerHTML={cachedSVG()!} /> : <></>}</div>;
}