Jak wyswietlać svg jako "zmienne" albo jak zrobić komponent renderujacy ikonę na podstawie propsa.

0

Temat jest może wydumany, albo przeoczyłam coś bardzo oczywistego.
Mam kilkanaście plików .svg.

W pliku index.ts zebrane są i eksportowane w sposób następujący:

import { ReactComponent as Person } from "icons/person.svg";
import { ReactComponent as Settings } from "icons/settings.svg";

const Icons = { Home, Edit, Chat, Cards, Person, Settings };

export default Icons;

Takie Icons można sobie spokojnie zaimportować. I gra muzyka, jeżeli zachcę potem renderować poszczególne ikonki to bez problemu <Icons.Edit /> itp się pięknie wyświetlają.

Tyle, że schody zaczynają się kiedy chcę wyświetlić Icons z parametrem. Nie Icons.Edit, tylko Icons[Edit] albo Icons["Edit"] . Jest mi to potrzebne tylko i wyłącznie po to, żeby na następnym etapie w miejsce obecnej zawartości nawiasu kwadratowego wstawić zmienną.

Probowałam innego podejścia - w sekwencji case/switch próbowałam przypisać do zmiennej Node wartości o tak

case "home":
            Node = Icons.Home;
            break;
case "chat":
            Node = Icons.Chat;
            break;

Tyle, że nie znalazłem sposobu, żeby to potem wyrenderować w komponencie. <Node /> rzuca błąd, {Node} tak samo, {()=>Node} natomiast nic nie wyświetla.

Oczywiście pewnie zaskoczyłaby sekwencja


{ icon === 'home' && <Icon.Home />
{ icon === 'person' && <Icon.Person />

ale pod każdym względem jest to koszmar (nb mam obejście, ale z użyciem img a nie chcę mieszać)

Czy to jest do zrobienia?

1

Możesz zamienić pierwszą literę na dużą (np. 'home' na 'Home') a potem się odwoływać po kluczu. Coś takiego mniej więcej:

// gdzieś na początku komponentu:
const iconName = icon.at(0).toUpperCase() + icon.slice(1);
const Icon = Object.hasOwn(Icons, iconName)? Icons[iconName] : null;

// a potem w JSX
{ Icon && <Icon /> }

tak jak tutaj zrobiłem w tym sandboksie: https://codesandbox.io/s/awesome-dream-1ebc0u

0
Doctanna napisał(a):

Tyle, że nie znalazłem sposobu, żeby to potem wyrenderować w komponencie. <Node /> rzuca błąd, {Node} tak samo, {()=>Node} natomiast nic nie wyświetla.

Jaki błąd, konkretnie?

0
Doctanna napisał(a):
import { ReactComponent as Person } from "icons/person.svg";
import { ReactComponent as Settings } from "icons/settings.svg";

const Icons = { Home, Edit, Chat, Cards, Person, Settings };

export default Icons;

Takie Icons można sobie spokojnie zaimportować. I gra muzyka, jeżeli zachcę potem renderować poszczególne ikonki to bez problemu <Icons.Edit /> itp się pięknie wyświetlają.

Tyle, że schody zaczynają się kiedy chcę wyświetlić Icons z parametrem. Nie Icons.Edit, tylko Icons[Edit] albo Icons["Edit"] . Jest mi to potrzebne tylko i wyłącznie po to, żeby na następnym etapie w miejsce obecnej zawartości nawiasu kwadratowego wstawić zmienną.

Możesz spróbować stworzyć komponent przez funkcję createElement

https://reactjs.org/docs/react-api.html#createelement

import React, { createElement, FC } from "react";
import { ReactComponent as Person } from "icons/person.svg";
import { ReactComponent as Settings } from "icons/settings.svg";

interface IconProps {
  type: keyof typeof Icons;
  width?: number;
  height?: number;
  id?: string;
}

const Icons = { Home, Edit, Chat, Cards, Person, Settings };

const Icon: FC<IconProps> = ({ type, ...props }) => createElement(Icons[type], props, null);

export default Icons;

I używasz tego w formie komponentu

<Icon type="Home" />

<Icon 
  type="Chat"
  id="chat-svg"
  width={32}
  height={27}
/>

1 użytkowników online, w tym zalogowanych: 0, gości: 1