التحديث السريع (Fast Refresh)
التحديث السريع هو ميزة في React مدمجة مع Next.js تتيح لك إعادة تحميل صفحة المتصفح مع الحفاظ على الحالة المؤقتة من جانب العميل عند حفظ التغييرات في ملف. هذه الميزة مفعلة افتراضيًا في جميع تطبيقات Next.js بإصدار 9.4 أو أحدث. مع تفعيل التحديث السريع، يجب أن تكون معظم التعديلات مرئية في غضون ثانية.
كيفية العمل
- إذا قمت بتحرير ملف يصدّر فقط مكونات 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)، والذي نوصي بشدة بتفعيله.