الدليل العملي لـ React Router: كل ما تحتاج إلى معرفته لإدارة التنقل في تطبيقات React
عند تطوير تطبيقات ويب باستخدام React، فأنت تحتاج إلى وسيلة منظمة لإدارة الصفحات والتنقل بينها دون إعادة تحميل الصفحة بالكامل. هنا يبرز دور React Router بوصفه أحد أهم الأدوات المعتمدة لبناء تجربة تنقل سلسة واحترافية داخل التطبيق.
في هذا الدليل العملي، ستتعرف على أبرز المفاهيم والمكونات والخطافات Hooks التي تحتاج إليها للعمل بكفاءة مع الحزمة react-router-dom في مشاريع الويب، مع شرح مبسط وأمثلة تساعدك على التطبيق مباشرة.

ما هو React Router ولماذا تحتاج إليه؟
يُستخدم React Router لتنظيم التنقل بين الصفحات أو الواجهات داخل تطبيقات React. وبدلاً من الاعتماد على الروابط التقليدية التي تعيد تحميل الصفحة، يتيح لك هذا الحل الانتقال بين المسارات Routes بشكل ديناميكي وسريع.
وتنقسم الحزمة إلى أكثر من إصدار بحسب بيئة الاستخدام:
react-router: النواة الأساسية للمكتبة.react-router-dom: مخصص لتطبيقات الويب.react-router-native: مخصص لتطبيقاتReact Native.
إذا كنت تبني موقعاً أو لوحة تحكم أو تطبيق ويب تفاعلي، فغالباً ستعتمد على react-router-dom.
تثبيت React Router DOM في المشروع
الخطوة الأولى هي تثبيت الحزمة المناسبة عبر npm أو yarn. المثال التالي يوضح أمر التثبيت باستخدام npm:
npm install react-router-dom
بعد التثبيت، يصبح بإمكانك استيراد المكونات التي تحتاج إليها داخل التطبيق والبدء في تعريف المسارات.
الإعداد الأساسي باستخدام BrowserRouter
المكون الأساسي الذي يبدأ منه كل شيء هو BrowserRouter. وظيفته احتواء شجرة المكونات التي ستتعامل مع نظام المسارات داخل التطبيق.
من الشائع إعادة تسمية BrowserRouter إلى Router عند الاستيراد لتسهيل القراءة:
import { BrowserRouter as Router } from 'react-router-dom';
export default function App() {
return (
<Router>
{/* routes go here */}
</Router>
);
}
من المهم أن تعرف أن أي بيانات أو أدوات مرتبطة بالتوجيه لا يمكن استخدامها خارج المكون Router. على سبيل المثال، لا يمكنك استخدام useHistory أو تعريف Route خارج هذا النطاق.
فهم مكون Route لتعريف الصفحات
يُستخدم المكون Route لربط مسار معين بمكون معين. أي أنك تخبر التطبيق: عند الوصول إلى هذا العنوان، اعرض هذا المكون.
import { BrowserRouter as Router, Route } from 'react-router-dom';
export default function App() {
return (
<Router>
<Route path="/about" component={About} />
</Router>
);
}
function About() {
return <>about</>;
}
أهم الخصائص المستخدمة هنا:
path: يحدد عنوان المسار مثل/about.component: يحدد المكون الذي سيتم عرضه.render: بديل مرن يسمح بإضافة منطق شرطي قبل العرض.
يمكنك أيضاً استخدام render إذا كنت تحتاج إلى تنفيذ منطق خاص:
import { BrowserRouter as Router, Route } from 'react-router-dom';
export default function App() {
return (
<Router>
<Route path="/" render={() => <Home />} />
<Route path="/about" component={About} />
</Router>
);
}
function Home() {
return <>home</>;
}
function About() {
return <>about</>;
}
كما يمكن تمرير المكون المطلوب بصفته ابناً مباشراً داخل Route بدلاً من استخدام component أو render.
عرض عناصر ثابتة في جميع الصفحات
إذا كنت تريد عرض عنصر مثل شريط التنقل Navbar في كل الصفحات، فضعه داخل Router ولكن خارج مجموعة المسارات الأساسية:
import { BrowserRouter as Router, Route } from 'react-router-dom';
export default function App() {
return (
<Router>
<Navbar />
<Route path="/" component={Home} />
<Route path="/about" component={About} />
</Router>
);
}
استخدام Switch لتجنب عرض أكثر من صفحة
عند تعريف أكثر من مسار، قد تلاحظ أن بعض الصفحات تُعرض معاً بسبب تطابق المسارات جزئياً، خاصة عند استخدام المسار /. لحل هذه المشكلة، نستخدم الخاصية exact مع المكون Switch.
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
export default function App() {
return (
<Router>
<Navbar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
</Router>
);
}
المكون Switch يبحث بين المسارات الأبناء ويعرض أول مسار يطابق الرابط الحالي فقط، وهذا هو السلوك المطلوب في معظم تطبيقات الويب.
إنشاء صفحة 404 للمسارات غير الموجودة
من الممارسات الضرورية تحسين تجربة المستخدم عند زيارة رابط غير موجود. يمكنك إنشاء مسار شامل باستخدام النجمة * لعرض صفحة مخصصة للحالات غير المعروفة:
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
export default function App() {
return (
<Router>
<Navbar />
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="*" component={NotFound} />
</Switch>
</Router>
);
}
function NotFound() {
return <>You have landed on a page that doesn't exist</>;
}
هذه الخطوة مفيدة لتحسين سهولة الاستخدام وتقليل ارتباك الزوار عند الوصول إلى صفحات غير متاحة.
التنقل داخل التطبيق باستخدام Link
بدلاً من تعديل الرابط يدوياً من المتصفح، يمكنك استخدام المكون Link لإنشاء روابط داخلية تنقل المستخدم بين الصفحات بسلاسة.
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
function Navbar() {
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
);
}
تستقبل الخاصية to المسار المطلوب الانتقال إليه، ويمكنك تنسيق الرابط مثل أي مكون React عادي.
تمييز الرابط النشط بواسطة NavLink
إذا كنت تريد معرفة الصفحة الحالية بصرياً، فاستخدم NavLink. هذا المكون يتيح تطبيق نمط خاص للرابط النشط، سواء عبر activeStyle أو activeClassName.
import { BrowserRouter as Router, Switch, Route, NavLink } from 'react-router-dom';
function Navbar() {
return (
<nav>
<NavLink activeStyle={{ fontWeight: 'bold', color: 'red' }} to="/">
Home
</NavLink>
<NavLink activeClassName="active" to="/about">
About
</NavLink>
</nav>
);
}
هذا الأسلوب يرفع من جودة تجربة المستخدم، خاصة في المواقع متعددة الأقسام أو لوحات التحكم.
إعادة التوجيه باستخدام Redirect
أحياناً تحتاج إلى نقل المستخدم تلقائياً إلى صفحة أخرى، مثل إعادة الزائر غير المسجل إلى صفحة تسجيل الدخول. هنا يأتي دور المكون Redirect.
import { BrowserRouter as Router, Switch, Route, Redirect } from 'react-router-dom';
export default function App() {
return (
<Router>
<Switch>
<Route exact path="/" component={Home} />
<PrivateRoute path="/hidden" component={Hidden} />
</Switch>
</Router>
);
}
function PrivateRoute({ component: Component, ...rest }) {
const isAuth = useAuth();
return (
<Route
{...rest}
render={(props) =>
isAuth ? <Component {...props} /> : <Redirect to="/" />
}
/>
);
}
هذا النمط شائع في حماية الصفحات الخاصة وإنشاء ما يُعرف باسم Private Route.
التحكم البرمجي في التنقل عبر useHistory
من أقوى الأدوات في React Router الخطاف useHistory، إذ يمنحك الوصول إلى معلومات التنقل الحالية، مع إمكانية نقل المستخدم برمجياً إلى مسار آخر.
import { useHistory } from 'react-router-dom';
function About() {
const history = useHistory();
return (
<>
<h1>The about page is on: {history.location.pathname}</h1>
<button onClick={() => history.push('/')}>Go to home page</button>
</>
);
}
أبرز الاستخدامات:
history.location: للحصول على معلومات الرابط الحالي.history.push(): للانتقال إلى صفحة جديدة مع حفظ السجل.history.replace(): للانتقال مع استبدال الصفحة الحالية في السجل.
ويُعد هذا مفيداً بعد تسجيل الدخول أو تسجيل الخروج أو إتمام إجراء معين داخل التطبيق.
الحصول على بيانات الرابط الحالي باستخدام useLocation
إذا كنت تحتاج فقط إلى معلومات المسار الحالي دون التحكم في السجل، فإن useLocation هو الخيار الأبسط.
import { useLocation } from 'react-router-dom';
function About() {
const location = useLocation();
return (
<>
<h1>The about page is on: {location.pathname}</h1>
</>
);
}
يوفر هذا الخطاف كائناً يحتوي على معلومات مثل pathname وبيانات إضافية مرتبطة بالرابط الحالي.
المسارات الديناميكية واستخدام useParams
تُستخدم المسارات الديناميكية عندما يكون جزء من الرابط متغيراً، مثل روابط المقالات أو المنتجات. على سبيل المثال، إذا كانت لديك صفحة لمقال مدونة، يمكنك تعريف المسار بهذه الطريقة:
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
export default function App() {
return (
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/blog/:postSlug" component={BlogPost} />
</Switch>
</Router>
);
}
الجزء :postSlug يمثل متغيراً ديناميكياً. وللوصول إلى قيمته داخل المكون، نستخدم الخطاف useParams:
import React from 'react';
import { BrowserRouter as Router, Switch, Route, useParams } from 'react-router-dom';
function BlogPost() {
const [post, setPost] = React.useState(null);
const { postSlug } = useParams();
React.useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/posts/${postSlug}`)
.then((res) => res.json())
.then((data) => setPost(data));
}, [postSlug]);
if (!post) return null;
return (
<>
<h1>{post.title}</h1>
<p>{post.description}</p>
</>
);
}
بهذه الطريقة يمكنك جلب بيانات مختلفة لكل صفحة اعتماداً على قيمة postSlug الموجودة في الرابط.
التحقق من تطابق المسار بواسطة useRouteMatch
عندما تحتاج إلى معرفة ما إذا كان المكون الحالي يتوافق مع مسار معين، يمكنك استخدام useRouteMatch. يفيد ذلك في الحالات التي ترغب فيها بإظهار أو إخفاء جزء معين من الواجهة حسب المسار الحالي.
import { useRouteMatch } from 'react-router-dom';
function BlogPost() {
const isBlogPostRoute = useRouteMatch('/blog/:postSlug');
}
إذا وُجد تطابق، يمكنك بناء منطق مرن للتحكم في سلوك الواجهة أو المحتوى المعروض.
أفضل ممارسات عند استخدام React Router
- ضع
Routerفي مستوى علوي ليغطي التطبيق بالكامل. - استخدم
Switchعندما تريد عرض صفحة واحدة فقط لكل رابط. - أضف صفحة
404دائماً لتحسين تجربة المستخدم. - اعتمد على
NavLinkإذا كنت بحاجة إلى تمييز الصفحة النشطة. - استخدم
useParamsمع المسارات الديناميكية لعرض محتوى مخصص. - استفد من
useHistoryوuseLocationللتحكم الدقيق في تجربة التنقل.
متى يصبح React Router خياراً أساسياً؟
إذا كان تطبيقك يحتوي على أكثر من صفحة، أو لوحة تحكم، أو صفحات مقالات، أو نظام تسجيل دخول، فإن استخدام React Router ليس مجرد إضافة مفيدة، بل عنصر أساسي في بنية التطبيق. فهو يساعدك على تنظيم الواجهات، وفصل المسؤوليات، وتحسين تجربة الاستخدام بشكل واضح.

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