DEV Community

banti kevat
banti kevat

Posted on • Originally published at itinfohubs.blogspot.com

React me Multiple Contexts Kaise Combine Karein

React me Multiple Contexts Kaise Combine Karein (in Hindi)
React me multiple contexts kaise combine karein? Is practical guide me nested providers ki problem ko dynamic compose method se solve karna seekhein.

दोस्तों, क्या आप भी अपने ReactJS एप्लीकेशन में Auth, Theme, और Language जैसी कई Global States को मैनेज करने के लिए अलग-अलग React Context Providers बनाते हैं? और क्या आपका App.jsx फ़ाइल धीरे-धीरे "Provider Pyramid of Doom" बनता जा रहा है? जब एक के अंदर एक, 10 Providers नेस्ट हो जाते हैं, तो कोड को पढ़ना और मेंटेन करना किसी भयानक सपने जैसा हो जाता है।

चिंता मत कीजिए! आज आपका यह सीनियर डेवलपर दोस्त आपको एक ऐसा बेहतरीन और क्लीन तरीका सिखाएगा जिससे आप चुटकियों में React me multiple contexts kaise combine karein का हल ढूंढ लेंगे। हम एक Dynamic Context Composer Pattern बनाएंगे, जो आपके कोड को नीट, क्लीन और सुपर-स्केलेबल बना देगा। तो चलिए, चाय की चुस्की लेते हैं और कोड की गहराई में उतरते हैं!

⚡ Quick Answer: React me multiple contexts kaise combine karein? Iska sabse best tarika ek custom Context Composer Component banana hai. Yeh component JavaScript ke reduceRight() function ka use karke sabhi context providers ko dynamically nest karta hai. Isse aapka Component Tree bilkul clean rehta hai aur readable code milta hai.

---

React Context API क्या है और Provider Nesting की समस्या क्या है?

जब हम MERN Stack में बड़े स्केलेबल प्रोजेक्ट्स पर काम करते हैं, तो Prop Drilling से बचने के लिए React Context API हमारा सबसे बड़ा सहारा होती है। लेकिन समस्या तब शुरू होती है जब हमारे पास अलग-अलग फीचर्स के लिए अलग-अलग Contexts होते हैं।

मान लीजिए आपके पास ये सब अलग-अलग Providers हैं:

  • AuthContext: यूज़र के लॉगिन स्टेट और टोकन्स के लिए।
  • ThemeContext: डार्क और लाइट मोड थीम के लिए।
  • LanguageContext: Multi-language (i18n) सपोर्ट के लिए।
  • NotificationContext: टोस्ट मैसेजेस और अलर्ट्स के लिए।

सामान्य तौर पर, आप इन्हें अपने App.jsx में कुछ इस तरह लिखते हैं:

function App() {
  return (
    <AuthProvider>
      <ThemeProvider>
        <LanguageProvider>
          <NotificationProvider>
            <MainLayout />
          </NotificationProvider>
        </LanguageProvider>
      </ThemeProvider>
    </AuthProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

ध्यान देने वाली बात ये है कि इसे हम "Pyramid of Doom" या "Provider Nesting Hell" कहते हैं। जैसे-जैसे आपका ऐप बढ़ेगा, यह ट्री और बड़ा होता जाएगा। अगर कल को आपको एक नया CartContext या UserPreferenceContext जोड़ना पड़ा, तो आपको फिर से इस दलदल में घुसना पड़ेगा।

---

React में Multiple Contexts को Nest करने के नुकसान क्या हैं?

इससे पहले कि हम समाधान पर बात करें, हमें यह समझना होगा कि इस तरह के Nesting पैटर्न से क्या-क्या नुकसान होते हैं:

  1. खराब Readability: कोड देखने में बहुत उलझा हुआ लगता है। नए डेवलपर्स के लिए यह समझना मुश्किल हो जाता है कि डेटा का फ्लो किस दिशा में जा रहा है।
  2. Maintenance में परेशानी: अगर आपको किसी Provider का आर्डर बदलना पड़े (जैसे, Language Provider को Auth Provider के ऊपर करना पड़े), तो आपको बहुत संभलकर ब्रैकेट मैच करने पड़ते हैं। जरा सी गलती से Syntax error आ सकता है।
  3. Testing में असुविधा: जब आप किसी सिंगल कंपोनेंट का Unit Test लिख रहे होते हैं, तो आपको उसके ऊपर के सभी Providers को मॉक (Mock) करना पड़ता है, जो बहुत थकाऊ काम है।

---

Component Tree का Structural Flow (Architecture Diagram)

चलिए एक बार डायग्राम की मदद से समझते हैं कि ट्रेडिशनल नेस्टिंग और हमारे कंपोजर पैटर्न में क्या अंतर है।

🏗️ Context Architecture Flow

Nested Providers (Nesting Hell)

Context Composer

Clean Component Tree

Diagram: Nested Providers को हटाकर Dynamic Array Composition की ओर बढ़ना।

---

React me Multiple Contexts Kaise Combine Karein? Step-by-Step implementation

अब हम अपना जादू शुरू करेंगे। हम एक ऐसा रियूजेबल कंपोनेंट बनाएंगे जिसे हम ContextComposer कहेंगे। यह कंपोनेंट एक Array लेगा (जिसमें हमारे सभी Providers होंगे) और उन्हें डायनामिकली एक दूसरे के अंदर नेस्ट कर देगा।

इसके लिए हम जावास्क्रिप्ट के ताकतवर एरे मेथड reduceRight() का उपयोग करेंगे। अगर आप इसके बारे में नहीं जानते, तो घबराइए मत, मैं आपको बिल्कुल आसान शब्दों में समझाऊंगा।

Step 1: पहले 3 डमी Contexts और Providers तैयार करते हैं

चलिए सबसे पहले तीन बुनियादी Contexts बना लेते हैं ताकि हमारे पास कंबाइन करने के लिए असली माल-मसाला मौजूद हो।

1. Auth Context (AuthContext.jsx)

import React, { createContext, useState, useContext } from 'react';

const AuthContext = createContext(null);

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState({ name: "Amit Kumar", role: "Senior Developer" });

  const login = (userData) => setUser(userData);
  const logout = () => setUser(null);

  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) throw new Error("useAuth must be used within AuthProvider");
  return context;
};
Enter fullscreen mode Exit fullscreen mode

