ગુજરાતી

ક્રાંતિકારી રીએક્ટ `use` હૂક માટેની એક વિસ્તૃત માર્ગદર્શિકા. પ્રોમિસ અને કોન્ટેક્સ્ટને હેન્ડલ કરવા પર તેની અસર જાણો, જેમાં રિસોર્સ વપરાશ, પર્ફોર્મન્સ અને શ્રેષ્ઠ પ્રેક્ટિસનું વિશ્લેષણ છે.

રીએક્ટના `use` હૂકને સમજવું: પ્રોમિસ, કોન્ટેક્સ્ટ અને રિસોર્સ મેનેજમેન્ટમાં ઊંડાણપૂર્વક અભ્યાસ

રીએક્ટનું ઇકોસિસ્ટમ સતત વિકસિત થઈ રહ્યું છે, જે ડેવલપરના અનુભવને સતત સુધારે છે અને વેબ પર શું શક્ય છે તેની સીમાઓને આગળ ધપાવે છે. ક્લાસથી લઈને હૂક્સ સુધી, દરેક મોટા ફેરફારે આપણે યુઝર ઇન્ટરફેસ કેવી રીતે બનાવીએ છીએ તે મૂળભૂત રીતે બદલી નાખ્યું છે. આજે, આપણે આવા જ એક પરિવર્તનની ટોચ પર ઊભા છીએ, જેની જાહેરાત એક ભ્રામક રીતે સરળ દેખાતા ફંક્શન દ્વારા કરવામાં આવી છે: `use` હૂક.

વર્ષોથી, ડેવલપર્સ એસિંક્રોનસ ઓપરેશન્સ અને સ્ટેટ મેનેજમેન્ટની જટિલતાઓ સાથે સંઘર્ષ કરી રહ્યા છે. ડેટા ફેચિંગનો અર્થ ઘણીવાર `useEffect`, `useState`, અને લોડિંગ/એરર સ્ટેટ્સનું ગૂંચવણભર્યું જાળું હતું. કોન્ટેક્સ્ટનો ઉપયોગ, શક્તિશાળી હોવા છતાં, દરેક કન્ઝ્યુમરમાં રી-રેન્ડર ટ્રિગર કરવાની નોંધપાત્ર પર્ફોર્મન્સની ખામી સાથે આવતો હતો. `use` હૂક એ રીએક્ટનો આ લાંબા સમયથી ચાલતા પડકારોનો સુંદર જવાબ છે.

આ વ્યાપક માર્ગદર્શિકા વ્યાવસાયિક રીએક્ટ ડેવલપર્સના વૈશ્વિક સમુદાય માટે બનાવવામાં આવી છે. આપણે `use` હૂકમાં ઊંડાણપૂર્વક જઈશું, તેની કાર્યપ્રણાલીનું વિચ્છેદન કરીશું અને તેના બે મુખ્ય પ્રારંભિક ઉપયોગોનું અન્વેષણ કરીશું: પ્રોમિસને અનરેપ કરવું અને કોન્ટેક્સ્ટમાંથી વાંચવું. વધુ મહત્ત્વની વાત એ છે કે, આપણે રિસોર્સના વપરાશ, પર્ફોર્મન્સ અને એપ્લિકેશન આર્કિટેક્ચર પરના ગહન પ્રભાવોનું વિશ્લેષણ કરીશું. તમારી રીએક્ટ એપ્લિકેશન્સમાં તમે એસિંક્રોનસ લોજિક અને સ્ટેટને કેવી રીતે હેન્ડલ કરો છો તે વિશે પુનર્વિચાર કરવા માટે તૈયાર થાઓ.

એક મૂળભૂત પરિવર્તન: `use` હૂકને શું અલગ બનાવે છે?

આપણે પ્રોમિસ અને કોન્ટેક્સ્ટમાં ઊંડા ઉતરીએ તે પહેલાં, `use` આટલું ક્રાંતિકારી કેમ છે તે સમજવું મહત્ત્વપૂર્ણ છે. વર્ષોથી, રીએક્ટ ડેવલપર્સ હૂક્સના કડક નિયમો (Rules of Hooks) હેઠળ કામ કરી રહ્યા છે:

આ નિયમો અસ્તિત્વમાં છે કારણ કે `useState` અને `useEffect` જેવા પરંપરાગત હૂક્સ તેમના સ્ટેટને જાળવવા માટે દરેક રેન્ડર દરમિયાન એક સુસંગત કોલ ઓર્ડર પર આધાર રાખે છે. `use` હૂક આ પ્રથાને તોડી નાખે છે. તમે `use` ને કન્ડિશન્સ (`if`/`else`), લૂપ્સ (`for`/`map`), અને વહેલા `return` સ્ટેટમેન્ટ્સની અંદર પણ કોલ કરી શકો છો.

