FlowingDev

SVG di React: Dari gambar statis jadi komponen dinamis

Pelajari cara mengubah gambar SVG statis menjadi komponen React (JSX/TSX) yang dinamis dan bisa dipakai ulang, bisa terima props, ganti warna, dan banyak lagi.

Coba tool-nya: SVG ke JSX

Dalam satu kalimat

SVG ke JSX mengubah kode gambar vektor lo menjadi komponen React yang bisa dipakai ulang, membuatnya dinamis dan bisa dikontrol dengan props, bukan lagi cuma file statis.

Masalah yang dipecahkannya

Di zaman baheula-nya web (kayak, lima tahun lalu), kalau lo mau nampilin ikon SVG, mungkin lo bakal lempar aja ke tag <img>: <img src="/icons/user.svg" alt="User profile" />. Tugas kelar. Kirim.

Tapi pendekatan simpel ini sebenernya jebakan. SVG lo sekarang jadi kotak hitam. Mau ganti warnanya pas kursor user melayang di atas tombol yang membungkusnya? Sial banget, nggak bisa. Browser nganggepnya sama kayak file gambar lain (JPG, PNG), dan lo nggak bisa dengan gampang ngasih style ke isinya pake CSS. Mau menganimasikan salah satu path di dalam ikon? Nggak bisa. Mau ganti warnanya buat tema dark mode? Lo bakal harus bikin file baru (user-white.svg) dan nulis logika buat gonta-ganti src. Jadinya berantakan cepet banget.

"Aha!" kata developer yang cerdik. "SVG kan cuma markup XML! Gue salin aja kodenya dari file .svg terus tempel langsung di return statement komponen gue!"

// MyComponent.js
const MyComponent = () => (
  <div>
    <p>My Profile</p>
    {/* Gue baru aja paste ini dari file .svg! */}
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path d="M12 12C14.21 12 16 10.21 16 8C16 5.79 14.21 4 12 4C9.79 4 8 5.79 8 8C8 10.21 9.79 12 12 12ZM12 14C9.33 14 4 15.34 4 18V20H20V18C20 15.34 14.67 14 12 14Z" fill="black"/>
    </svg>
  </div>
);

Ini namanya "inlining", dan ini kemajuan pesat. Sekarang SVG-nya jadi bagian dari DOM, dan lo bisa kasih style pake CSS. Tapi lo nuker satu masalah dengan masalah lain.

  1. Bikin Kaku: Gumpalan kode SVG itu bikin komponen lo lebih susah dibaca. Bayangin kalo ada lima ikon di dalamnya.
  2. Nggak Bisa Dipakai Ulang: Butuh ikon user itu di tempat lain? Siap-siap aja salin-tempel seluruh gumpalan kode itu lagi dan lagi.
  3. Bukan JSX: React punya dialek HTML-nya sendiri. Atribut kayak stroke-width harus diubah jadi camelCase strokeWidth, dan class jadi className. Lupa mengonversinya bisa bikin error diam-diam atau warning yang berisik di console.

Solusi sebenarnya adalah memperlakukan ikon bukan sebagai aset statis, tapi sebagai warga kelas satu di ekosistem komponen lo. Lo pengennya nulis <UserIcon color="blue" size={24} />. Inilah masalah yang dipecahkan oleh konversi SVG ke JSX: dia mengotomatiskan boilerplate untuk mengubah markup SVG mentah menjadi komponen React yang bersih, bisa dipakai ulang, dan dikendalikan oleh props.

Cara kerjanya di balik layar

Mengubah gumpalan teks jadi komponen React yang keren mungkin kelihatan kayak sihir, tapi sebenarnya ini proses langkah demi langkah yang bisa ditebak. Yuk, kita intip di balik tirainya.

Langkah 1: Parsing Markup SVG

Pertama, tool-nya harus ngerti SVG itu apa. Karena SVG adalah dialek dari XML, dia bisa di-parse menjadi struktur pohon node, sama seperti dokumen HTML. Setiap elemen (<svg>, <path>, <g>, dll.) menjadi sebuah node, dan atributnya (width, fill, d, dll.) menjadi properti dari node itu.

Jadi, ini:

<svg width="24" height="24">
  <path fill-rule="evenodd" d="..." />
</svg>

Dipahami oleh parser sebagai pohon:

  • svg node dengan atribut width="24" dan height="24"
    • path node dengan atribut fill-rule="evenodd" dan d="..."

Langkah 2: Mengubah Atribut jadi JSX

Di sinilah terjemahan spesifik-React terjadi. Parser akan menelusuri pohon node dan mengonversi atributnya agar sesuai dengan JSX.

  • Camel-casing: Atribut apa pun dengan tanda hubung (kebab-case) diubah menjadi camelCase. fill-rule menjadi fillRule, stroke-width menjadi strokeWidth.
  • Pemetaan keyword: Keyword JavaScript yang direservasi akan ditukar. Yang paling umum adalah class, yang menjadi className.
  • Atribut style: Atribut style="fill:red; stroke:blue" diubah menjadi objek JavaScript: style={{ fill: 'red', stroke: 'blue' }}.