2. Theme Context (ThemeContext.jsx)

import React, { createContext, useState, useContext } from 'react';

const ThemeContext = createContext(null);

export const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState("dark");

  const toggleTheme = () => {
    setTheme((prev) => (prev === "light" ? "dark" : "light"));
  };

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

export const useTheme = () => {
  const context = useContext(ThemeContext);
  if (!context) throw new Error("useTheme must be used within ThemeProvider");
  return context;
};
Enter fullscreen mode Exit fullscreen mode

3. Language Context (LangContext.jsx)

import React, { createContext, useState, useContext } from 'react';

const LangContext = createContext(null);

export const LangProvider = ({ children }) => {
  const [lang, setLang] = useState("Hindi");

  const changeLanguage = (newLang) => setLang(newLang);

  return (
    <LangContext.Provider value={{ lang, changeLanguage }}>
      {children}
    </LangContext.Provider>
  );
};

export const useLang = () => {
  const context = useContext(LangContext);
  if (!context) throw new Error("useLang must be used within LangProvider");
  return context;
};
Enter fullscreen mode Exit fullscreen mode

---

Step 2: Context Composer Component बनाना (The Magic Engine)

अब समय आ गया है उस जादुई कंपोनेंट को बनाने का जो इन तीनों Providers को एक झटके में कंबाइन कर देगा। हम एक फ़ाइल बनाएंगे जिसका नाम होगा ContextComposer.jsx

import React from 'react';

export const ContextComposer = ({ providers, children }) => {
  return (
    <>
      {providers.reduceRight((accumulator, CurrentProvider) => {
        return <CurrentProvider>{accumulator}</CurrentProvider>;
      }, children)}
    </>
  );
};
Enter fullscreen mode Exit fullscreen mode

यह कोड कैसे काम करता है? चलिए आसान शब्दों में समझें:

  • reduceRight() एरे के आखिरी एलिमेंट से शुरू करता है और पहले एलिमेंट की तरफ बढ़ता है।
  • यहाँ children हमारा शुरुआती Accumulator (आरंभिक वैल्यू) है।
  • सबसे पहले यह आखिरी Provider को लेता है और उसके अंदर children को डाल देता है।
  • फिर उसके पिछले Provider को लेता है और पूरे स्ट्रक्चर को उसके अंदर रैप कर देता है।
  • अंत में, हमें एक पूरी तरह से नेस्टेड कम्पोनेंट ट्री मिल जाता है, बिना हमारे हाथ-पैर हिलाए!

---

Step 3: App.jsx में Providers को Combine करना

अब देखिए कि हमारा App.jsx कितना साफ़-सुथरा और खूबसूरत दिखने वाला है।

import React from 'react';
import { AuthProvider } from './context/AuthContext';
import { ThemeProvider } from './context/ThemeContext';
import { LangProvider } from './context/LangContext';
import { ContextComposer } from './components/ContextComposer';
import MainDashboard from './components/MainDashboard';

