Skip to content

ما هي الـ Signals في JavaScript؟ ولماذا تتبناها كل أُطر العمل الحديثة؟

ما هي الـ Signals في JavaScript؟ ولماذا تتبناها كل أُطر العمل الحديثة؟

26 فبراير 2026 | 08:30

إذا كنت تتابع أخبار عالم تطوير الواجهات الأمامية في الفترة الأخيرة، فلا بد أنك صادفت كلمة Signals مرارا وتكرارا. Angular اعتمدتها رسميا، SolidJS بنيت عليها منذ اليوم الأول، Preact أضافتها، Vue.js - على لسان إيفان يو (Evan You) - وصفوها بأنها ”فكرة في جوهرها موجودة منذ مدة في مكتبة Vue ولكن تحت مسمى آخر هو ref()”. حتى اللجنة المسؤولة عن تطوير مواصفات جافاسكريبت (TC39) فتحت ملفا رسميا لإضافتها إلى اللغة نفسها.

إذن ما الذي يجري بالضبط؟ ولماذا هذا الاهتمام الكبير بفكرة تبدو في ظاهرها بسيطة؟

لنتكشف هذا معا في هذه التدوينة.

المشكلة التي تحلها الـ Signals

قبل أن نشرح ما هي الـ Signals، دعنا نفهم أولا المشكلة التي جاءت لحلها.

لنأخذ مثالا مبسطا في React. مكوّن يعرض عدَّادا، وزرَّا لزيادته:

function Counter() {
  const [count, setCount] = useState(0);
 
  return (
    <div>
      <p>العدد الحالي: {count}</p>
      <button onClick={() => setCount(count + 1)}>زيادة</button>
    </div>
  );
}

يبدو بسيطا. لكن ماذا يحدث خلف الكواليس عندما على نضغط على الزر؟

React لا تعرف بالضبط أين تُستخدم قيمة count داخل الـ JSX. كل ما تعرفه هو أن “هناك حالة تغيّرت في هذا المكوّن”. لذلك قرارها الوحيد هو: أعد رسم (Render) المكوّن بأكمله من جديد.

في مثالنا هذا الأمر مقبول تماما. لكن تخيّل أن لديك مكوّنا ضخما فيه عشرات العناصر، وتغيّرت حالة واحدة فقط تؤثر على عنصر واحد بالذات، رياكت ستعيد رسم كل شيء على أي حال، بالإعتماد على خوارزمية المقارنة (Diffing) الخاصة بها لتحديد ما تغيّر فعلا في الـ DOM.

هذا يعمل بشكل جيد في معظم الحالات، لكنه يعني: عمل إضافي غير ضروري في كل مرة.

تشبيه يوضح الفكرة

تخيّل أنك مدير في شركة، ولديك فريق مكوّن من 20 موظفا. في كل مرة يحدث أي تغيير - حتى لو كان تغييرا يخص موظفا واحدا فقط - تقوم بجمع الفريق كله في اجتماع عام، ثم توضح لكل واحد منهم ما الذي تغيّر، وتسأله: “هل يؤثر هذا عليك؟” فإذا قال لا، انصرف. وإذا قال نعم، تصرّف.

هذه هي طريقة عمل React تقريبا. تُعيد الرسم، ثم تقارن، ثم تحدّث ما تغيّر.

الآن تخيّل بدلا من ذلك أن كل موظف مشترك مباشرة في القرارات التي تخصه تحديدا. عندما يحدث تغيير، يصله إشعار فوري: “هذا يخصك، تصرّف”. لا اجتماع عام، لا مقارنة، لا جهد ضائع.

هذا بالضبط ما تفعله الـ Signals.


ما هي الـ Signal إذن؟

الـ Signal ببساطة هي وحدة تخزين للحالة تعرف بنفسها من يهتم بقيمتها، وتُخطره تلقائيا عند أي تغيير.

بدلا من أن يعيد الإطار رسم المكوّن بأكمله ليكتشف ما الذي تغيّر، كل Signal تحتفظ بقائمة المشتركين فيها. وعندما تتغيّر قيمتها، تذهب مباشرة لكل مشترك وتقول: “القيمة تغيّرت، حدّث نفسك.”

لنر كيف يبدو نفس المثال باستخدام الـ Signals في SolidJS:

import { createSignal } from "solid-js";
 
function Counter() {
  const [count, setCount] = createSignal(0);
 
  return (
    <div>
      <p>العدد الحالي: {count()}</p>
      <button onClick={() => setCount(count() + 1)}>زيادة</button>
    </div>
  );
}

يبدو مشابها جدا لـ useState في React! لكن الفرق الجوهري يكمن في هذا السطر:

<p>العدد الحالي: {count()}</p>

لاحظ أن count هنا لا نقرأ قيمتها مباشرة — بل نستدعيها كدالة count(). هذه التفصيلة الصغيرة لها أثر كبير.

عندما تُستدعى count() أثناء رسم الصفحة لأول مرة، تُسجّل الـ Signal في ذاكرتها: “هناك عقدة نصية (Text Node) معينة في الـ DOM تهتم بقيمتي”. بمعنى آخر، الـ Signal تعرف بدقة مَن يستخدمها.

بعدها عندما تتغيّر قيمة count، لا يحدث شيء درامي - لا يُعاد تنفيذ المكوّن من البداية، ولا تُقارَن نسخ افتراضية من الـ DOM. تذهب الـ Signal مباشرة لتلك العقدة النصية وتغيّر قيمتها فقط.

في SolidJS، المكوّن لا يُعاد تنفيذه أبدا بعد المرة الأولى ( مثلما يحدث في رياكت). الكود داخل الدالة يعمل مرة واحدة فقط عند الإنشاء، والـ Compiler يحوّل JSX إلى تعليمات DOM مباشرة.