આ માત્ર એક નાનો ફેરફાર નથી; તે એક પેરાડાઈમ શિફ્ટ છે. તે રિસોર્સનો ઉપયોગ કરવાની વધુ લવચીક અને સાહજિક રીતને મંજૂરી આપે છે, જે સ્ટેટિક, ટોપ-લેવલ સબ્સ્ક્રિપ્શન મોડેલથી ડાયનેમિક, ઓન-ડિમાન્ડ વપરાશ મોડેલ તરફ આગળ વધે છે. જ્યારે તે સૈદ્ધાંતિક રીતે વિવિધ રિસોર્સ પ્રકારો સાથે કામ કરી શકે છે, ત્યારે તેનું પ્રારંભિક અમલીકરણ રીએક્ટ ડેવલપમેન્ટમાં બે સૌથી સામાન્ય મુશ્કેલીઓ પર ધ્યાન કેન્દ્રિત કરે છે: પ્રોમિસ અને કોન્ટેક્સ્ટ.

મુખ્ય ખ્યાલ: વેલ્યુને અનરેપ કરવું

તેના હૃદયમાં, `use` હૂક એક રિસોર્સમાંથી વેલ્યુને "અનરેપ" કરવા માટે બનાવવામાં આવ્યું છે. તેને આ રીતે વિચારો:

ચાલો આ બે શક્તિશાળી ક્ષમતાઓનું વિગતવાર અન્વેષણ કરીએ.

એસિંક્રોનસ ઓપરેશન્સમાં નિપુણતા: પ્રોમિસ સાથે `use`

ડેટા ફેચિંગ એ આધુનિક વેબ એપ્લિકેશન્સનું જીવનરક્ત છે. રીએક્ટમાં પરંપરાગત અભિગમ કાર્યાત્મક રહ્યો છે પરંતુ ઘણીવાર શબ્ડાળુ અને સૂક્ષ્મ બગ્સ માટે સંવેદનશીલ હોય છે.

જૂની રીત: `useEffect` અને `useState` નો ખેલ

એક સરળ કમ્પોનન્ટનો વિચાર કરો જે યુઝર ડેટા ફેચ કરે છે. પ્રમાણભૂત પેટર્ન કંઈક આના જેવી દેખાય છે:


import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    let isMounted = true;
    const fetchUser = async () => {
      try {
        setIsLoading(true);
        const response = await fetch(`https://api.example.com/users/${userId}`);
        if (!response.ok) {
          throw new Error('Network response was not ok');
        }
        const data = await response.json();
        if (isMounted) {
          setUser(data);
        }
      } catch (err) {
        if (isMounted) {
          setError(err);
        }
      } finally {
        if (isMounted) {
          setIsLoading(false);
        }
      }
    };

    fetchUser();

    return () => {
      isMounted = false;
    };
  }, [userId]);

  if (isLoading) {
    return <p>પ્રોફાઇલ લોડ થઈ રહી છે...</p>;
  }

  if (error) {
    return <p>એરર: {error.message}</p>;
  }

  return (
    <div>
      <h1>{user.name}</h1>
      <p>ઇમેઇલ: {user.email}</p>
    </div>
  );
}

આ કોડ ઘણો બોઈલરપ્લેટ-હેવી છે. આપણે મેન્યુઅલી ત્રણ અલગ-અલગ સ્ટેટ્સ (`user`, `isLoading`, `error`) મેનેજ કરવા પડે છે, અને આપણે માઉન્ટેડ ફ્લેગનો ઉપયોગ કરીને રેસ કન્ડિશન્સ અને ક્લીનઅપ વિશે સાવચેત રહેવું પડે છે. જ્યારે કસ્ટમ હૂક્સ આને એબ્સ્ટ્રેક્ટ કરી શકે છે, ત્યારે અંતર્ગત જટિલતા યથાવત રહે છે.

નવી રીત: `use` સાથે સુંદર એસિંક્રોનિસિટી

રીએક્ટ સસ્પેન્સ સાથે મળીને `use` હૂક આ સમગ્ર પ્રક્રિયાને નાટકીય રીતે સરળ બનાવે છે. તે આપણને એસિંક્રોનસ કોડ લખવાની મંજૂરી આપે છે જે સિંક્રોનસ કોડ જેવો વાંચી શકાય છે.