function App() {
  // सभी Providers को एक सादे एरे में रखें
  const appProviders = [
    AuthProvider,
    ThemeProvider,
    LangProvider
  ];

  return (
    <ContextComposer providers={appProviders}>
      <MainDashboard />
    </ContextComposer>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

देखा आपने? कोई "Pyramid of Doom" नहीं, कोई उलझा हुआ कोड नहीं। बस एक सिंपल एरे, और आपका काम हो गया! अगर भविष्य में आपको नया Provider जोड़ना हो, तो बस उसे appProviders एरे में डाल दीजिए। काम खत्म!

---

Performance Optimization: क्या Context Re-renders को रोका जा सकता है?

मेरे प्यारे दोस्तों, एक बात का हमेशा ध्यान रखें। React Context API कोई पूर्ण स्टेट मैनेजमेंट टूल नहीं है जैसे Redux या Zustand। जब भी किसी Context की वैल्यू बदलती है, तो उस Context को इस्तेमाल करने वाले सभी कंपोनेंट्स दोबारा रेंडर (re-render) होते हैं।

जब हम React me multiple contexts kaise combine karein का तरीका अपनाते हैं, तो परफॉरमेंस को लेकर कुछ बेस्ट प्रैक्टिसेज का ध्यान रखना बेहद ज़रूरी है:

  1. Keep Contexts Segregated (अलग-अलग रखें): एक ही "Super Context" बनाने की गलती कभी न करें जिसमें सब कुछ हो। थीम का डेटा अलग रखें, ऑथ का अलग। हमारे कंपोजर पैटर्न का सबसे बड़ा फायदा यही है कि यह अलग-अलग छोटे कॉन्टेक्स्ट्स को मिलाकर एक बनाता है, जिससे अनचाहे रेंडर्स केवल उसी सब-ट्री में होते हैं जहाँ बदलाव हुआ है।
  2. Memoize the Context Values: हमेशा अपने Provider के भीतर वैल्यूज को पास करते समय useMemo और useCallback का इस्तेमाल करें।

चलिए मैं आपको दिखाता हूँ कि कैसे आप अपने Providers की वैल्यूज को ऑप्टिमाइज़ कर सकते हैं:

import React, { createContext, useState, useMemo, useCallback } from 'react';

export const OptimizedContext = createContext(null);

export const OptimizedProvider = ({ children }) => {
  const [data, setData] = useState({ clicks: 0, user: "John" });

  const increment = useCallback(() => {
    setData((prev) => ({ ...prev, clicks: prev.clicks + 1 }));
  }, []);

  // useMemo का उपयोग करके ऑब्जेक्ट को री-क्रिएट होने से बचाएं
  const contextValue = useMemo(() => ({
    data,
    increment
  }), [data, increment]);

  return (
    <OptimizedContext.Provider value={contextValue}>
      {children}
    </OptimizedContext.Provider>
  );
};
Enter fullscreen mode Exit fullscreen mode

---

Common Errors और Debugging Tips

जब आप पहली बार Providers को कंबाइन करेंगे, तो कुछ सामान्य गलतियां हो सकती हैं। आइए देखते हैं उन्हें कैसे पहचानें और error को कैसे दूर करें:

1. "Uncaught TypeError: Cannot read properties of undefined"

यह तब होता है जब आप किसी कंपोनेंट में useAuth() जैसी कस्टम हुक कॉल करते हैं, लेकिन वह कंपोनेंट उस Provider के बाहर स्थित होता है।

समाधान: सुनिश्चित करें कि आपका कंपोनेंट ContextComposer के नीचे (children के रूप में) ही रेंडर हो रहा हो। साथ ही, अपनी हुक्स में चेक लगाना न भूलें जैसा हमने ऊपर किया था: if (!context) throw new Error(...)

2. गलत आर्डरिंग (Ordering Issues)

कभी-कभी एक Provider दूसरे Provider के डेटा पर निर्भर करता है। उदाहरण के लिए, CartProvider को यूजर की आईडी जानने के लिए AuthProvider की आवश्यकता हो सकती है।

समाधान: अपने appProviders एरे में आर्डर का विशेष ध्यान रखें। जो Provider पहले चाहिए, उसे एरे में पहले रखें। चूंकि हमारा कंपोजर reduceRight() का उपयोग करता है, इसलिए एरे में ऊपर लिखा गया Provider कंपोनेंट ट्री में सबसे बाहर (Parent) रहेगा।

---

Context Composer vs Redux: आपके प्रोजेक्ट के लिए क्या सही है?

बहुत से डेवलपर्स मुझसे पूछते हैं कि "भाई, जब हम इस तरह से मल्टीपल कॉन्टेक्स्ट्स को कंबाइन कर सकते हैं, तो हमें Redux या Zustand की क्या ज़रूरत है?"

आइए इस तुलना तालिका (Comparison Table) से इसे अच्छे से समझते हैं:

Feature Combined Context API Zustand / Redux
Setup Complexity बहुत कम (No extra libraries needed) मध्यम से उच्च (Boilerplate code की जरूरत)
Performance (Large Scale) मध्यम (Frequent updates पर re-render इश्यूज) बेहतरीन (Selective state subscription)
Learning Curve बहुत आसान (React built-in features) मध्यम (Flux architecture समझना पड़ता है)
Debugging Tools React DevTools (Basic) Redux DevTools (Advanced state tracing)

मेरा मशवरा: अगर आप एक छोटा या मध्यम स्तर का प्रोजेक्ट बना रहे हैं, तो Combined Context API आपके लिए सबसे बेस्ट और लाइटवेट उपाय है। लेकिन अगर आप बहुत बड़ा सोशल मीडिया ऐप या ई-कॉमर्स प्लेटफॉर्म बना रहे हैं जहां प्रति सेकंड सैकड़ों स्टेट अपडेट्स होते हैं, तो आपको Zustand या Redux की तरफ जाना चाहिए। अधिक जानकारी के लिए आप React official documentation भी देख सकते हैं।

---

तो दोस्तों, आज हमने सीखा कि कैसे हम React में "Provider Nesting Hell" से छुटकारा पा सकते हैं और एक साफ-सुथरा, स्केलेबल कंपोजर पैटर्न बना सकते हैं। जावास्क्रिप्ट के reduceRight की मदद से हमने जटिल कोड को कितना आसान बना दिया!

अब आपकी बारी है! अपने मौजूदा प्रोजेक्ट में जाइए, उस गंदे दिख रहे App.jsx को साफ़ कीजिए, और इस पैटर्न को लागू कीजिए। अगर कोई भी शंका या सवाल हो, तो नीचे कमेंट बॉक्स खुला है। आपका यह दोस्त हमेशा आपकी मदद के लिए तैयार है। हैप्पी कोडिंग!

---

Frequently Asked Questions (FAQs)

Q1: क्या Multiple Contexts को Combine करने से Performance पर कोई बुरा असर पड़ता है?
जी नहीं, बिल्कुल नहीं! बल्कि यह आपके कोड को व्यवस्थित रखता है। परफॉरमेंस पर असर केवल तभी पड़ता है जब आपके किसी एक Context का स्टेट बार-बार अपडेट हो रहा हो और आपने useMemo का उपयोग न किया हो। कंबाइन करने की प्रोसेस स्वयं कोई एक्स्ट्रा ओवरहेड पैदा नहीं करती।
Q2: Context Composer में Providers का Order (क्रम) क्यों महत्वपूर्ण है?
ऑर्डर इसलिए जरूरी है क्योंकि कभी-कभी एक Provider दूसरे के डेटा पर निर्भर करता है। उदाहरण के लिए, आपके API Context को User Token की जरूरत हो सकती है जो Auth Context से आता है। ऐसे में AuthProvider को हमेशा APIProvider से ऊपर (यानी एरे में पहले) होना चाहिए।
Q3: क्या हम कंबाइंड प्रोवाइडर्स के साथ Dynamic States को भी पास कर सकते हैं?
हाँ, बिल्कुल। Providers के अंदर की स्टेट्स सामान्य रूप से काम करती रहेंगी। कंपोजर सिर्फ उनके रेंडरिंग स्ट्रक्चर (Nesting) को सुधारता है, उनके अंदरूनी स्टेट मैनेजमेंट लॉजिक में कोई बदलाव नहीं करता।
Q4: क्या इस पैटर्न का उपयोग Next.js में भी किया जा सकता है?
हाँ, आप इसे Next.js के क्लाइंट कंपोनेंट्स ('use client') में पूरी तरह से उपयोग कर सकते हैं। सर्वर कंपोनेंट्स में डायरेक्ट Context का उपयोग नहीं होता, इसलिए वहां इसकी जरूरत नहीं पड़ेगी।
Q5: क्या हमें हर छोटे स्टेट के लिए नया Context बनाना चाहिए?
नहीं, ऐसा करने से बचें। केवल उन्हीं ग्लोबल वैल्यूज के लिए Context बनाएं जो पूरे ऐप में या कई कंपोनेंट लेयर्स में शेयर की जा रही हों। लोकल स्टेट्स के लिए सामान्य useState या useReducer ही सबसे बेस्ट हैं।

---

Top comments (0)