لذلك ورغم أن SolidJS و React يتشابهان كثيرا من حيث الشكل وطريقة إنشاء المكونات (JSX)، إلا أن الآلية المتبعة لإدارة الحالة وتحيين تلك المكونات تختلف اختلافا جذريا بين الإثنين.

الأجزاء الثلاثة ل Signals

أي نظام Signals ناضج يتكوّن عادةً من ثلاثة عناصر أساسية:

أولا: State Signal — وهي الحالة الأساسية القابلة للتغيير:

const count = new Signal.State(0);
count.set(1); // تغيير القيمة
count.get(); // قراءة القيمة

ثانيا: Computed Signal — قيمة مشتقة من Signal أخرى، تتحدث تلقائيا عند تغيّر مصدرها:

const isEven = new Signal.Computed(() => count.get() % 2 === 0);
// isEven ستُعيد حساب قيمتها تلقائيا في كل مرة تتغير فيها count

ثالثا: Effect — كود جانبي يُنفذ تلقائيا عند تغيّر قيمة ال Signal الذي تم استدعاؤه بداخل ال Effect:

effect(() => {
  console.log(`القيمة الحالية: ${count.get()}`);
  // هذا الكود سيُنفَّذ مرة عند الإنشاء، ثم في كل مرة تتغيّر count
});

مقارنة مع منهجية رياكت

React (useState)Signals
عند تغيّر الحالةيُعيد رسم المكوّن كاملايُحدِّث فقط ما تغيّر
تتبع الإعتمادياتيدوي (dependency arrays)تلقائي
الأداء في التطبيقات الكبيرةيحتاج تحسينات (useMemo, useCallback)كفء بطبيعته

في مثال بسيط لن تلاحظ الفرق أبدا. لكن في تطبيق به مئات المكوّنات وبيانات تتغيّر باستمرار - كلوحة تحكم معقدة - يصبح الفرق ملموسا جدا.


أين تجد الـ Signals اليوم؟

الـ Signals كما ذكرنا في المقدمة ليست جديدة على الإطلاق. فكرة رد الفعل التلقائي على تغيّر البيانات (Reactivity) موجودة منذ زمن طويل. Knockout.js و Meteor استخدماها قبل أن تولد مكتبة React. لكن ما الجديد؟

الجديد هو أن كل الأطر الكبرى اتفقت على هذا النهج وبدأت تتبناه بجدية:

Vue.js : ref() وcomputed() هي في الحقيقة Signals بمسمى مختلف. Evan You نفسه قال ذلك صراحة في أكثر من مكان.

Preact: أضاف مكتبة @preact/signals منفصلة يمكن استخدامها حتى مع React العادية.

TC39: هيئة تطوير JavaScript فتحت اقتراحا رسميا لإضافة Signals كميزة أصلية في لغة الجافاسكريبت، بمشاركة من فرق Angular ،Solid، Vue وغيرهم.

TC39 Signals Proposal

ماذا عن React؟

السؤال الذي يطرحه الجميع: هل ستتبنى React الـ Signals؟

الجواب الصريح: على الأرجح لا، وهذا ليس خطأ.

React لها فلسفة مختلفة في جوهرها. هي تعتمد على Pure Rendering، أي أن واجهة المستخدم (UI) هي مجرد دالة للحالة، وفي كل مرة تتغيّر الحالة يُعاد حساب هذه الدالة من جديد. الـ Virtual DOM الخاص بها مُحسَّن بشكل كبير لهذا الغرض.

بدلا من ذلك، يتجه فريق React نحو مفهوم React Compiler الذي يحلل كودك تلقائيا ويضيف التحسينات اللازمة (مثل useMemo وuseCallback) دون أن تكتبها بنفسك.

طريقة مختلفة للوصول لنفس الهدف.

هل يجب عليك استخدام الـ Signals الآن؟

إذا كنت تعمل على مشروع Angular فالجواب هو “نعم”، هذا هو الاتجاه الرسمي للإطار، ابدأ بتعلمها.

إذا كنت تبحث عن إطار جديد للمشاريع المقبلة فإن SolidJS أو Preact خيارات ممتازة لتجربة Signals بشكلها الأنقى.

إذا كنت مع React فلا داعي للقلق. React تعمل بشكل ممتاز لمعظم حالات الاستخدام، والـ Signals ليست ثورة تُلغيها، بل هي نهج مختلف لحل نفس المشكلة.

خلاصة القول

الـ Signals ليست موضة عابرة. هي حل أنيق لمشكلة أساسية في إدارة الحالة: كيف تجعل واجهة المستخدم تتحدث بذكاء وبدون عمل يدوي وجهد إضافي كبير؟

الفكرة الجوهرية بسيطة: بدلا من إعادة حساب كل شيء في كل مرة، دع كل جزء من الـ UI يشترك مباشرة في البيانات التي يحتاجها، وسيُحدَّث فقط عند الحاجة.

هل سنرى الـ Signals قريبا كجزء رسمي من JavaScript نفسها؟ الأمور تسير في هذا الاتجاه. اقتراح TC39 لا يزال في مراحله الأولى، لكن المشاركة الواسعة من فرق Angular وSolid وVue وغيرها تُشير إلى أن هناك إرادة جدية لتوحيد هذا المفهوم على مستوى اللغة.

عيسى محمد علي
عيسى محمد علي
مطور ويب متخصص في الواجهات الأمامية، أحب التدوين وإغناء المحتوى التقني للغة الضاد وهذا كان السبب الرئيسي في إنشائي لمدونة توتومينا.