અહીં એ જ કમ્પોનન્ટ `use` સાથે કેવી રીતે લખી શકાય તે છે:


// તમારે આ કમ્પોનન્ટને <Suspense> અને <ErrorBoundary> માં લપેટવું આવશ્યક છે
import { use } from 'react';
import { fetchUser } from './api'; // માની લો કે આ એક કેશ્ડ પ્રોમિસ રિટર્ન કરે છે

function UserProfile({ userId }) {
  // `use` પ્રોમિસ રિઝોલ્વ ન થાય ત્યાં સુધી કમ્પોનન્ટને સસ્પેન્ડ કરશે
  const user = use(fetchUser(userId));

  // જ્યારે એક્ઝેક્યુશન અહીં પહોંચે છે, ત્યારે પ્રોમિસ રિઝોલ્વ થઈ ગયું હોય છે અને `user` પાસે ડેટા હોય છે.
  // કમ્પોનન્ટમાં isLoading કે એરર સ્ટેટ્સની જરૂર નથી.
  return (
    <div>
      <h1>{user.name}</h1>
      <p>ઇમેઇલ: {user.email}</p>
    </div>
  );
}

તફાવત આશ્ચર્યજનક છે. લોડિંગ અને એરર સ્ટેટ્સ આપણા કમ્પોનન્ટ લોજિકમાંથી અદૃશ્ય થઈ ગયા છે. પડદા પાછળ શું થઈ રહ્યું છે?

  1. જ્યારે `UserProfile` પ્રથમ વખત રેન્ડર થાય છે, ત્યારે તે `use(fetchUser(userId))` ને કોલ કરે છે.
  2. `fetchUser` ફંક્શન એક નેટવર્ક રિક્વેસ્ટ શરૂ કરે છે અને એક પ્રોમિસ રિટર્ન કરે છે.
  3. `use` હૂક આ પેન્ડિંગ પ્રોમિસ મેળવે છે અને રીએક્ટના રેન્ડરર સાથે વાતચીત કરીને આ કમ્પોનન્ટના રેન્ડરિંગને સસ્પેન્ડ કરે છે.
  4. રીએક્ટ કમ્પોનન્ટ ટ્રીમાં ઉપર જઈને સૌથી નજીકની `` બાઉન્ડ્રી શોધે છે અને તેનું `fallback` UI (દા.ત., એક સ્પિનર) દર્શાવે છે.
  5. એકવાર પ્રોમિસ રિઝોલ્વ થઈ જાય, રીએક્ટ `UserProfile` ને ફરીથી રેન્ડર કરે છે. આ વખતે, જ્યારે `use` ને એ જ પ્રોમિસ સાથે કોલ કરવામાં આવે છે, ત્યારે પ્રોમિસ પાસે રિઝોલ્વ થયેલ વેલ્યુ હોય છે. `use` આ વેલ્યુ રિટર્ન કરે છે.
  6. કમ્પોનન્ટ રેન્ડરિંગ આગળ વધે છે, અને યુઝરની પ્રોફાઇલ પ્રદર્શિત થાય છે.
  7. જો પ્રોમિસ રિજેક્ટ થાય છે, તો `use` એરર થ્રો કરે છે. રીએક્ટ આને પકડે છે અને ટ્રીમાં ઉપર જઈને સૌથી નજીકની `` પર જઈને ફોલબેક એરર UI દર્શાવે છે.

રિસોર્સ વપરાશનું ઊંડાણપૂર્વક વિશ્લેષણ: કેશિંગની અનિવાર્યતા

`use(fetchUser(userId))` ની સરળતા એક નિર્ણાયક વિગત છુપાવે છે: તમારે દરેક રેન્ડર પર નવું પ્રોમિસ બનાવવું જોઈએ નહીં. જો આપણું `fetchUser` ફંક્શન ફક્ત `() => fetch(...)` હોત, અને આપણે તેને સીધું કમ્પોનન્ટની અંદર કોલ કર્યું હોત, તો આપણે દરેક રેન્ડર પ્રયાસ પર નવી નેટવર્ક રિક્વેસ્ટ બનાવતા, જે અનંત લૂપ તરફ દોરી જતું. કમ્પોનન્ટ સસ્પેન્ડ થતું, પ્રોમિસ રિઝોલ્વ થતું, રીએક્ટ ફરીથી રેન્ડર કરતું, એક નવું પ્રોમિસ બનાવવામાં આવતું, અને તે ફરીથી સસ્પેન્ડ થતું.

