التحديث السريع (Fast Refresh)

أمثلة

التحديث السريع هو ميزة في Next.js تمنحك ملاحظات فورية على التعديلات التي تجريها على مكونات React. التحديث السريع مفعل افتراضيًا في جميع تطبيقات Next.js على الإصدار 9.4 أو أحدث. مع تفعيل التحديث السريع في Next.js، يجب أن تكون معظم التعديلات مرئية في غضون ثانية دون فقدان حالة المكون.

كيف يعمل

  • إذا قمت بتحرير ملف يصدّر فقط مكونات React، فسيقوم التحديث السريع بتحديث الكود لهذا الملف فقط، وإعادة عرض مكونك. يمكنك تحرير أي شيء في هذا الملف، بما في ذلك الأنماط، منطق العرض، معالجات الأحداث، أو التأثيرات.
  • إذا قمت بتحرير ملف يحتوي على تصديرات ليست مكونات React، فسيعيد التحديث السريع تشغيل هذا الملف والملفات الأخرى التي تستورده. لذا إذا كان كل من Button.js و Modal.js يستوردان theme.js، فإن تحرير theme.js سيحدث كلا المكونين.
  • أخيرًا، إذا قمت بتحرير ملف يتم استيراده بواسطة ملفات خارج شجرة React، فسيعود التحديث السريع إلى إعادة تحميل كاملة. قد يكون لديك ملف يعرض مكون React ولكنه أيضًا يصدر قيمة يتم استيرادها بواسطة مكون غير React. على سبيل المثال، ربما يصدر مكونك أيضًا ثابتًا، ويقوم ملف خدمة غير React باستيراده. في هذه الحالة، فكر في نقل الثابت إلى ملف منفصل واستيراده في كلا الملفين. هذا سيعيد تفعيل عمل التحديث السريع. يمكن حل الحالات الأخرى عادة بطريقة مماثلة.

مرونة الأخطاء

أخطاء الصياغة (Syntax Errors)

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

أخطاء التنفيذ (Runtime Errors)

إذا قمت بخطأ يؤدي إلى حدوث خطأ أثناء التنفيذ داخل مكونك، فستستقبلك نافذة سياقية. إصلاح الخطأ سيؤدي إلى إغلاق النافذة تلقائيًا، دون إعادة تحميل التطبيق.

سيتم الاحتفاظ بحالة المكون إذا لم يحدث الخطأ أثناء العرض. إذا حدث الخطأ أثناء العرض، سيعيد React تحميل تطبيقك باستخدام الكود المحدث.

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

القيود

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

  • لا يتم الحفاظ على الحالة المحلية لمكونات الفئة (فقط مكونات الدوال و Hooks تحافظ على الحالة).
  • قد يحتوي الملف الذي تقوم بتحريره على تصديرات أخرى بالإضافة إلى مكون React.
  • في بعض الأحيان، قد يصدر الملف نتيجة استدعاء مكون ذو ترتيب أعلى مثل HOC(WrappedComponent). إذا كان المكون المرجع عبارة عن فئة، فسيتم إعادة تعيين حالته.
  • دوال السهم المجهولة مثل export default () => <div />; تسبب عدم الحفاظ على حالة المكون المحلية في التحديث السريع. بالنسبة لقواعد الكود الكبيرة، يمكنك استخدام تحويل الكود name-default-component.

كلما تحولت قاعدة الكود الخاصة بك إلى مكونات دوال و Hooks، يمكنك توقع الحفاظ على الحالة في المزيد من الحالات.

نصائح

  • يحافظ التحديث السريع على حالة React المحلية في مكونات الدوال (و Hooks) افتراضيًا.
  • في بعض الأحيان قد ترغب في إجبار إعادة تعيين الحالة، وإعادة تحميل المكون. على سبيل المثال، يمكن أن يكون هذا مفيدًا إذا كنت تضبط رسوم متحركة تحدث فقط عند التحميل. للقيام بذلك، يمكنك إضافة // @refresh reset في أي مكان في الملف الذي تقوم بتحريره. هذا التوجيه محلي للملف، ويوجه التحديث السريع لإعادة تحميل المكونات المعرفة في هذا الملف في كل تحرير.
  • يمكنك وضع console.log أو debugger; في المكونات التي تقوم بتحريرها أثناء التطوير.
  • تذكر أن عمليات الاستيراد حساسة لحالة الأحرف. يمكن أن يفشل كل من التحديث السريع والكامل، عندما لا يتطابق استيرادك مع اسم الملف الفعلي. على سبيل المثال، './header' مقابل './Header'.

التحديث السريع و Hooks

عندما يكون ذلك ممكنًا، يحاول التحديث السريع الحفاظ على حالة مكونك بين التعديلات. على وجه الخصوص، تحافظ useState و useRef على قيمها السابقة طالما لم تقم بتغيير وسائطها أو ترتيب استدعاءات الـ Hook.

الـ Hooks ذات التبعيات - مثل useEffect و useMemo و useCallback - ستقوم دائمًا بالتحديث أثناء التحديث السريع. سيتم تجاهل قائمة تبعياتها أثناء حدوث التحديث السريع.

على سبيل المثال، عندما تقوم بتحرير useMemo(() => x * 2, [x]) إلى useMemo(() => x * 10, [x])، سيعيد التشغيل حتى لو لم يتغير x (التبعية). إذا لم يفعل React ذلك، فلن ينعكس تعديلك على الشاشة!

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

ومع ذلك، فإن كتابة كود مقاوم لإعادة تشغيل useEffect العرضية هو ممارسة جيدة حتى بدون التحديث السريع. سيجعل من الأسهل عليك إدخال تبعيات جديدة إليه لاحقًا وهو مفروض بواسطة وضع React الصارم (React Strict Mode)، والذي نوصي بشدة بتفعيله.