كل المقالات

هندسة04 نوفمبر 20268 دقائق قراءة0 مشاهدة

قبل أن تتعلم React، تعلّم هذه الأساسيات من JavaScript

هل تريد تعلّم React؟ قبل أن تبدأ، هناك مفاهيم أساسية في JavaScript يجب أن تفهمها، مثل import وexport والمصفوفات والكائنات وmap وfilter. إليك شرحًا بسيطًا مع أمثلة عملية.

Software engineer
شجرة من مكوّنات React ترتكز على أساس من مكعّبات مصنوعة من أسطر كود ملوّنة.

عندما بدأت تعلّم React، كنت أعتقد أن أصعب جزء هو فهم React نفسها.

لكن مع الوقت اكتشفت أن معظم المشكلات التي واجهتني لم تكن بسبب React، بل بسبب مفاهيم في JavaScript لم أكن أفهمها جيدًا.

كنت أرى import وexport دون أن أفهم الفرق بينهما، وأستخدم map() لعرض العناصر دون أن أعرف كيف تعمل، وأحيانًا أعدّل مصفوفة داخل state ثم أتساءل لماذا لم تتحدث الواجهة.

والمشكلة أن كثيرًا من المبتدئين يمرون بالتجربة نفسها.

لهذا، إذا كنت تخطط لتعلّم React، فأنصحك بفهم بعض أساسيات JavaScript أولًا.

لا تحتاج إلى إتقان اللغة بالكامل، لكن هناك مفاهيم ستستخدمها يوميًا أثناء كتابة تطبيقات React.

دعنا نتعرّف عليها بأمثلة بسيطة.

أولًا: React تعتمد على JavaScript

لنبدأ بمثال صغير لمكوّن React يعرض قائمة مهام:

JSX
import { useState } from "react";

