React Router: التنقل البرمجي بدون ألم أو بطء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

التنقل في React: ليس مجرد نقرة على رابط

\n\n

هل تساءلت يومًا كيف تجعل React Router ينتقل إلى صفحة أخرى ليس بنقرة المستخدم، بل بأمر من الكود؟ على سبيل المثال، بعد إرسال نموذج بنجاح، أو تسجيل الدخول، أو ببساطة بعد 5 ثوانٍ؟ إذا كان الأمر كذلك، فقد وصلت إلى المكان الصحيح. سؤال "How can I programmatically navigate using React Router؟" هو أحد أكثر الأسئلة شيوعًا على Stack Overflow، وليس من دون سبب. يبدو الأمر بسيطًا، لكنه في الواقع يخفي العديد من المزالق، خاصة عندما يتعلق الأمر بالأداء.

\n\n

في هذه المقالة، لن نعرض فقط كيفية استخدام useNavigate. سنشرح كيفية القيام بذلك بشكل صحيح، بسرعة وبدون تأخير. ستتعرف على الأنماط التي تؤدي إلى تسرب الذاكرة، وتلك التي تؤدي إلى تنقل فائق السرعة. هيا بنا!

\n\n

الكلاسيكي: useNavigate — أداتك الرئيسية

\n\n

بدءًا من React Router v6، حل useNavigate محل useHistory القديم. هذا هو hook يقوم بإرجاع دالة navigate. يبدو الأمر كما يلي:

\n\n
import { useNavigate } from 'react-router-dom';\n\nfunction LoginButton() {\n  const navigate = useNavigate();\n\n  const handleLogin = () => {\n    // منطق تسجيل الدخول هنا\n    const user = { name: 'إيفان' };\n    // بعد النجاح — إعادة توجيه\n    navigate('/dashboard', { replace: true });\n  };\n\n  return <button onClick={handleLogin}>تسجيل الدخول</button>;\n}\n
\n\n

لاحظ المعامل { replace: true }. فهو يستبدل الإدخال الحالي في السجل، بدلاً من إضافة إدخال جديد. هذا أمر بالغ الأهمية لتسجيل الدخول، حتى لا يعود المستخدم إلى صفحة تسجيل الدخول.

\n\n

إلى أين يمكنك الانتقال؟

\n
    \n
  • مسار مطلق: navigate('/about')
  • \n
  • مسار نسبي: navigate('../settings')
  • \n
  • للخلف/للأمام في السجل: navigate(-1) أو navigate(2)
  • \n
\n\n

المستوى المتقدم: التنقل خارج المكونات

\n\n

ماذا لو كنت بحاجة إلى إجراء إعادة توجيه من دالة عادية، وليس داخل مكون React؟ على سبيل المثال، من action creator في Redux أو من axios-interceptor؟ لن يعمل hook useNavigate هنا — يتم استدعاء hooks فقط داخل المكونات الوظيفية.

\n\n

الحل: إنشاء مكون غلاف مخصص أو استخدام كائن الموجه العام. في React Router v6، يوجد مكون خاص RouterProvider و createBrowserRouter لهذا الغرض، ولكن هناك طريقة أبسط — حفظ مرجع إلى navigate في متغير.

\n\n
// router.js\nimport { createBrowserRouter, RouterProvider } from 'react-router-dom';\n\nexport const router = createBrowserRouter([...]);\n\n// navigation.js — وحدة منفصلة للتنقل\nlet navigateFunction = null;\n\nexport const setNavigate = (navigate) => {\n  navigateFunction = navigate;\n};\n\nexport const navigateTo = (path) => {\n  if (navigateFunction) {\n    navigateFunction(path);\n  } else {\n    console.warn('التنقل ليس جاهزًا بعد');\n  }\n};\n\n// App.js\nimport { useNavigate } from 'react-router-dom';\nimport { setNavigate } from './navigation';\nimport { useEffect } from 'react';\n\nfunction App() {\n  const navigate = useNavigate();\n\n  useEffect(() => {\n    setNavigate(navigate);\n  }, [navigate]);\n\n  return /* الكود الخاص بك */;\n}\n
\n\n

الآن من أي دالة (سواء من setTimeout أو من fetch) يمكنك استدعاء navigateTo('/home'). مريح؟ نعم. آمن؟ فقط إذا لم تنسَ مسح المرجع عند إلغاء تثبيت المكون.

\n\n

تحسين الأداء: لماذا تطبيقك بطيء؟

\n\n

التنقل البرمجي ليس مجرد استدعاء دالة. إنه مشغل لإعادة عرض كاملة للصفحة. وإذا كنت تفعل هذا

المدونات

توصيات الكتب