પ્રોમિસ સાથે `use` નો ઉપયોગ કરતી વખતે સમજવા માટે આ સૌથી મહત્ત્વપૂર્ણ રિસોર્સ મેનેજમેન્ટનો ખ્યાલ છે. પ્રોમિસ રી-રેન્ડર્સ દરમિયાન સ્થિર અને કેશ્ડ હોવું જોઈએ.

રીએક્ટ આમાં મદદ કરવા માટે એક નવું `cache` ફંક્શન પ્રદાન કરે છે. ચાલો એક મજબૂત ડેટા-ફેચિંગ યુટિલિટી બનાવીએ:


// api.js
import { cache } from 'react';

export const fetchUser = cache(async (userId) => {
  console.log(`યુઝર માટે ડેટા ફેચ કરી રહ્યું છે: ${userId}`);
  const response = await fetch(`https://api.example.com/users/${userId}`);
  if (!response.ok) {
    throw new Error('યુઝર ડેટા ફેચ કરવામાં નિષ્ફળ.');
  }
  return response.json();
});

રીએક્ટનું `cache` ફંક્શન એસિંક્રોનસ ફંક્શનને મેમોઇઝ કરે છે. જ્યારે `fetchUser(1)` ને કોલ કરવામાં આવે છે, ત્યારે તે ફેચ શરૂ કરે છે અને પરિણામી પ્રોમિસને સ્ટોર કરે છે. જો અન્ય કમ્પોનન્ટ (અથવા એ જ કમ્પોનન્ટ પછીના રેન્ડર પર) એ જ રેન્ડર પાસમાં ફરીથી `fetchUser(1)` ને કોલ કરે છે, તો `cache` એ જ પ્રોમિસ ઓબ્જેક્ટ પરત કરશે, જે બિનજરૂરી નેટવર્ક રિક્વેસ્ટ્સને અટકાવશે. આ ડેટા ફેચિંગને આઇડેમ્પોટન્ટ અને `use` હૂક સાથે વાપરવા માટે સુરક્ષિત બનાવે છે.

આ રિસોર્સ મેનેજમેન્ટમાં એક મૂળભૂત પરિવર્તન છે. કમ્પોનન્ટની અંદર ફેચ સ્ટેટનું સંચાલન કરવાને બદલે, આપણે તેની બહાર રિસોર્સ (ડેટા પ્રોમિસ) નું સંચાલન કરીએ છીએ, અને કમ્પોનન્ટ ફક્ત તેનો ઉપયોગ કરે છે.

સ્ટેટ મેનેજમેન્ટમાં ક્રાંતિ: કોન્ટેક્સ્ટ સાથે `use`

રીએક્ટ કોન્ટેક્સ્ટ "પ્રોપ ડ્રિલિંગ"—ઘણા સ્તરોનાં કમ્પોનન્ટ્સ દ્વારા પ્રોપ્સ પસાર કરવાનું ટાળવા માટેનું એક શક્તિશાળી સાધન છે. જોકે, તેના પરંપરાગત અમલીકરણમાં એક નોંધપાત્ર પર્ફોર્મન્સની ખામી છે.

`useContext` ની સમસ્યા

`useContext` હૂક એક કમ્પોનન્ટને કોન્ટેક્સ્ટ સાથે સબ્સ્ક્રાઇબ કરે છે. આનો અર્થ એ છે કે જ્યારે પણ કોન્ટેક્સ્ટની વેલ્યુ બદલાય છે, ત્યારે તે કોન્ટેક્સ્ટ માટે `useContext` નો ઉપયોગ કરતું દરેક કમ્પોનન્ટ રી-રેન્ડર થશે. આ ત્યારે પણ સાચું છે જ્યારે કમ્પોનન્ટ ફક્ત કોન્ટેક્સ્ટ વેલ્યુના નાના, ન બદલાયેલા ભાગની જ ચિંતા કરતું હોય.

એક `SessionContext` નો વિચાર કરો જે યુઝર માહિતી અને વર્તમાન થીમ બંને ધરાવે છે:


// SessionContext.js
const SessionContext = createContext({
  user: null,
  theme: 'light',
  updateTheme: () => {},
});

// કમ્પોનન્ટ જે ફક્ત યુઝરની ચિંતા કરે છે
function WelcomeMessage() {
  const { user } = useContext(SessionContext);
  console.log('Rendering WelcomeMessage');
  return <p>સ્વાગત છે, {user?.name}!</p>;
}

