العربية

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

سياق React: دليل شامل

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

فهم المشكلة: حفر الخصائص (Prop Drilling)

في تطبيقات React المعقدة، قد تواجه مشكلة "حفر الخصائص" (prop drilling). يحدث هذا عندما تحتاج إلى تمرير البيانات من مكون أب إلى مكون ابن متداخل بعمق. للقيام بذلك، يجب عليك تمرير البيانات عبر كل مكون وسيط، حتى لو كانت تلك المكونات لا تحتاج إلى البيانات نفسها. يمكن أن يؤدي هذا إلى:

خذ بعين الاعتبار هذا المثال المبسط:


function App() {
  const user = { name: 'Alice', theme: 'dark' };
  return (
    <Layout user={user} />
  );
}

function Layout({ user }) {
  return (
    <Header user={user} />
  );
}

function Header({ user }) {
  return (
    <Navigation user={user} />
  );
}

function Navigation({ user }) {
  return (
    <Profile user={user} />
  );
}

function Profile({ user }) {
  return (
    <p>أهلاً بك، {user.name}!
السمة: {user.theme}</p>
  );
}

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

تقديم سياق React

يوفر سياق React طريقة لتجنب حفر الخصائص عن طريق جعل البيانات متاحة لأي مكون في شجرة فرعية دون تمريرها بشكل صريح عبر الخصائص. يتكون من ثلاثة أجزاء رئيسية:

متى يجب استخدام سياق React

يعتبر سياق React مفيدًا بشكل خاص لمشاركة البيانات التي تعتبر "عامة" لشجرة من مكونات React. قد يشمل هذا:

اعتبارات هامة:

كيفية استخدام سياق React: مثال عملي

لنعد إلى مثال حفر الخصائص ونحله باستخدام سياق React.

1. إنشاء سياق

أولاً، قم بإنشاء سياق باستخدام React.createContext(). سيحتوي هذا السياق على بيانات المستخدم.


// UserContext.js
import React from 'react';

const UserContext = React.createContext(null); // يمكن أن تكون القيمة الافتراضية null أو كائن مستخدم أولي

export default UserContext;

2. إنشاء مزود

بعد ذلك، قم بتغليف جذر تطبيقك (أو الشجرة الفرعية ذات الصلة) بـ UserContext.Provider. قم بتمرير كائن user كخاصية value إلى المزود.


// App.js
import React from 'react';
import UserContext from './UserContext';
import Layout from './Layout';

function App() {
  const user = { name: 'Alice', theme: 'dark' };
  return (
    <UserContext.Provider value={user}>
      <Layout />
    </UserContext.Provider>
  );
}

export default App;

3. استهلاك السياق

الآن، يمكن لمكون Profile الوصول إلى بيانات user مباشرة من السياق باستخدام خطاف useContext. لا مزيد من حفر الخصائص!


// Profile.js
import React, { useContext } from 'react';
import UserContext from './UserContext';

function Profile() {
  const user = useContext(UserContext);

  return (
    <p>أهلاً بك، {user.name}!
السمة: {user.theme}</p>
  );
}

export default Profile;

لم تعد المكونات الوسيطة (Layout، Header، وNavigation) بحاجة إلى استقبال خاصية user.


// Layout.js, Header.js, Navigation.js
import React from 'react';

function Layout({ children }) {
  return (
    <div>
      <Header />
      <main>{children}</main>
    </div>
  );
}

function Header() {
  return (<Navigation />);
}

function Navigation() {
  return (<Profile />);
}

export default Layout;

الاستخدام المتقدم وأفضل الممارسات

1. دمج السياق مع useReducer

لإدارة الحالة الأكثر تعقيدًا، يمكنك دمج سياق React مع خطاف useReducer. يتيح لك هذا إدارة تحديثات الحالة بطريقة أكثر قابلية للتنبؤ والصيانة. يوفر السياق الحالة، ويتولى المخفض (reducer) انتقالات الحالة بناءً على الإجراءات المرسلة (dispatched actions).


// ThemeContext.js
import React, { createContext, useReducer } from 'react';

const ThemeContext = createContext();

const initialState = { theme: 'light' };

const themeReducer = (state, action) => {
  switch (action.type) {
    case 'TOGGLE_THEME':
      return { ...state, theme: state.theme === 'light' ? 'dark' : 'light' };
    default:
      return state;
  }
};

function ThemeProvider({ children }) {
  const [state, dispatch] = useReducer(themeReducer, initialState);

  return (
    <ThemeContext.Provider value={{ ...state, dispatch }}>
      {children}
    </ThemeContext.Provider>
  );
}

export { ThemeContext, ThemeProvider };



// ThemeToggle.js
import React, { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

function ThemeToggle() {
  const { theme, dispatch } = useContext(ThemeContext);

  return (
    <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}>
      تبديل السمة (الحالية: {theme})
    </button>
  );
}

export default ThemeToggle;



// App.js
import React from 'react';
import { ThemeProvider } from './ThemeContext';
import ThemeToggle from './ThemeToggle';

function App() {
  return (
    <ThemeProvider>
      <div>
        <ThemeToggle />
      </div>
    </ThemeProvider>
  );
}

export default App;

2. سياقات متعددة

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

3. تحسين الأداء

كما ذكرنا سابقًا، يمكن أن تؤدي تغييرات السياق إلى إعادة العرض في المكونات المستهلكة. لتحسين الأداء، ضع في اعتبارك ما يلي:

4. استخدام الخطافات المخصصة للوصول إلى السياق

قم بإنشاء خطافات مخصصة لتغليف منطق الوصول إلى قيم السياق وتحديثها. هذا يحسن من قابلية قراءة الكود وصيانته. على سبيل المثال:


// useTheme.js
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';

function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('يجب استخدام useTheme داخل ThemeProvider');
  }
  return context;
}

export default useTheme;



// MyComponent.js
import React from 'react';
import useTheme from './useTheme';

function MyComponent() {
  const { theme, dispatch } = useTheme();

  return (
    <div>
      السمة الحالية: {theme}
      <button onClick={() => dispatch({ type: 'TOGGLE_THEME' })}>
        تبديل السمة
      </button>
    </div>
  );
}

export default MyComponent;

الأخطاء الشائعة التي يجب تجنبها

بدائل لسياق React

بينما يعد سياق React أداة قيمة، إلا أنه ليس دائمًا الحل الأفضل. ضع في اعتبارك هذه البدائل:

الخاتمة

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