0Pricing
React Academy · درس

تقليل INP: تحسين معالجات الأحداث

أخّر المعالجات الثقيلة، واستخدم scheduler.yield()، وتجنب المهام الطويلة التي تحجب الخيط الرئيسي.

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

ما هو INP؟

يقيس Interaction to Next Paint (INP) زمن الانتقال من تفاعل المستخدم، مثل النقر أو اللمس أو ضغط مفتاح، إلى لحظة عرض المتصفح للاستجابة. ويبدو INP الذي يتجاوز 200ms بطيئاً.

لماذا قد تكون أحداث React بطيئة

تحجب معالجات أحداث React التي تنفذ الكثير من العمل بشكل متزامن الخيط الرئيسي. ولا يستطيع المتصفح عرض الاستجابة حتى تكتمل مهمة JavaScript، مما يؤدي إلى ارتفاع INP.

إزالة التكرار من الإدخال المكتوب

أجّل العمليات المكلفة، مثل استدعاءات API البحث والحسابات الثقيلة، التي تُفعّلها ضغطات المفاتيح باستخدام debounce. لا مشكلة في تحديث حالة React عند كل ضغطة مفتاح؛ بل يجب تأجيل العمل المكلف.

import { useDeferredValue, useState } from 'react';

function SearchPage() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query); // defers re-render of slow parts

  return (
    <>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <SearchResults query={deferredQuery} /> {/* re-renders with lower priority */}
    </>
  );
}

استخدام useTransition للتحديثات غير العاجلة

غلّف تحديثات الحالة البطيئة داخل startTransition لوضع علامة بأنها غير عاجلة. يؤجلها React، مما يحافظ على استجابة الإدخال.

const [isPending, startTransition] = useTransition();

function handleFilter(value) {
  setInputValue(value); // urgent — update input immediately
  startTransition(() => {
    setFilteredList(expensiveFilter(value)); // non-urgent — can be interrupted
  });
}

نقل العمل الثقيل خارج الخيط الرئيسي

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

const worker = new Worker(new URL('./heavy-worker.js', import.meta.url));

function processData(data) {
  return new Promise(resolve => {
    worker.postMessage(data);
    worker.onmessage = e => resolve(e.data);
  });
}

// In component:
const handleClick = async () => {
  const result = await processData(largeDataset); // doesn't block main thread
  setResult(result);
};

تجنب المهام الطويلة

تحجب المهام الطويلة (>50ms) الخيط الرئيسي وتزيد INP. قسّمها باستخدام setTimeout أو scheduler.yield() أو requestIdleCallback.

async function processInChunks(items) {
  const CHUNK_SIZE = 100;
  for (let i = 0; i < items.length; i += CHUNK_SIZE) {
    const chunk = items.slice(i, i + CHUNK_SIZE);
    processChunk(chunk);
    await new Promise(r => setTimeout(r, 0)); // yield to browser between chunks
  }
}

scheduler.yield() (واجهة API الحديثة)

تعيد scheduler.yield() التحكم إلى حلقة أحداث المتصفح، مما يسمح بمعالجة تفاعلات المستخدم المعلقة قبل استئناف شيفرتك.

async function longTask() {
  for (const item of largeList) {
    processItem(item);
    if (/* every N items */) {
      await scheduler.yield(); // let browser handle pending clicks/inputs
    }
  }
}

تجنب التخطيطات المتزامنة في المعالجات

تؤدي قراءة خصائص التخطيط، مثل offsetWidth وgetBoundingClientRect()، إلى فرض إعادة حساب متزامنة للتخطيط. اجمع عمليات القراءة قبل الكتابة لتجنب تكرار إعادة حساب التخطيط.

// Bad — forces layout recalculation on each iteration:
items.forEach(item => {
  const height = item.offsetHeight; // READ — forces layout
  item.style.height = height * 2 + 'px'; // WRITE — dirties layout
});

// Good — batch reads, then writes:
const heights = items.map(item => item.offsetHeight); // all reads
heights.forEach((h, i) => items[i].style.height = h * 2 + 'px'); // all writes

إجراءات React 19 لـ INP غير المتزامن

تتعامل إجراءات React 19 مع التغييرات غير المتزامنة دون حجب واجهة المستخدم — إذ تُحدَّث حالة الانتظار بشكل مستقل، فتظل الصفحة تفاعلية.

function LikeButton({ postId }) {
  const [optimistic, setOptimistic] = useOptimistic(false);

  async function handleLike() {
    setOptimistic(true);
    await likePost(postId); // async — doesn't block
  }

  return <button onClick={handleLike}>{optimistic ? 'Liked' : 'Like'}</button>;
}

مشكلات تفويض الأحداث

يستخدم React تفويضاً اصطناعياً للأحداث، إذ يثبت مستمعاً واحداً على العنصر الجذر. تجنب تثبيت مئات مستمعي DOM الفرديين داخل useEffect — واستخدم بدلاً من ذلك أحداث React الاصطناعية على عناصر JSX.

قياس INP في DevTools

استخدم لوحة Performance في Chrome DevTools لتسجيل تفاعل وفحص المهام الطويلة. ابحث عن إدخالات «Interaction» في المخطط الزمني ووسّعها للعثور على تقييمات الشيفرات البرمجية التي تحجب التنفيذ.

تحقق سريع

أي خطاف في React يضع علامة على تحديث الحالة بأنه غير عاجل، بحيث يمكن مقاطعته بواسطة تفاعلات المستخدم؟

مراجعة

خفّض INP بتأجيل العمل المكلف باستخدام debounce، واستخدام startTransition للتحديثات غير العاجلة، ونقل العمل الذي يستهلك وحدة المعالجة المركزية إلى Web Workers، وتقسيم المهام الطويلة باستخدام scheduler.yield(). اجمع قراءات DOM قبل عمليات الكتابة لتجنب تكرار إعادة حساب التخطيط.

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

هل درس «تقليل INP: تحسين معالجات الأحداث» مجاني؟

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

ماذا ستتعلم في «تقليل INP: تحسين معالجات الأحداث»؟

أخّر المعالجات الثقيلة، واستخدم scheduler.yield()، وتجنب المهام الطويلة التي تحجب الخيط الرئيسي. تتمرن على React Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

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

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

كم من الوقت يستغرق درس «تقليل INP: تحسين معالجات الأحداث»؟

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

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

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

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

  1. قياس مؤشرات الويب الأساسية في تطبيقات React
  2. تحليل الحزمة واستراتيجية تقسيم التعليمات البرمجية
  3. تحسين الصور والخطوط في React
  4. تقليل INP: تحسين معالجات الأحداث
← العودة إلى React Academy