// કમ્પોનન્ટ જે ફક્ત થીમની ચિંતા કરે છે
function ThemeToggleButton() {
  const { theme, updateTheme } = useContext(SessionContext);
  console.log('Rendering ThemeToggleButton');
  return <button onClick={updateTheme}>{theme === 'light' ? 'dark' : 'light'} થીમ પર સ્વિચ કરો</button>;
}

આ દૃશ્યમાં, જ્યારે યુઝર `ThemeToggleButton` પર ક્લિક કરે છે અને `updateTheme` કોલ થાય છે, ત્યારે સમગ્ર `SessionContext` વેલ્યુ ઓબ્જેક્ટ બદલાઈ જાય છે. આ `ThemeToggleButton` અને `WelcomeMessage` બંનેને રી-રેન્ડર કરવા માટેનું કારણ બને છે, ભલે `user` ઓબ્જેક્ટ બદલાયો ન હોય. સેંકડો કોન્ટેક્સ્ટ કન્ઝ્યુમર્સ સાથેની મોટી એપ્લિકેશનમાં, આ ગંભીર પર્ફોર્મન્સ સમસ્યાઓ તરફ દોરી શકે છે.

આવી રહ્યું છે `use(Context)`: શરતી વપરાશ

`use` હૂક આ સમસ્યાનો એક ક્રાંતિકારી ઉકેલ આપે છે. કારણ કે તેને શરતી રીતે કોલ કરી શકાય છે, એક કમ્પોનન્ટ ફક્ત ત્યારે જ કોન્ટેક્સ્ટ સાથે સબ્સ્ક્રિપ્શન સ્થાપિત કરે છે જ્યારે તે ખરેખર વેલ્યુ વાંચે છે.

ચાલો આ શક્તિને પ્રદર્શિત કરવા માટે એક કમ્પોનન્ટને રિફેક્ટર કરીએ:


function UserSettings({ userId }) {
  const { user, theme } = useContext(SessionContext); // પરંપરાગત રીત: હંમેશા સબ્સ્ક્રાઇબ કરે છે

  // ચાલો કલ્પના કરીએ કે આપણે ફક્ત હાલમાં લોગ-ઇન થયેલા યુઝર માટે જ થીમ સેટિંગ્સ બતાવીએ છીએ
  if (user?.id !== userId) {
    return <p>તમે ફક્ત તમારા પોતાના સેટિંગ્સ જોઈ શકો છો.</p>;
  }

  // આ ભાગ ફક્ત ત્યારે જ ચાલે છે જો યુઝર ID મેચ થાય
  return <div>વર્તમાન થીમ: {theme}</div>;
}

`useContext` સાથે, આ `UserSettings` કમ્પોનન્ટ દર વખતે થીમ બદલાય ત્યારે રી-રેન્ડર થશે, ભલે `user.id !== userId` હોય અને થીમની માહિતી ક્યારેય પ્રદર્શિત ન થાય. સબ્સ્ક્રિપ્શન ટોપ લેવલ પર બિનશરતી રીતે સ્થાપિત થાય છે.

હવે, ચાલો `use` સંસ્કરણ જોઈએ:


import { use } from 'react';

function UserSettings({ userId }) {
  // પહેલા યુઝરને વાંચો. ચાલો માની લઈએ કે આ ભાગ સસ્તો અથવા જરૂરી છે.
  const user = use(SessionContext).user;

  // જો શરત પૂરી ન થાય, તો આપણે વહેલા રિટર્ન થઈ જઈએ છીએ.
  // મુખ્ય વાત એ છે કે, આપણે હજી સુધી થીમ વાંચી નથી.
  if (user?.id !== userId) {
    return <p>તમે ફક્ત તમારા પોતાના સેટિંગ્સ જોઈ શકો છો.</p>;
  }

  // ફક્ત જો શરત પૂરી થાય, તો જ આપણે કોન્ટેક્સ્ટમાંથી થીમ વાંચીએ છીએ.
  // કોન્ટેક્સ્ટ ફેરફારોનું સબ્સ્ક્રિપ્શન અહીં, શરતી રીતે સ્થાપિત થાય છે.
  const theme = use(SessionContext).theme;

  return <div>વર્તમાન થીમ: {theme}</div>;
}

