0Pricing
Frontend Academy · درس

TypeScript مع React: الأنواع العامة لـ FC وhooks

حدّد أنواع مكوّنات React باستخدام props عامة، وأضف أنواعًا صريحة إلى useState وuseRef، وحدّد نوع hooks المخصّصة التي تُرجع tuples

TypeScript مع React: الأنواع العامة لـ FC وhooks درس مجاني في Frontend Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Frontend Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Frontend Academy 4 دروس في المجموع.

كتابة أنواع المكونات

في React الحديث، عرّفوا أنواع الخصائص باستخدام interface واستخدموا دالة عادية. توجد React.FC، لكنها لم تعد موصى بها (لأنها تضيف children ضمنيًا ولا تدعم الأنواع العامة).

// Recommended:
interface ButtonProps {
  label: string;
  onClick: () => void;
  disabled?: boolean;
}

function Button({ label, onClick, disabled }: ButtonProps) {
  return <button onClick={onClick} disabled={disabled}>{label}</button>;
}

كتابة نوع children

استخدموا React.ReactNode لأي عنصر ابن قابل للعرض.

interface CardProps {
  title: string;
  children: React.ReactNode;
}

function Card({ title, children }: CardProps) {
  return (
    <div className="card">
      <h2>{title}</h2>
      {children}
    </div>
  );
}

كتابة نوع useState

يستنتج useState النوع عادةً من القيمة الابتدائية. وفّروا نوعًا صريحًا عندما تكون القيمة الابتدائية null أو لا تمثل جميع الأنواع المحتملة.

const [count, setCount] = useState(0);              // number
const [name, setName] = useState('');                // string

const [user, setUser] = useState<User | null>(null); // explicit
const [items, setItems] = useState<Item[]>([]);      // explicit array type

كتابة نوع useRef

هناك صيغتان: مرجع إلى عنصر DOM (تتم تهيئته إلى null)، أو حاوية قابلة للتغيير.

const inputRef = useRef<HTMLInputElement>(null);
const timerRef = useRef<number | null>(null);

useEffect(() => {
  inputRef.current?.focus();
  timerRef.current = window.setInterval(tick, 1000);
  return () => clearInterval(timerRef.current!);
}, []);

كتابة أنواع معالجات الأحداث

استخدموا أنواع الأحداث الاصطناعية الخاصة بـ React.

function Form() {
  function onSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
  }
  function onChange(e: React.ChangeEvent<HTMLInputElement>) {
    setValue(e.target.value);
  }
  function onClick(e: React.MouseEvent<HTMLButtonElement>) {
    /* ... */
  }
  return <form onSubmit={onSubmit}>...</form>;
}

المكونات العامة

يمكن أن تكون المكونات عامة — إذ يستنتج TypeScript معلمة النوع من موضع الاستدعاء.

interface ListProps<T> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
  keyOf: (item: T) => string | number;
}

function List<T>({ items, renderItem, keyOf }: ListProps<T>) {
  return <ul>{items.map(i => <li key={keyOf(i)}>{renderItem(i)}</li>)}</ul>;
}

<List<User>
  items={users}
  renderItem={u => u.name}
  keyOf={u => u.id}
/>

كتابة أنواع الخطافات المخصصة

الخطافات المخصصة دوال، لذا اكتبوا أنواعها كما تكتبون نوع أي دالة أخرى. وتحتاج الصفوف المُعادة إلى تعيين صريح للنوع لتجنب توسيعها إلى مصفوفة.

function useToggle(initial = false): [boolean, () => void] {
  const [value, setValue] = useState(initial);
  const toggle = () => setValue(v => !v);
  return [value, toggle]; // tuple — annotation makes this stable
}

const [isOpen, toggle] = useToggle();

كتابة نوع Context

تحتاج createContext إلى قيمة ابتدائية من النوع نفسه للقيمة التي ستوفرونها. استخدموا تأكيدًا بعدم كون القيمة null أو كائنًا افتراضيًا.

interface AuthContextValue {
  user: User | null;
  signIn: (email: string, pw: string) => Promise<void>;
  signOut: () => void;
}

const AuthContext = createContext<AuthContextValue | null>(null);

export function useAuth() {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be inside AuthProvider');
  return ctx;
}

كتابة نوع useReducer

حدّدوا نوع الحالة واتحاد الإجراءات بشكل صريح.

type State = { count: number };
type Action =
  | { type: 'increment' }
  | { type: 'decrement' }
  | { type: 'set'; value: number };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'increment': return { count: state.count + 1 };
    case 'decrement': return { count: state.count - 1 };
    case 'set':       return { count: action.value };
  }
}

const [state, dispatch] = useReducer(reducer, { count: 0 });

تجنبوا React.FC

تراجع استخدام React.FC: فهي تضيف children ضمنيًا، ولا تدعم المكونات العامة بطريقة سلسة، وتعيق بعض التحسينات. فضّلوا مكونات الدوال العادية مع خصائص محددة النوع.

أداة ComponentPropsWithoutRef

لوراثة خصائص عنصر أصلي (مثل توسيع خصائص زر أو حقل إدخال)، استخدم ComponentPropsWithoutRef.

type ButtonProps = React.ComponentPropsWithoutRef<'button'> & {
  variant?: 'primary' | 'secondary';
};

function Button({ variant = 'primary', ...rest }: ButtonProps) {
  return <button className={`btn ${variant}`} {...rest} />;
}

اختبار سريع

لماذا لا يُنصح عمومًا باستخدام React.FC، ويُفضَّل استخدام مكوّنات دوال عادية ذات أنواع محددة؟

مراجعة: TypeScript + React

حدّد أنواع الخصائص باستخدام الواجهات، وفضّل الدوال العادية على React.FC. استخدم children: React.ReactNode. غالبًا ما يستنتج useState النوع تلقائيًا؛ أضف تعليقًا توضيحيًا عند استخدام null أو المصفوفات الفارغة. استخدم useRef لعناصر DOM. استخدم أنواع أحداث React لمعالجات الأحداث. استخدم المكوّنات العامة للقوائم والنماذج القابلة لإعادة الاستخدام. تحتاج القيمة المرجعة على شكل Tuple من Hooks مخصّصة إلى تحديد نوع. استخدم ComponentPropsWithoutRef لتوسيع العناصر الأصلية.

الأسئلة الشائعة

هل درس «TypeScript مع React: الأنواع العامة لـ FC وhooks» مجاني؟

نعم — نص درس «TypeScript مع React: الأنواع العامة لـ FC وhooks» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Frontend Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Frontend Academy 4 دروس في المجموع.

ماذا ستتعلم في «TypeScript مع React: الأنواع العامة لـ FC وhooks»؟

حدّد أنواع مكوّنات React باستخدام props عامة، وأضف أنواعًا صريحة إلى useState وuseRef، وحدّد نوع hooks المخصّصة التي تُرجع tuples تتمرن على Frontend Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Frontend Academy؟

لا تُشترط خبرة سابقة. Frontend Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «TypeScript مع React: الأنواع العامة لـ FC وhooks»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Frontend Academy هذا؟

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

جميع الدروس في هذه الدورة

  1. أنواع Template Literal
  2. Decorators والبيانات الوصفية
  3. TypeScript مع React: الأنواع العامة لـ FC وhooks
  4. الوضع الصارم والتخلّص من any
← العودة إلى Frontend Academy