في جملة واحدة
يحول SVG to JSX كود صورتك الفيكتور إلى مكون React قابل لإعادة الاستخدام، مما يجعله ديناميكيًا ويمكن التحكم فيه عن طريق الـ props بدلاً من كونه مجرد ملف ثابت.
المشكلة التي يحلها
في الأيام الخوالي للويب (يعني، قبل خمس سنوات مثلاً)، لو أردت عرض أيقونة SVG، فغالباً كنت سترميها في وسم <img>: <img src="/icons/user.svg" alt="User profile" />. خلصت الشغلة. اطلق الموقع.
لكن هذه الطريقة البسيطة هي فخ. صورتك الـ SVG أصبحت الآن صندوقًا أسود. هل تريد تغيير لونها عندما يمرر المستخدم الفأرة فوق الزر الذي يحتويها؟ حظ أوفر. المتصفح يعاملها كأي ملف صورة آخر (JPG أو PNG)، ولا يمكنك بسهولة تعديل أجزائها الداخلية بالـ CSS. هل تريد تحريك أحد المسارات داخل الأيقونة؟ لا يمكن. هل تريد تغيير لونها ليتناسب مع الثيم الداكن؟ ستجد نفسك مضطراً لإنشاء ملف جديد بالكامل (user-white.svg) وكتابة منطق برمجي لتبديل الـ src. الأمور تتعقد بسرعة.
"أها!" يقول المطور الذكي. "الـ SVG هو مجرد كود XML! سأقوم بنسخ الكود من ملف .svg ولصقه مباشرة في جملة الـ return في المكون الخاص بي!"
// MyComponent.js
const MyComponent = () => (
<div>
<p>My Profile</p>
{/* لقد لصقت هذا للتو من ملف .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>
);
هذا يسمى "التضمين" (inlining)، وهو خطوة عملاقة للأمام. الآن الـ SVG أصبح جزءًا من الـ DOM، ويمكنك بالفعل تنسيقه باستخدام CSS. لكنك استبدلت مشكلة بأخرى.
- غير عملي وضخم: كتلة كود الـ SVG هذه تجعل مكونك أصعب في القراءة. تخيل لو كان لديك خمس أيقونات بداخله.
- غير قابل لإعادة الاستخدام: هل تحتاج أيقونة المستخدم هذه في مكان آخر؟ استعد لنسخ ولصق تلك الكتلة بأكملها مرة أخرى في كل مكان.
- ليس بصيغة JSX: لغة React لها "لهجتها" الخاصة من HTML. الخصائص مثل
stroke-widthيجب تحويلها إلىcamelCaseلتصبحstrokeWidth، وclassتصبحclassName. نسيان تحويل هذه الخصائص يمكن أن يؤدي إلى فشل صامت أو تحذيرات مزعجة في الـ console.
الحل الحقيقي هو التعامل مع الأيقونات ليس كأصول ثابتة، بل كمواطنين من الدرجة الأولى في نظام المكونات الخاص بك. أنت تريد شيئًا مثل <UserIcon color="blue" size={24} />. هذه هي المشكلة التي يحلها تحويل SVG إلى JSX: فهو يؤتمت العملية الروتينية لتحويل كود SVG الخام إلى مكون React نظيف، قابل لإعادة الاستخدام، ومُدار بواسطة الـ props.
كيف يعمل خلف الكواليس
قد يبدو تحويل كتلة من النص إلى مكون React أنيق وكأنه سحر، ولكنه في الواقع عملية متوقعة خطوة بخطوة. دعنا نزيل الستار عن الكواليس.
الخطوة 1: تحليل كود SVG
أولاً، يجب على الأداة أن تفهم الـ SVG. بما أن SVG هو لهجة من XML، يمكن تحليله إلى بنية شجرية من العُقد (nodes)، تمامًا مثل مستند HTML. كل عنصر (<svg>، <path>، <g>، إلخ) يصبح عقدة، وخصائصه (width، fill، d، إلخ) تصبح خصائص لتلك العقدة.
إذًا، هذا الكود:
<svg width="24" height="24">
<path fill-rule="evenodd" d="..." />
</svg>
يفهمه المحلل كشجرة:
- عقدة
svgبالخصائصwidth="24"وheight="24"- عقدة
pathبالخصائصfill-rule="evenodd"وd="..."
- عقدة
الخطوة 2: تحويل الخصائص لتتوافق مع JSX
هنا تحدث الترجمة الخاصة بـ React. يتجول المحلل في شجرة العُقد ويحول الخصائص لتكون متوافقة مع JSX.
- التحويل إلى camelCase: أي خاصية تحتوي على شرطة (kebab-case) يتم تحويلها إلى camelCase.
fill-ruleتصبحfillRule، وstroke-widthتصبحstrokeWidth. - مطابقة الكلمات المفتاحية: يتم استبدال الكلمات المحجوزة في JavaScript. وأشهرها
class، التي تصبحclassName. - خصائص النمط: خاصية مثل
style="fill:red; stroke:blue"يتم تحويلها إلى كائن JavaScript:style={{ fill: 'red', stroke: 'blue' }}.
إذًا، <path fill-rule="evenodd" class="icon-path"> تتحول إلى ما يعادلها في JSX: <path fillRule="evenodd" className="icon-path">.
الخطوة 3: تغليف الكود في مكون
مع تحول شجرة SVG الآن لتتحدث JSX بطلاقة، الخطوة التالية هي تغليفها في بنية مكون React وظيفي قياسي. أبسط نسخة تبدو هكذا:
import React from 'react';
const MyIcon = () => {
return (
<svg width="24" height="24" viewBox="0 0 24 24">
{/* ... كل المسارات والعناصر الأخرى المحولة إلى JSX ... */}
</svg>
);
};
export default MyIcon;
هذا يمنحك بالفعل مكون <MyIcon /> قابل لإعادة الاستخدام، وهو مكسب كبير. لكن القوة الحقيقية تأتي من جعله ديناميكيًا.
الخطوة 4: إضافة Props و currentColor
هذه هي الخلطة السرية. المحول الجيد لا يقوم فقط بتثبيت قيم خصائص SVG الأصلية. بل يجعلها قابلة للتعديل.
نشر الـ Props: يتم تعديل المكون ليقبل props وينشرها على عنصر
<svg>الجذري. غالبًا ما يتم ذلك باستخدام صيغة...rest. الآن يمكنك تمرير أي خاصية SVG قياسية (مثلwidth،height،className، أوaria-label) مباشرة إلى مكونك.خدعة
currentColor: هذه تغير قواعد اللعبة في التنسيق. سيجد المحول خصائصfillوstrokeذات القيم الثابتة التي تحدد لون الأيقونة (مثلاًfill="#000000") ويستبدلها بالكلمة المفتاحية الخاصة في CSScurrentColor.
currentColor تخبر المتصفح، "مهما كانت قيمة خاصية CSS color على هذا العنصر، استخدمها للتعبئة/الحدود." هذا يعني أن أيقونتك تتصرف الآن مثل النص. إذا وضعت أيقونتك في div وضبطت color: blue، ستتحول الأيقونة إلى اللون الأزرق.
// المكون المطور
const MyIcon = ({ color = 'currentColor', size = 24, ...rest }) => {
return (
<svg
width={size}
height={size}
fill={color} // أو يتم تطبيقها مباشرة على المسارات
{...rest}
>
<path d="..." fill="currentColor" />
</svg>
);
};
الخطوة 5: تمرير الـ Refs
أحيانًا، تحتاج إلى الحصول على وصول مباشر لعنصر <svg> الحقيقي في الـ DOM من مكون أب، ربما لقياس موضعه أو لاستخدامه مع مكتبة خارجية. المكون الوظيفي العادي يخفي بنيته الداخلية في الـ DOM. الحل هو React.forwardRef.
سيقوم المحول المتطور بتغليف المكون في React.forwardRef، مما ينشئ قناة لتمرير ref من المكون الأب مباشرة إلى وسم <svg> الأساسي.
المكون النهائي الجاهز للإنتاج غالبًا ما يبدو كالتالي (مثال بـ 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'; // مفيد في تصحيح الأخطاء
export default MyIcon;
قصص من الواقع
كابوس الثيمات
كان فريق الواجهة الأمامية يبني تطبيق ويب جميلًا يتميز بوضع فاتح وداكن. استخدموا حوالي 50 أيقونة، كلها تم تنفيذها باستخدام <img src="/icons/whatever.svg">. كانت الأيقونات سوداء. عندما أطلقوا الوضع الداكن، دب الرعب: اختفت جميع الأيقونات السوداء الخمسين على الخلفية الداكنة الجديدة. كان أول "حل" مذعور لهم هو تصدير مجموعة ثانية من الأيقونات البيضاء (whatever-dark.svg) وكتابة منطق شرطي معقد ومقرف (isDarkMode ? 'whatever-dark.svg' : 'whatever.svg') في كل مكان. كانت كارثة من ناحية الصيانة.
ثم، قام أحد المطورين بتقديم سير عمل لتحويل SVG إلى JSX. قاموا بتشغيل سكربت حول جميع الـ 50 أيقونة SVG إلى مكونات React، والأهم من ذلك، استبدلوا جميع خصائص fill="black" بـ fill="currentColor". استبدلوا جميع وسوم <img> بمكونات الأيقونات الجديدة، مثل <WhateverIcon />. على الفور، ورثت الأيقونات لونها من لون النص الأصلي، والذي كان يتم التعامل معه بالفعل بواسطة CSS الخاص بالثيم. الوضع الفاتح: نص أسود، أيقونات سوداء. الوضع الداكن: نص أبيض، أيقونات بيضاء. ببساطة، اشتغلت.
الدرس: تضمين الـ SVGs كمكونات يسمح لها بالاندماج بسلاسة مع نظام التصميم والتنسيق الحالي لتطبيقك، مما ينقذك من جحيم إدارة الأصول.
علامة الصح المتحركة
أراد مدير منتج أنيميشن "مبهج": عندما يكمل المستخدم نموذجًا، يجب أن ترسم علامة صح نفسها ديناميكيًا على الشاشة. استخدام صورة GIF متحركة كان خيارًا مستبعدًا - بدت منقطة (pixelated) وكان حجم ملفها كبيرًا. حاول المطور العثور على مكتبة برمجية، لكن لم يناسب أي شيء تصميم علامة الصح المخصص.
أخذت زمام المبادرة بنفسها، وأخذت SVG علامة الصح الثابتة من المصمم وحولتها إلى مكون JSX. هذا أعطاها وصولًا مباشرًا إلى عنصر <path> لعلامة الصح داخل كود React الخاص بها. باستخدام انتقال CSS بسيط على خصائص stroke-dasharray و stroke-dashoffset لذلك المسار، تمكنت من إنشاء تأثير "الرسم" الذي أرادته بالضبط. كان الأنيميشن سلسًا كالزبدة، قابلًا للتكبير بلا حدود، واستغرق أقل من 1 كيلوبايت من الكود.
الدرس: تحويل SVG إلى مكون يفتح الباب للتحكم الدقيق في أجزائه الفردية، مما يجعل الرسوم المتحركة المعقدة المعتمدة على CSS أو JavaScript ممكنة.
أخطاء وفخاخ شائعة
- نسيان إمكانية الوصول (accessibility). الأيقونة التي تنقل معنى (مثل علامة "X" للإغلاق) ليست مجرد زخرفة. إذا قمت بإزالة وسم
<title>أثناء التحويل، فقد يعلنها قارئ الشاشة كـ "مجموعة" أو يتجاهلها ببساطة. تأكد دائمًا من أن مكونك النهائي يحتوي علىaria-labelمناسب أو اسم يمكن الوصول إليه عبر عنصر<title>داخل الـ SVG. المكون الجيد سيتم عرضه كـ<svg role="img" ...>. - تضخيم الـ bundle. تضمين الـ SVGs يعني أن كودها أصبح الآن جزءًا من حزمة JavaScript (bundle) الخاصة بك. بالنسبة لبضع عشرات من أيقونات واجهة المستخدم الصغيرة، يعد هذا مكسبًا صافيًا (طلبات HTTP أقل). ولكن إذا حاولت تضمين رسم توضيحي ضخم ومعقد بآلاف المسارات، يمكنك أن تضخم حجم الـ bundle بشكل خطير وتبطئ التحميل الأولي للصفحة. بالنسبة للرسوم التوضيحية الكبيرة والثابتة، لا يزال
<img>خيارًا صالحًا تمامًا. - تجاهل التحسين أولاً. الـ SVGs المصدرة من أدوات التصميم مثل Figma أو Adobe Illustrator تكون فوضوية بشكل سيء السمعة. فهي تحتوي على بيانات وصفية للمحرر، وتعليقات، وطبقات مخفية، وقيم عشرية مفرطة الدقة. حشر هذا مباشرة في مكون JSX ينتج عنه كود متضخم وصعب القراءة. قم دائمًا بتمرير الـ SVGs الخاصة بك عبر مُحسِّن مثل SVGO قبل تحويلها. هذا يمكن أن يقلل من حجم الكود بنسبة 50% أو أكثر في كثير من الأحيان.
- التعديل اليدوي يسبب مشكلة في المزامنة. قمت بتحويل
icon.svgإلىIcon.jsx. ثم قمت بتعديلIcon.jsxيدويًا لإضافة ميزة. بعد أسبوع، يعطيك المصممicon.svgمحدثًا. الآن لديك خيار: إما إعادة تشغيل التحويل وفقدان تعديلاتك اليدوية، أو محاولة دمج التصميم الجديد يدويًا في JSX المعدل. يجب أن يكون مصدر الحقيقة (source of truth) هو ملف.svg؛ يجب أن يكون التحويل إلى JSX سكربتًا آليًا وقابلًا للتكرار.
لماذا يجب أن تكون على رادارك
يجب أن تفكر في تحويل الـ SVGs إلى JSX كلما كنت تبني تطبيق ويب قائم على المكونات (React, Preact, etc.) وتحتاج أيقوناتك أن تكون أكثر من مجرد صور ثابتة.
إنها الأداة المناسبة للمهمة عندما:
- تحتاج إلى تغيير لون الأيقونات أو حجمها أو عرض حدودها بناءً على الحالة أو الـ props.
- تبني نظام تصميم أو مكتبة مكونات وتحتاج إلى طريقة قابلة للتطوير ومتسقة لإدارة الأيقونات.
- تريد تحريك أجزاء من أيقونة.
- تقوم بتحسين الأداء وتريد تقليل عدد طلبات الشبكة عن طريق تضمين الأيقونات الهامة.
في تطوير الواجهات الأمامية الحديث، لا يعد التعامل مع أيقوناتك كمكونات حيلة - بل هو المعيار لبناء واجهات مستخدم ديناميكية وقابلة للصيانة وعالية الأداء.
تعمق أكثر
- MDN: SVG: Scalable Vector Graphics — الدليل النهائي لكيفية عمل SVG في المتصفح.
- W3C: Scalable Vector Graphics (SVG) 2 Specification — المواصفات الرسمية. كثيفة، لكنها المصدر النهائي للحقيقة.
- React Docs: Forwarding Refs — الوثائق الرسمية حول هذه التقنية الأساسية لتكوين المكونات.
- MDN:
currentColor— قيمة CSS البسيطة والقوية التي تجعل تطبيق الثيمات على SVG أمرًا سهلاً. - CSS-Tricks: Styling SVG — مجموعة رائعة من المقالات حول الطرق العديدة التي يمكنك من خلالها التعامل مع SVGs وتنسيقها باستخدام CSS.
- SVGO (SVG Optimizer) — الأداة القياسية في الصناعة لتنظيف ملفات SVG. فهم ما تفعله سيجعلك تقدر ما يدخل في مكون SVG نظيف.