આ એક ગેમ-ચેન્જર છે. આ સંસ્કરણમાં, જો `user.id` એ `userId` સાથે મેળ ખાતું નથી, તો કમ્પોનન્ટ વહેલું રિટર્ન થાય છે. `const theme = use(SessionContext).theme;` લાઇન ક્યારેય એક્ઝેક્યુટ થતી નથી. તેથી, આ કમ્પોનન્ટ ઇન્સ્ટન્સ `SessionContext` પર સબ્સ્ક્રાઇબ કરતું નથી. જો એપ્લિકેશનમાં અન્યત્ર થીમ બદલવામાં આવે, તો આ કમ્પોનન્ટ બિનજરૂરી રીતે રી-રેન્ડર નહીં થાય. તેણે કોન્ટેક્સ્ટમાંથી શરતી રીતે વાંચીને પોતાના રિસોર્સના વપરાશને અસરકારક રીતે ઓપ્ટિમાઇઝ કર્યું છે.

રિસોર્સ વપરાશ વિશ્લેષણ: સબ્સ્ક્રિપ્શન મોડેલ્સ

કોન્ટેક્સ્ટ વપરાશ માટેનું માનસિક મોડેલ નાટકીય રીતે બદલાય છે:

રી-રેન્ડર્સ પર આ ઝીણવટભર્યું નિયંત્રણ મોટા પાયાની એપ્લિકેશન્સમાં પર્ફોર્મન્સ ઓપ્ટિમાઇઝેશન માટે એક શક્તિશાળી સાધન છે. તે ડેવલપર્સને એવા કમ્પોનન્ટ્સ બનાવવાની મંજૂરી આપે છે જે અપ્રસ્તુત સ્ટેટ અપડેટ્સથી ખરેખર અલગ હોય, જે જટિલ મેમોઇઝેશન (`React.memo`) અથવા સ્ટેટ સિલેક્ટર પેટર્નનો આશરો લીધા વિના વધુ કાર્યક્ષમ અને પ્રતિભાવશીલ યુઝર ઇન્ટરફેસ તરફ દોરી જાય છે.

આંતરછેદ: કોન્ટેક્સ્ટમાં પ્રોમિસ સાથે `use`

`use` ની સાચી શક્તિ ત્યારે સ્પષ્ટ થાય છે જ્યારે આપણે આ બે ખ્યાલોને જોડીએ છીએ. શું થશે જો કોન્ટેક્સ્ટ પ્રોવાઇડર સીધો ડેટા નહીં, પરંતુ તે ડેટા માટેનું પ્રોમિસ પ્રદાન કરે? આ પેટર્ન એપ્લિકેશન-વ્યાપી ડેટા સ્રોતોના સંચાલન માટે અત્યંત ઉપયોગી છે.


// DataContext.js
import { createContext } from 'react';
import { fetchSomeGlobalData } from './api'; // એક કેશ્ડ પ્રોમિસ રિટર્ન કરે છે

// કોન્ટેક્સ્ટ ડેટા નહીં, પરંતુ એક પ્રોમિસ પ્રદાન કરે છે.
export const GlobalDataContext = createContext(fetchSomeGlobalData());

// App.js
function App() {
  return (
    <GlobalDataContext.Provider value={fetchSomeGlobalData()}>
      <Suspense fallback={<h1>એપ્લિકેશન લોડ થઈ રહી છે...</h1>}>
        <Dashboard />
      </Suspense>
    </GlobalDataContext.Provider>
  );
}

// Dashboard.js
import { use } from 'react';
import { GlobalDataContext } from './DataContext';

function Dashboard() {
  // પ્રથમ `use` કોન્ટેક્સ્ટમાંથી પ્રોમિસ વાંચે છે.
  const dataPromise = use(GlobalDataContext);

  // બીજું `use` પ્રોમિસને અનરેપ કરે છે, જો જરૂરી હોય તો સસ્પેન્ડ કરે છે.
  const globalData = use(dataPromise);

  // ઉપરની બે લાઇન લખવાની વધુ સંક્ષિપ્ત રીત:
  // const globalData = use(use(GlobalDataContext));

  return <h1>સ્વાગત છે, {globalData.userName}!</h1>;
}

ચાલો `const globalData = use(use(GlobalDataContext));` ને તોડીને સમજીએ:

  1. `use(GlobalDataContext)`: આંતરિક કોલ પ્રથમ એક્ઝેક્યુટ થાય છે. તે `GlobalDataContext` માંથી વેલ્યુ વાંચે છે. આપણા સેટઅપમાં, આ વેલ્યુ `fetchSomeGlobalData()` દ્વારા પરત કરાયેલ એક પ્રોમિસ છે.
  2. `use(dataPromise)`: બાહ્ય કોલ પછી આ પ્રોમિસ મેળવે છે. તે બરાબર એ જ રીતે વર્તે છે જે આપણે પ્રથમ વિભાગમાં જોયું: જો પ્રોમિસ પેન્ડિંગ હોય તો તે `Dashboard` કમ્પોનન્ટને સસ્પેન્ડ કરે છે, જો રિજેક્ટ થાય તો થ્રો કરે છે, અથવા રિઝોલ્વ થયેલ ડેટા પરત કરે છે.

