0Pricing
React Academy · درس

تحديد أنواع Context وCustom Hooks

أنشئ سياقًا محدد النوع بقيم افتراضية واكتب custom hooks مع أنواع إرجاع صريحة.

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

سياق محدّد النوع باستخدام createContext

مرّر نوع السياق وقيمة افتراضية إلى createContext. استخدم null كقيمة افتراضية عندما يجب استخدام السياق داخل مزوّد، وتعامل مع ذلك باستخدام حارس.

interface AuthContextType {
  user: User | null;
  login: (credentials: Credentials) => Promise<void>;
  logout: () => void;
}

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

نمط hook الحارس

أنشئ hook مخصّصًا يقرأ السياق ويطرح خطأً إذا استُخدم خارج المزوّد الخاص به. وبذلك تتخلص من عمليات التحقق من null في كل موضع استدعاء.

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

تحديد نوع المزوّد

يغلّف المزوّد العناصر الفرعية ويزوّدها بقيمة السياق. حدّد نوع كائن القيمة صراحةً حتى يتحقق TypeScript من توافقه مع نوع السياق.

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState<User | null>(null);

  const login = async (creds: Credentials) => {
    const u = await apiLogin(creds);
    setUser(u);
  };

  const logout = () => setUser(null);

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

السياق مع قيمة افتراضية

عند وجود قيمة افتراضية مناسبة، مثل سمة، مرّرها مباشرةً إلى createContext حتى لا يكون السياق null أبدًا ولا تحتاج إلى hook حارس.

interface ThemeContextType { theme: 'light' | 'dark'; toggle: () => void; }

const ThemeContext = createContext<ThemeContextType>({
  theme: 'light',
  toggle: () => {},
});

export const useTheme = () => useContext(ThemeContext);

تحديد أنواع القيم المرجعة من hooks المخصّصة

أضف تعليقًا توضيحيًا لنوع القيمة المرجعة من hooks المخصّصة صراحةً، أو اترك TypeScript يستنتجه. تعمل الأنواع الصريحة كتوثيق وتمنع تغيّر الشكل عرضيًا.

interface UseCounterReturn {
  count: number;
  increment: () => void;
  decrement: () => void;
  reset: () => void;
}

function useCounter(initial = 0): UseCounterReturn {
  const [count, setCount] = useState(initial);
  return {
    count,
    increment: () => setCount(c => c + 1),
    decrement: () => setCount(c => c - 1),
    reset: () => setCount(initial),
  };
}

أنواع القيم المرجعة على شكل tuple

تستخدم hooks التي تُرجع زوجًا، مثل useState، tuples. حدّد أنواعها باستخدام as const أو نوع tuple صريح حتى يُجري التفكيك الاستنتاج الصحيح.

function useToggle(initial = false): [boolean, () => void] {
  const [value, setValue] = useState(initial);
  const toggle = useCallback(() => setValue(v => !v), []);
  return [value, toggle];
}

// Destructuring correctly infers types:
const [isOpen, toggleOpen] = useToggle();

Hooks مخصّصة عامة

يمكن أن تكون hooks المخصّصة عامة أيضًا. إذ يخزّن hook عام باسم useLocalStorage أي نوع قابل للتسلسل مع أمان كامل للأنواع.

function useLocalStorage<T>(key: string, initialValue: T): [T, (val: T) => void] {
  const [stored, setStored] = useState<T>(() => {
    try {
      const item = localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch { return initialValue; }
  });

  const setValue = (val: T) => {
    setStored(val);
    localStorage.setItem(key, JSON.stringify(val));
  };

  return [stored, setValue];
}

تحديد نوع useReducer

عرّف أنواع الإجراءات كاتحادات مميَّزة، وشكل الحالة كواجهة. وسيفرض TypeScript أنواع الإجراءات الصحيحة داخل reducer.

interface State { count: number; status: 'idle' | 'loading'; }
type Action =
  | { type: 'INCREMENT' }
  | { type: 'SET_STATUS'; payload: State['status'] };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'INCREMENT': return { ...state, count: state.count + 1 };
    case 'SET_STATUS': return { ...state, status: action.payload };
  }
}

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

تحديد نوع useCallback وuseMemo

يستنتج TypeScript الأنواع الخاصة بـ useCallback وuseMemo من دالة الإنشاء. أضف الأنواع صراحةً فقط عندما يفشل الاستنتاج.

const handleChange = useCallback(
  (e: React.ChangeEvent<HTMLInputElement>) => {
    onChange(e.target.value);
  },
  [onChange]
);

const sorted = useMemo(
  () => [...items].sort((a, b) => a.name.localeCompare(b.name)),
  [items]
); // inferred as typeof items

نمط محدد السياق مع الأنواع

يتلقى hook محدد الأنواع دالة تحديد ويُرجع الجزء المطلوب فقط، مع الحفاظ على الاستنتاج الكامل للأنواع.

function useAuthSelector<T>(selector: (ctx: AuthContextType) => T): T {
  const ctx = useAuth();
  return selector(ctx);
}

// Usage — TypeScript infers User | null:
const user = useAuthSelector(ctx => ctx.user);

تجنّب any في hooks

لا تستخدم any مطلقًا في hooks المخصّصة. استخدم الأنواع العامة أو unknown مع حراس الأنواع أو واجهات محدّدة للحفاظ على سلسلة الأنواع سليمة.

// Bad:
function useFetch(url: string): { data: any; loading: boolean } { ... }

// Good:
function useFetch<T>(url: string): { data: T | null; loading: boolean } {
  const [data, setData] = useState<T | null>(null);
  // ...
  return { data, loading };
}

تحقق سريع

ما الغرض من نمط hook الحارس عند تحديد أنواع سياق React؟

مراجعة

حدّد نوع السياق باستخدام واجهة صريحة وhook يتحقق من null. أضف أنواعًا للقيم المرجعة من hooks المخصّصة باستخدام الواجهات أو أنواع tuple، واستخدم الأنواع العامة في hooks القابلة لإعادة الاستخدام، وحدّد نوع useReducer باستخدام إجراءات الاتحاد المميَّز لاكتشاف عمليات الإرسال غير الصحيحة أثناء الترجمة.

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

هل درس «تحديد أنواع Context وCustom Hooks» مجاني؟

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

ماذا ستتعلم في «تحديد أنواع Context وCustom Hooks»؟

أنشئ سياقًا محدد النوع بقيم افتراضية واكتب custom hooks مع أنواع إرجاع صريحة. تتمرن على React Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

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

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

كم من الوقت يستغرق درس «تحديد أنواع Context وCustom Hooks»؟

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

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

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

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

  1. تحديد أنواع الخصائص والقيم المرجعة للمكوّنات
  2. تحديد أنواع الأحداث والمراجع في TypeScript
  3. المكوّنات العامة وأنواع الأدوات
  4. تحديد أنواع Context وCustom Hooks
← العودة إلى React Academy