export default function TodoList({ items }) {
  const [showDone, setShowDone] = useState(false);

  const visibleItems = items.filter(
    (item) => !showDone || item.done
  );

  return (
    <div>
      <button onClick={() => setShowDone(!showDone)}>
        Show completed only
      </button>

      <ul>
        {visibleItems.map((item) => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}

قد يبدو هذا الكود معقدًا إذا كنت مبتدئًا، لكنه في الحقيقة يجمع مجموعة من مفاهيم JavaScript البسيطة.

مثل:

  • import وexport لاستيراد الكود وتصديره.
  • const لتعريف المتغيرات.
  • ({ items }) لاستخراج قيمة من كائن.
  • () => لكتابة دالة قصيرة.
  • filter() لتصفية المصفوفات.
  • map() لتحويل عناصر المصفوفة إلى عناصر تظهر على الشاشة.

أما useState وJSX وطريقة عرض المكونات وتحديثها، فهي من المفاهيم التي ستتعلمها مع React.

مكوّن TodoList مع تلوين كل جزء: useState و JSX من React، أما import و export و const والتفكيك والدوال السهمية و filter و map والشروط فهي JavaScript عادية.

الفكرة هنا بسيطة: كلما فهمت JavaScript أكثر، أصبحت React أسهل.

ثانيًا: افهم ES6 وModules

عندما تبدأ بتعلّم React، ستسمع كثيرًا عن ES6 وJavaScript Modules.

فما الفرق بينهما؟

ES6 هو إصدار مهم من JavaScript صدر في عام 2015، وأضاف مجموعة كبيرة من الميزات التي نستخدمها اليوم، مثل:

  • let وconst
  • الدوال السهمية (Arrow Functions)
  • تفكيك الكائنات والمصفوفات (Destructuring)
  • عامل النشر (Spread)
  • القوالب النصية (Template Literals)
  • نظام الوحدات (Modules)

أما Modules فهي ميزة تسمح لك بتقسيم الكود إلى ملفات مستقلة، واستيراد ما تحتاجه منها.

كيف تعمل import وexport؟

تخيّل أن لديك ملفًا يحتوي على مجموعة من الدوال الرياضية:

JavaScript
// math.js

export const add = (a, b) => a + b;

export const subtract = (a, b) => a - b;

يمكنك استخدام هذه الدوال في ملف آخر:

JavaScript
// app.js

import { add, subtract } from "./math.js";

console.log(add(5, 3));      // 8
console.log(subtract(5, 3)); // 2

بهذه الطريقة، لا تحتاج إلى كتابة الدوال نفسها في كل ملف.

لكن هناك نوعان من التصدير يجب أن تعرفهما.

Named Export وDefault Export

Named Export يعني أنك تصدّر شيئًا باسمه، وتستخدم الأقواس المعقوفة عند استيراده:

JavaScript
// utils.js
export const greet = (name) => `Hello ${name}`;

import { greet } from "./utils.js";

أما Default Export فيسمح لك بتصدير قيمة افتراضية واحدة من الملف، ويمكنك اختيار اسمها عند الاستيراد:

JavaScript
// greet.js
export default function greet(name) {
  return `Hello ${name}`;
}

import sayHello from "./greet.js";
الملف math.js يصدّر add و subtract بالاسم، و greet.js يصدّر greet كتصدير افتراضي، و app.js يستورد { add, subtract } بأقواس معقوفة و sayHello بدونها.

وهذا يفسّر لماذا نكتب في React:

JSX
import { useState } from "react";
import Header from "./Header.jsx";

الأولى تستورد قيمة مسمّاة، والثانية تستورد التصدير الافتراضي.

تذكّر: الأقواس { } في الاستيراد المسمّى ليست مجرد تنسيق، بل لها معنى مختلف عن الاستيراد الافتراضي.

وقد تصادف أيضًا require() وmodule.exports في مشاريع Node.js القديمة. هذا نظام آخر يسمى CommonJS، لكن تعلّم import وexport أولًا، لأنهما الأكثر استخدامًا في كود React الحديث.

ثالثًا: أهم ميزات JavaScript الحديثة

هناك بعض الميزات التي ستراها باستمرار أثناء كتابة React.

1. المتغيرات: const وlet

في JavaScript الحديثة، نستخدم غالبًا const وlet بدل var.

JavaScript
const name = "Ali";

let count = 0;
count = 1;

الفرق بسيط:

  • const: لا يمكنك إعادة إسناد قيمة جديدة للمتغير.
  • let: يمكنك تغيير قيمته لاحقًا.

ابدأ باستخدام const، وانتقل إلى let عندما تحتاج إلى إعادة تعيين قيمة المتغير.

2. الدوال السهمية (Arrow Functions)

بدل كتابة دالة بالطريقة التقليدية:

JavaScript
function double(number) {
  return number * 2;
}

يمكنك كتابتها بشكل أقصر:

JavaScript
const double = (number) => number * 2;

النتيجة نفسها في هذا المثال.

وستستخدم الدوال السهمية كثيرًا مع map وfilter وأحداث React.

انتبه فقط إلى أن الدالة السهمية بدون أقواس معقوفة تُرجع التعبير تلقائيًا، بينما تحتاج إلى return إذا استخدمت جسم دالة بين { }.

3. تفكيك الكائنات والمصفوفات (Destructuring)

تخيّل أن لديك كائنًا يحتوي على بيانات مستخدم:

JavaScript
const user = {
  name: "Sara",
  age: 24,
};

بدل كتابة:

JavaScript
const name = user.name;
const age = user.age;

يمكنك كتابة:

JavaScript
const { name, age } = user;

ويمكن فعل الشيء نفسه مع المصفوفات:

JavaScript
const colors = ["red", "blue"];

const [first, second] = colors;

هذا المفهوم مهم جدًا لأن React تستخدمه كثيرًا:

JSX
const [count, setCount] = useState(0);

هنا تُرجع useState مصفوفة تحتوي على القيمة الحالية ودالة لتحديثها، ونستخدم التفكيك للحصول عليهما.

4. عامل النشر (Spread Operator)

يسمح لك العامل ... بنشر محتويات مصفوفة أو كائن داخل قيمة جديدة.

JavaScript
const numbers = [1, 2, 3];

const updated = [...numbers, 4];

console.log(updated); // [1, 2, 3, 4]

ويمكن استخدامه مع الكائنات:

JavaScript
const user = {
  name: "Sara",
  age: 24,
};

const updatedUser = {
  ...user,
  age: 25,
};

بهذا أنشأنا كائنًا جديدًا مع تغيير العمر فقط.

ستحتاج إلى هذا المفهوم كثيرًا عند تحديث بيانات state في React.

لاحظ أن Spread ينشئ نسخة سطحية، وليس نسخة مستقلة من جميع الكائنات والمصفوفات المتداخلة.

5. النصوص القالبية (Template Literals)

بدل دمج النصوص بهذه الطريقة:

JavaScript
const message = "Hello " + name;

يمكنك استخدام:

JavaScript
const message = `Hello ${name}`;

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

ومن المفيد أيضًا معرفة ?. للوصول الآمن إلى الخصائص الاختيارية، و?? لتحديد قيمة بديلة عندما تكون القيمة null أو undefined.

رابعًا: افهم الكائنات والمصفوفات قبل استخدام State

هذه واحدة من أهم النقاط التي أنصح بفهمها قبل تعلّم React.

في JavaScript، هناك فرق بين القيم البسيطة مثل الأرقام والنصوص، وبين الكائنات والمصفوفات.

لنبدأ بمثال:

JavaScript
let a = 5;
let b = a;

b = 10;

console.log(a); // 5

تغيير b لم يؤثر على a.

لكن مع المصفوفات، الأمر مختلف:

JavaScript
const numbers = [1, 2];

const copy = numbers;

copy.push(3);

console.log(numbers); // [1, 2, 3]

لماذا تغيّرت المصفوفة الأصلية؟

لأن copy وnumbers يشيران إلى المصفوفة نفسها في الذاكرة.

وهذا مهم جدًا في React.

تخيّل أن لديك قائمة مهام محفوظة في state:

JSX
const [todos, setTodos] = useState([]);

إذا أردت إضافة مهمة جديدة، فقد تكتب:

JavaScript
// طريقة خاطئة
todos.push(newTodo);
setTodos(todos);

لكن المشكلة أنك عدّلت المصفوفة نفسها، ثم مرّرت المرجع القديم إلى React.

React تعتمد على مقارنة قيمة الحالة الجديدة بالسابقة، ولذلك قد لا تعيد عرض المكوّن عندما تعيد تمرير المصفوفة نفسها.

الطريقة الصحيحة:

JavaScript
setTodos([...todos, newTodo]);

والأفضل عند الاعتماد على الحالة السابقة:

JavaScript
setTodos((previous) => [...previous, newTodo]);

هنا ننشئ مصفوفة جديدة تحتوي على العناصر القديمة والعنصر الجديد.

القاعدة المهمة: لا تعدّل المصفوفات والكائنات المخزنة في React State مباشرة. أنشئ نسخة جديدة مع التعديلات المطلوبة.

خامسًا: تعلّم دوال المصفوفات (Array Methods)

إذا كان هناك جزء من JavaScript يستحق أن تمنحه وقتًا إضافيًا قبل React، فهو دوال المصفوفات.

ستستخدمها لعرض القوائم، وتصفية النتائج، والبحث عن البيانات، وإجراء الحسابات.

لنستخدم هذه البيانات في الأمثلة:

JavaScript
const products = [
  { id: 1, name: "Laptop", price: 800 },
  { id: 2, name: "Mouse", price: 20 },
  { id: 3, name: "Keyboard", price: 50 },
];
قائمة منتجات فيها Laptop بسعر 800 و Mouse بسعر 20 و Keyboard بسعر 50، وما ترجعه كل دالة: map مصفوفة أسماء جديدة، و filter المنتجين Mouse و Keyboard، و find المنتج Mouse، و some القيمة true، و every القيمة false، و reduce الرقم 870.

map() — تحويل عناصر المصفوفة

تستخدم map() عندما تريد إنشاء مصفوفة جديدة من عناصر المصفوفة الأصلية.

مثل استخراج أسماء المنتجات:

JavaScript
const names = products.map(
  (product) => product.name
);

console.log(names);
// ["Laptop", "Mouse", "Keyboard"]

ترجع map() مصفوفة جديدة تحتوي على نتيجة الدالة لكل عنصر.

filter() — تصفية العناصر

تستخدم filter() عندما تريد الاحتفاظ بالعناصر التي تحقق شرطًا معينًا.

مثل المنتجات التي يقل سعرها عن 100:

JavaScript
const cheapProducts = products.filter(
  (product) => product.price < 100
);

النتيجة تحتوي على Mouse وKeyboard فقط.

find() — البحث عن عنصر واحد

إذا أردت البحث عن منتج معين:

JavaScript
const product = products.find(
  (product) => product.id === 2
);

ستحصل على كائن Mouse.

وإذا لم تجد الدالة عنصرًا يطابق الشرط، فسترجع undefined.

some() وevery() — التحقق من الشروط

تستخدم some() لمعرفة ما إذا كان هناك عنصر واحد على الأقل يحقق الشرط:

JavaScript
const hasExpensiveProduct = products.some(
  (product) => product.price > 500
);

// true

أما every() فتتحقق من أن جميع العناصر تحقق الشرط:

JavaScript
const allAffordable = products.every(
  (product) => product.price < 100
);

// false

reduce() — حساب قيمة من المصفوفة

تستخدم reduce() عندما تريد جمع بيانات المصفوفة في نتيجة واحدة.

مثل حساب السعر الإجمالي لجميع المنتجات:

JavaScript
const total = products.reduce(
  (sum, product) => sum + product.price,
  0
);

console.log(total); // 870

تبدأ الدالة بالقيمة 0، ثم تضيف سعر كل منتج إلى المجموع حتى تصل إلى النتيجة النهائية.

احذر من الدوال التي تعدّل المصفوفة

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

مثلًا، push() وsplice() وsort() وreverse() تغيّر المصفوفة الأصلية.

أما map() وfilter() وslice() فتُرجع مصفوفات جديدة دون تعديل الأصل.

إذا أردت ترتيب المنتجات حسب السعر دون تغيير المصفوفة الأصلية:

JavaScript
const sortedProducts = [...products].sort(
  (a, b) => a.price - b.price
);

أو باستخدام toSorted() في بيئات JavaScript الحديثة:

JavaScript
const sortedProducts = products.toSorted(
  (a, b) => a.price - b.price
);

فهم هذا الفرق سيساعدك كثيرًا عند التعامل مع React State.

سادسًا: ما الفرق بين map وforEach؟

كثير من المبتدئين يخلطون بين map() وforEach()، لأن كليهما يمر على عناصر المصفوفة.

لكن الفرق الأساسي بينهما هو القيمة التي ترجعها كل دالة.

قائمة JSX نفسها مكتوبة بـ forEach و map. الدالة forEach ترجع undefined فتبقى الشاشة فارغة، و map ترجع مصفوفة من عناصر li فتظهر القائمة.

لنبدأ بـforEach():

JavaScript
const numbers = [1, 2, 3];

numbers.forEach((number) => {
  console.log(number);
});

ستطبع الأرقام:

Code
1
2
3

لكن forEach() نفسها ترجع undefined.

أما map():

JavaScript
const doubled = numbers.map(
  (number) => number * 2
);

console.log(doubled);
// [2, 4, 6]

ترجع مصفوفة جديدة.

لماذا نستخدم map في React؟

تخيّل أنك تريد عرض قائمة من المستخدمين:

JavaScript
const users = ["Sara", "Ali", "Omar"];

يمكنك كتابة:

JSX
<ul>
  {users.map((user) => (
    <li key={user}>{user}</li>
  ))}
</ul>

تقوم map() بتحويل كل اسم إلى عنصر JSX، ثم ترجع مصفوفة من العناصر تستطيع React عرضها.

لكن إذا استخدمت forEach():

JSX
<ul>
  {users.forEach((user) => (
    <li key={user}>{user}</li>
  ))}
</ul>

فلن تظهر العناصر، لأن forEach() لا ترجع المصفوفة التي أنشأتها داخل الدالة.

إذن:

  • استخدم map() عندما تريد إنشاء مصفوفة جديدة، مثل تحويل البيانات إلى عناصر واجهة.
  • استخدم forEach() عندما تريد تنفيذ عملية لكل عنصر دون الحاجة إلى مصفوفة جديدة.

وهناك نقطة إضافية: عند عرض قائمة في React، استخدم key فريدًا وثابتًا لكل عنصر، مثل معرف المستخدم أو المنتج، حتى تستطيع React تتبع العناصر عند تحديث القائمة.

سابعًا: هل يجب أن تتعلم الحلقات (Loops)؟

نعم، لكن لا تحتاج إلى التعمق فيها قبل React.

في JavaScript يمكنك المرور على العناصر بطرق مختلفة:

حلقة for التقليدية:

JavaScript
for (let i = 0; i < 3; i++) {
  console.log(i);
}

حلقة for...of:

JavaScript
const names = ["Ali", "Sara", "Omar"];

for (const name of names) {
  console.log(name);
}

حلقة while:

JavaScript
let count = 0;

while (count < 3) {
  console.log(count);
  count++;
}

حلقة for...in تُستخدم للمرور على أسماء الخصائص القابلة للتعداد في الكائنات:

JavaScript
const user = {
  name: "Ali",
  age: 25,
};

for (const key in user) {
  console.log(key);
}

ويمكنك استخدام Object.keys() عندما تريد الحصول على أسماء خصائص الكائن نفسه فقط.

كل هذه الطرق مفيدة، لكن ستلاحظ أن map() أكثر شيوعًا عند عرض قوائم React، لأنها تُرجع قيمًا يمكن وضعها مباشرة داخل JSX.

ثامنًا: افهم الشروط قبل كتابة JSX

من الأشياء التي ستستخدمها كثيرًا في React عرض عناصر مختلفة حسب شرط معين.

في JavaScript يمكنك استخدام if:

JavaScript
if (isLoggedIn) {
  console.log("Welcome");
} else {
  console.log("Please login");
}

لكن داخل JSX ستستخدم كثيرًا العامل الثلاثي ? ::

JSX
{isLoggedIn ? (
  <p>Welcome</p>
) : (
  <p>Please login</p>
)}

وإذا كنت تريد عرض عنصر فقط عند تحقق شرط، يمكنك استخدام &&:

JSX
{isLoggedIn && <p>Welcome</p>}

انتبه إلى أن الطرف الأيسر من && قد يظهر كقيمة على الشاشة إذا لم يكن قيمة منطقية.

مثلًا:

JSX
{count && <p>New messages</p>}

إذا كانت count تساوي صفرًا، فقد يظهر الرقم 0 على الشاشة.

الأفضل كتابة:

JSX
{count > 0 && <p>New messages</p>}

تفاصيل صغيرة كهذه تصبح أسهل عندما تفهم سلوك JavaScript أولًا.

أفضل المصادر لتعلّم JavaScript

لا تحتاج إلى مشاهدة عشرات الدورات قبل البدء في React.

اختر مصدرًا واحدًا أو اثنين، ثم طبّق ما تتعلمه في مشاريع صغيرة.

  1. MDN JavaScript Guide
    من أفضل المراجع لتعلّم JavaScript وفهم طريقة عملها. أنصح بالعودة إليه كلما واجهت مفهومًا غير واضح.
  2. JavaScript.info
    موقع ممتاز للمبتدئين، يشرح المفاهيم بالتدريج، مع أمثلة وتمارين تساعدك على التطبيق.
  3. Eloquent JavaScript
    كتاب مجاني على الإنترنت يشرح JavaScript من الأساسيات حتى المفاهيم المتقدمة، ومفيد لمن يريد فهم اللغة بشكل أعمق.
  4. You Don't Know JS Yet
    سلسلة كتب مفتوحة المصدر تساعدك على فهم تفاصيل JavaScript مثل Scope وClosures. أنصح بها بعد إتقان الأساسيات.
  5. Meta Front-End Developer Professional Certificate
    إذا كنت تفضّل مسارًا تعليميًا منظمًا، فهذه الشهادة تشمل أساسيات تطوير الواجهات، ثم JavaScript وReact ومشاريع تطبيقية.

تختلف خيارات الدراسة المجانية والمساعدة المالية بحسب سياسات Coursera والدورة.

تمرين أنصحك به قبل React

بدل الاكتفاء بمشاهدة الدروس، جرّب بناء تطبيق مهام بسيط باستخدام JavaScript العادية.

اجعل التطبيق يستطيع:

  1. إضافة مهمة جديدة.
  2. حذف مهمة.
  3. تحديد المهمة كمكتملة.
  4. عرض المهام المكتملة فقط.
  5. حفظ المهام في localStorage.

أثناء بناء التطبيق، ستستخدم المتغيرات والمصفوفات والكائنات والدوال والشروط والحلقات.

وبعد أن تنتهي، حاول بناء التطبيق نفسه باستخدام React.

ستلاحظ أن الكثير من المنطق الذي كتبته سابقًا لم يتغير، لكن React أصبحت تساعدك على تنظيم الواجهة وتحديثها عند تغيّر البيانات.

وهذه من أفضل الطرق لفهم الفرق بين JavaScript وReact عمليًا.

كيف تعرف أنك جاهز لتعلّم React؟

قبل أن تبدأ، تأكد من أنك تستطيع:

  • استخدام import وexport وفهم الفرق بين التصدير المسمّى والافتراضي.
  • كتابة الدوال السهمية وفهم قيمة return.
  • التعامل مع الكائنات والمصفوفات باستخدام Destructuring وSpread.
  • استخدام map() وfilter() وfind() وreduce().
  • معرفة الفرق بين تعديل مصفوفة وإنشاء مصفوفة جديدة.
  • استخدام الشروط والحلقات لفهم البيانات وعرضها.

لا يشترط أن تحفظ جميع الدوال أو تعرف كل تفاصيل JavaScript.

المهم أن تكون قادرًا على قراءة الكود البسيط وفهم ما يفعله، وأن تعرف أين تبحث عندما تواجه شيئًا جديدًا.

الخلاصة

React ليست صعبة بالضرورة، لكن محاولة تعلّمها دون أساس جيد في JavaScript تجعل الأمور أكثر تعقيدًا مما ينبغي.

الكثير من المشكلات التي يواجهها المبتدئون، مثل عدم تحديث State أو عدم ظهور العناصر أو أخطاء الاستيراد، تصبح أسهل عندما يفهمون طريقة عمل JavaScript.

لهذا لا تتعجل الانتقال إلى React بمجرد أن تتعلم المتغيرات والدوال.

امنح نفسك وقتًا لفهم المصفوفات والكائنات والـModules ودوال المصفوفات، ثم ابدأ بتطبيق ما تعلمته.

الهدف ليس أن تتعلم JavaScript بالكامل قبل React، بل أن تتعلم منها ما يكفي حتى تفهم الكود الذي تكتبه، بدل أن تكتفي بنسخه.

0لا تعليقات
مشاركة

التعليقات

تظهر التعليقات بعد مراجعة سريعة لمنع الرسائل المزعجة. لا حاجة لبريد إلكتروني.

لا تعليقات بعد. كن أول من يعلّق.

تابع القراءة