આ પેટર્ન અપવાદરૂપે શક્તિશાળી છે. તે ડેટા-ફેચિંગ લોજિકને ડેટાનો ઉપયોગ કરતા કમ્પોનન્ટ્સથી અલગ કરે છે, જ્યારે સીમલેસ લોડિંગ અનુભવ માટે રીએક્ટના બિલ્ટ-ઇન સસ્પેન્સ મિકેનિઝમનો લાભ ઉઠાવે છે. કમ્પોનન્ટ્સને એ જાણવાની જરૂર નથી કે ડેટા *કેવી રીતે* અથવા *ક્યારે* ફેચ થાય છે; તેઓ ફક્ત તેની માંગ કરે છે, અને રીએક્ટ બાકીનું સંચાલન કરે છે.

પર્ફોર્મન્સ, મુશ્કેલીઓ અને શ્રેષ્ઠ પ્રયાસો

કોઈપણ શક્તિશાળી સાધનની જેમ, `use` હૂકને અસરકારક રીતે વાપરવા માટે સમજણ અને શિસ્તની જરૂર છે. પ્રોડક્શન એપ્લિકેશન્સ માટે અહીં કેટલાક મુખ્ય વિચારણાઓ છે.

પર્ફોર્મન્સ સારાંશ

ટાળવા જેવી સામાન્ય ભૂલો

  1. અનકેશ્ડ પ્રોમિસ: નંબર વન ભૂલ. કમ્પોનન્ટમાં સીધું `use(fetch(...))` કોલ કરવાથી અનંત લૂપ થશે. હંમેશા રીએક્ટના `cache` જેવી કેશિંગ મિકેનિઝમ અથવા SWR/React Query જેવી લાઇબ્રેરીઓનો ઉપયોગ કરો.
  2. ગુમ થયેલ બાઉન્ડ્રીઝ: પેરેન્ટ `` બાઉન્ડ્રી વિના `use(Promise)` નો ઉપયોગ કરવાથી તમારી એપ્લિકેશન ક્રેશ થશે. તેવી જ રીતે, પેરેન્ટ `` વિના રિજેક્ટેડ પ્રોમિસ પણ એપ્લિકેશનને ક્રેશ કરશે. તમારે તમારા કમ્પોનન્ટ ટ્રીને આ બાઉન્ડ્રીઝને ધ્યાનમાં રાખીને ડિઝાઇન કરવું આવશ્યક છે.
  3. અકાળ ઓપ્ટિમાઇઝેશન: જ્યારે `use(Context)` પર્ફોર્મન્સ માટે ઉત્તમ છે, તે હંમેશા જરૂરી નથી. એવા કોન્ટેક્સ્ટ્સ માટે કે જે સરળ છે, ભાગ્યે જ બદલાય છે, અથવા જ્યાં કન્ઝ્યુમર્સને રી-રેન્ડર કરવું સસ્તું છે, ત્યાં પરંપરાગત `useContext` સંપૂર્ણપણે ઠીક છે અને થોડું વધુ સીધું છે. સ્પષ્ટ પર્ફોર્મન્સ કારણ વિના તમારા કોડને વધુ જટિલ બનાવશો નહીં.
  4. `cache` ની ગેરસમજ: રીએક્ટનું `cache` ફંક્શન તેના આર્ગ્યુમેન્ટ્સના આધારે મેમોઇઝ કરે છે, પરંતુ આ કેશ સામાન્ય રીતે સર્વર રિક્વેસ્ટ્સ વચ્ચે અથવા ક્લાયંટ પર સંપૂર્ણ પેજ રીલોડ પર સાફ થઈ જાય છે. તે રિક્વેસ્ટ-લેવલ કેશિંગ માટે રચાયેલ છે, લાંબા ગાળાના ક્લાયંટ-સાઇડ સ્ટેટ માટે નહીં. જટિલ ક્લાયંટ-સાઇડ કેશિંગ, ઇન્વેલિડેશન અને મ્યુટેશન માટે, એક સમર્પિત ડેટા-ફેચિંગ લાઇબ્રેરી હજી પણ ખૂબ જ મજબૂત પસંદગી છે.

શ્રેષ્ઠ પ્રયાસોની ચેકલિસ્ટ

ભવિષ્ય `use` છે: સર્વર કમ્પોનન્ટ્સ અને તેનાથી આગળ