Jadi, <path fill-rule="evenodd" class="icon-path"> berubah menjadi padanannya di JSX: <path fillRule="evenodd" className="icon-path">.

Langkah 3: Membungkusnya jadi Komponen

Setelah pohon SVG-nya sekarang lancar berbahasa JSX, langkah berikutnya adalah membungkusnya dalam struktur komponen fungsional React standar. Versi paling sederhananya seperti ini:

import React from 'react';

const MyIcon = () => {
  return (
    <svg width="24" height="24" viewBox="0 0 24 24">
      {/* ... semua path dan elemen lain yang sudah jadi JSX ... */}
    </svg>
  );
};

export default MyIcon;

Ini aja udah ngasih lo komponen <MyIcon /> yang bisa dipakai ulang, yang mana udah kemenangan besar. Tapi kekuatan sebenarnya datang dari membuatnya dinamis.

Langkah 4: Menambahkan Props dan currentColor

Inilah saus rahasianya. Converter yang bagus nggak cuma nge-hardcode atribut asli SVG. Dia membuatnya bisa dikonfigurasi.

  • Menyebarkan Props: Komponen dimodifikasi untuk menerima props dan menyebarkannya ke elemen <svg> root. Ini sering dilakukan pake sintaks ...rest. Sekarang lo bisa ngoper atribut SVG standar apa pun (kayak width, height, className, atau aria-label) langsung ke komponen lo.

  • Trik currentColor: Ini jurus jitu yang mengubah permainan buat styling. Converter akan menemukan atribut fill dan stroke yang di-hardcode yang mendefinisikan warna ikon (misal, fill="#000000") dan menggantinya dengan keyword CSS spesial currentColor.

currentColor memberi tahu browser, "Apa pun properti color CSS di elemen ini, pake itu buat fill/stroke." Artinya, ikon lo sekarang berperilaku seperti teks. Kalo lo bungkus ikon lo di dalam div dan set color: blue, ikonnya jadi biru.

// Komponen yang sudah di-upgrade
const MyIcon = ({ color = 'currentColor', size = 24, ...rest }) => {
  return (
    <svg 
      width={size} 
      height={size} 
      fill={color} // atau diterapkan langsung ke path
      {...rest}
    >
      <path d="..." fill="currentColor" />
    </svg>
  );
};

Langkah 5: Meneruskan Ref (Forwarding Refs)

Kadang-kadang, lo butuh pegangan langsung ke elemen DOM <svg> yang sebenarnya dari komponen induk, mungkin buat ngukur posisinya atau make itu dengan library pihak ketiga. Komponen fungsional biasa menyembunyikan struktur DOM internalnya. Solusinya adalah React.forwardRef.

Converter yang canggih akan membungkus komponen dalam React.forwardRef, yang membuat sebuah saluran untuk meneruskan ref dari induk langsung ke tag <svg> di bawahnya.

Komponen akhir yang kualitas produksi seringnya kelihatan seperti ini (contoh TypeScript):

import * as React from 'react';

type Props = React.SVGProps<SVGSVGElement>;

const MyIcon = React.forwardRef<SVGSVGElement, Props>((props, ref) => (
  <svg ref={ref} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props}>
    <path d="..." fill="currentColor" />
  </svg>
));

MyIcon.displayName = 'MyIcon'; // Bagus untuk debugging
export default MyIcon;

Kisah dari dunia nyata

Mimpi Buruk Theming

Sebuah tim frontend lagi ngebangun aplikasi web keren yang punya mode terang dan gelap. Mereka pake sekitar 50 ikon, semuanya diimplementasikan sebagai <img src="/icons/whatever.svg">. Ikonnya warna hitam. Waktu mereka rilis mode gelap, kepanikan melanda: semua 50 ikon hitam lenyap di latar belakang gelap yang baru. "Perbaikan" panik pertama mereka adalah mengekspor set kedua ikon putih (whatever-dark.svg) dan nulis logika kondisional yang ribet (isDarkMode ? 'whatever-dark.svg' : 'whatever.svg') di mana-mana. Itu bencana dari segi maintenance.

Kemudian, seorang developer memperkenalkan alur kerja SVG-ke-JSX. Mereka menjalankan skrip yang mengubah semua 50 SVG menjadi komponen React, yang krusialnya mengganti semua atribut fill="black" dengan fill="currentColor". Mereka mengganti semua tag <img> dengan komponen ikon baru mereka, seperti <WhateverIcon />. Seketika, ikon-ikon itu mewarisi warnanya dari warna teks induk, yang sudah diatur oleh CSS tema. Mode terang: teks hitam, ikon hitam. Mode gelap: teks putih, ikon putih. Langsung beres gitu aja.