`use` હૂક માત્ર ક્લાયંટ-સાઇડની સુવિધા નથી; તે રીએક્ટ સર્વર કમ્પોનન્ટ્સ (RSCs) નો મૂળભૂત સ્તંભ છે. RSC વાતાવરણમાં, એક કમ્પોનન્ટ સર્વર પર એક્ઝેક્યુટ થઈ શકે છે. જ્યારે તે `use(fetch(...))` ને કોલ કરે છે, ત્યારે સર્વર શાબ્દિક રીતે તે કમ્પોનન્ટના રેન્ડરિંગને અટકાવી શકે છે, ડેટાબેઝ ક્વેરી અથવા API કોલ પૂર્ણ થવાની રાહ જોઈ શકે છે, અને પછી ડેટા સાથે રેન્ડરિંગ ફરી શરૂ કરી શકે છે, અંતિમ HTML ક્લાયંટને સ્ટ્રીમ કરી શકે છે.

આ એક સીમલેસ મોડેલ બનાવે છે જ્યાં ડેટા ફેચિંગ રેન્ડરિંગ પ્રક્રિયાનો પ્રથમ-વર્ગનો નાગરિક છે, જે સર્વર-સાઇડ ડેટા પુનઃપ્રાપ્તિ અને ક્લાયંટ-સાઇડ UI કમ્પોઝિશન વચ્ચેની સીમાને ભૂંસી નાખે છે. આપણે અગાઉ લખેલું એ જ `UserProfile` કમ્પોનન્ટ, ન્યૂનતમ ફેરફારો સાથે, સર્વર પર ચાલી શકે છે, તેનો ડેટા ફેચ કરી શકે છે, અને બ્રાઉઝરને સંપૂર્ણ-રચિત HTML મોકલી શકે છે, જે ઝડપી પ્રારંભિક પેજ લોડ અને બહેતર યુઝર અનુભવ તરફ દોરી જાય છે.

`use` API પણ વિસ્તૃત કરી શકાય તેવું છે. ભવિષ્યમાં, તેનો ઉપયોગ અન્ય એસિંક્રોનસ સ્રોતો જેવા કે ઓબ્ઝર્વેબલ્સ (દા.ત., RxJS માંથી) અથવા અન્ય કસ્ટમ "thenable" ઓબ્જેક્ટ્સમાંથી વેલ્યુને અનરેપ કરવા માટે થઈ શકે છે, જે રીએક્ટ કમ્પોનન્ટ્સ બાહ્ય ડેટા અને ઇવેન્ટ્સ સાથે કેવી રીતે ક્રિયાપ્રતિક્રિયા કરે છે તેને વધુ એકીકૃત કરશે.

નિષ્કર્ષ: રીએક્ટ ડેવલપમેન્ટનો નવો યુગ

`use` હૂક માત્ર એક નવી API કરતાં વધુ છે; તે સ્વચ્છ, વધુ ઘોષણાત્મક અને વધુ કાર્યક્ષમ રીએક્ટ એપ્લિકેશન્સ લખવા માટેનું આમંત્રણ છે. એસિંક્રોનસ ઓપરેશન્સ અને કોન્ટેક્સ્ટ વપરાશને સીધા રેન્ડરિંગ પ્રવાહમાં એકીકૃત કરીને, તે એવી સમસ્યાઓનું સુંદર રીતે નિરાકરણ લાવે છે જેને વર્ષોથી જટિલ પેટર્ન અને બોઈલરપ્લેટની જરૂર પડતી હતી.

દરેક વૈશ્વિક ડેવલપર માટે મુખ્ય તારણો છે:

જેમ જેમ આપણે રીએક્ટ 19 અને તેનાથી આગળના યુગમાં આગળ વધીએ છીએ, `use` હૂકમાં નિપુણતા મેળવવી આવશ્યક બનશે. તે ડાયનેમિક યુઝર ઇન્ટરફેસ બનાવવાની વધુ સાહજિક અને શક્તિશાળી રીતને અનલોક કરે છે, ક્લાયંટ અને સર્વર વચ્ચેના અંતરને પૂરે છે અને વેબ એપ્લિકેશન્સની આગામી પેઢી માટે માર્ગ મોકળો કરે છે.

`use` હૂક પર તમારા શું વિચારો છે? શું તમે તેની સાથે પ્રયોગ કરવાનું શરૂ કર્યું છે? તમારા અનુભવો, પ્રશ્નો અને આંતરદૃષ્ટિ નીચેની ટિપ્પણીઓમાં શેર કરો!