Pelajaran: Meng-inline SVG sebagai komponen membuat mereka terintegrasi mulus dengan sistem desain dan styling aplikasi lo yang sudah ada, menyelamatkan lo dari neraka manajemen aset.

Centang yang Dianimasikan

Seorang manajer produk pengen animasi yang "delightful": ketika user selesai ngisi form, sebuah tanda centang harus secara dinamis kegambar di layar. Pake GIF animasi nggak mungkin—kelihatan pecah dan filenya gede. Developernya coba cari library, tapi nggak ada yang pas banget sama desain centang kustomnya.

Mengambil alih masalahnya sendiri, dia mengambil SVG centang statis dari desainer dan mengubahnya jadi komponen JSX. Ini memberinya akses langsung ke elemen <path> dari centang itu di dalam kode React-nya. Dengan transisi CSS sederhana pada properti stroke-dasharray dan stroke-dashoffset dari path itu, dia berhasil menciptakan efek "menggambar" persis seperti yang dia inginkan. Animasinya super mulus, bisa diskalakan tanpa batas, dan cuma butuh kurang dari 1KB kode.

Pelajaran: Mengubah SVG menjadi komponen membuka kontrol granular atas bagian-bagian individualnya, memungkinkan animasi kompleks yang digerakkan oleh CSS atau JavaScript.

Kesalahan dan jebakan umum

  • Melupakan aksesibilitas. Ikon yang menyampaikan makna (seperti X untuk "tutup") bukan cuma hiasan. Kalau lo hapus tag <title> selama konversi, screen reader mungkin akan mengumumkannya sebagai "grup" atau mengabaikannya. Selalu pastikan komponen akhir lo punya prop aria-label yang sesuai atau nama yang dapat diakses via elemen <title> di dalam SVG. Komponen yang baik akan di-render sebagai <svg role="img" ...>.
  • Menggembungkan bundle. Meng-inline SVG berarti kodenya sekarang jadi bagian dari bundle JavaScript lo. Untuk beberapa lusin ikon UI kecil, ini tetap lebih untung (lebih sedikit request HTTP). Tapi kalo lo coba meng-inline ilustrasi besar yang kompleks dengan ribuan path, lo bisa secara serius menggembungkan ukuran bundle lo dan memperlambat pemuatan halaman awal. Untuk ilustrasi besar yang statis, <img> masih pilihan yang sangat valid.
  • Mengabaikan optimasi dulu. SVG yang diekspor dari tool desain seperti Figma atau Adobe Illustrator terkenal berantakan. Mereka berisi metadata editor, komentar, layer tersembunyi, dan nilai desimal yang terlalu presisi. Memasukkan ini langsung ke komponen JSX menghasilkan kode yang gendut dan sulit dibaca. Selalu jalankan SVG lo melalui optimizer seperti SVGO sebelum mengonversinya. Ini seringkali bisa mengurangi ukuran kode hingga 50% atau lebih.
  • Pengeditan manual jadi masalah sinkronisasi. Lo ubah icon.svg jadi Icon.jsx. Terus lo utak-atik Icon.jsx secara manual buat nambahin fitur. Seminggu kemudian, desainer ngasih lo icon.svg yang diperbarui. Sekarang lo punya pilihan: jalankan lagi konversinya dan kehilangan editan manual lo, atau coba secara manual menambal desain baru ke JSX yang udah lo edit. Sumber kebenaran (source of truth) haruslah file .svg; konversi ke JSX haruslah skrip yang bisa diulang dan otomatis.

Kenapa ini wajib kamu lirik

Lo harus mikirin buat ngubah SVG ke JSX setiap kali lo ngebangun aplikasi web berbasis komponen (React, Preact, dll.) dan ikon lo harus lebih dari sekadar gambar statis.

Ini alat yang pas untuk kerjaan kalau:

  • Lo butuh ikon buat ganti warna, ukuran, atau lebar stroke berdasarkan state atau props.
  • Lo lagi ngebangun sistem desain atau library komponen dan butuh cara yang skalabel dan konsisten buat ngelola ikon.
  • Lo mau menganimasikan bagian-bagian dari sebuah ikon.
  • Lo lagi ngoptimalin performa dan mau ngurangin jumlah request jaringan dengan meng-inline ikon-ikon penting.

Di pengembangan frontend modern, memperlakukan ikon lo sebagai komponen bukanlah sebuah hack—ini udah jadi standar untuk membangun antarmuka pengguna yang dinamis, mudah di-maintain, dan berperforma tinggi.

Pelajari lebih dalam

Teori beres. Saatnya praktik — 100% di browser kamu.

Coba tool-nya: SVG ke JSX