ડેટા ફેચિંગ માટે React સસ્પેન્સમાં નિપુણતા મેળવો. ડિક્લેરેટિવ રીતે લોડિંગ સ્ટેટ્સ મેનેજ કરવાનું શીખો, ટ્રાન્ઝિશન્સ વડે UX સુધારો, અને એરર બાઉન્ડ્રીઝ વડે એરરને હેન્ડલ કરો.
React સસ્પેન્સ બાઉન્ડ્રીઝ: ડિક્લેરેટિવ લોડિંગ સ્ટેટ મેનેજમેન્ટમાં ઊંડાણપૂર્વક માર્ગદર્શન
આધુનિક વેબ ડેવલપમેન્ટની દુનિયામાં, એક સરળ અને રિસ્પોન્સિવ યુઝર એક્સપિરિયન્સ બનાવવો સર્વોપરી છે. ડેવલપર્સ જે સૌથી સતત પડકારોનો સામનો કરે છે તેમાંથી એક લોડિંગ સ્ટેટ્સનું સંચાલન કરવું છે. યુઝર પ્રોફાઇલ માટે ડેટા મેળવવાથી માંડીને એપ્લિકેશનના નવા વિભાગને લોડ કરવા સુધી, રાહ જોવાની ક્ષણો નિર્ણાયક હોય છે. ઐતિહાસિક રીતે, આમાં isLoading
, isFetching
, અને hasError
જેવા બુલિયન ફ્લેગ્સનું એક ગૂંચવણભર્યું જાળું સામેલ હતું, જે આપણા કમ્પોનન્ટ્સમાં વેરવિખેર હતું. આ ઇમ્પેરેટિવ અભિગમ આપણા કોડને અવ્યવસ્થિત કરે છે, લોજિકને જટિલ બનાવે છે, અને રેસ કન્ડિશન્સ જેવી ભૂલોનો વારંવાર સ્ત્રોત બને છે.
અહીં React સસ્પેન્સ આવે છે. શરૂઆતમાં React.lazy()
સાથે કોડ-સ્પ્લિટિંગ માટે રજૂ કરાયેલ, તેની ક્ષમતાઓ React 18 સાથે નાટકીય રીતે વિસ્તરી છે અને તે અસિંક્રોનસ ઓપરેશન્સ, ખાસ કરીને ડેટા ફેચિંગને હેન્ડલ કરવા માટે એક શક્તિશાળી, ફર્સ્ટ-ક્લાસ મિકેનિઝમ બની ગયું છે. સસ્પેન્સ આપણને ડિક્લેરેટિવ રીતે લોડિંગ સ્ટેટ્સનું સંચાલન કરવાની મંજૂરી આપે છે, જે આપણે આપણા કમ્પોનન્ટ્સ વિશે કેવી રીતે લખીએ છીએ અને વિચારીએ છીએ તેને મૂળભૂત રીતે બદલી નાખે છે. "શું હું લોડ કરી રહ્યો છું?" પૂછવાને બદલે, આપણા કમ્પોનન્ટ્સ ફક્ત કહી શકે છે, "મને રેન્ડર કરવા માટે આ ડેટાની જરૂર છે. જ્યારે હું રાહ જોઉં, ત્યારે કૃપા કરીને આ ફોલબેક UI બતાવો."
આ વ્યાપક માર્ગદર્શિકા તમને સ્ટેટ મેનેજમેન્ટની પરંપરાગત પદ્ધતિઓથી React સસ્પેન્સના ડિક્લેરેટિવ પેરાડાઈમ સુધીની સફર પર લઈ જશે. આપણે સસ્પેન્સ બાઉન્ડ્રીઝ શું છે, તે કોડ-સ્પ્લિટિંગ અને ડેટા ફેચિંગ બંને માટે કેવી રીતે કાર્ય કરે છે, અને જટિલ લોડિંગ UIs કેવી રીતે બનાવવું જે તમારા યુઝર્સને નિરાશ કરવાને બદલે આનંદિત કરે છે તે વિશે જાણીશું.
જૂની પદ્ધતિ: મેન્યુઅલ લોડિંગ સ્ટેટ્સનું કંટાળાજનક કામ
આપણે સસ્પેન્સની સુંદરતાને સંપૂર્ણ રીતે સમજી શકીએ તે પહેલાં, તે જે સમસ્યાનું સમાધાન કરે છે તેને સમજવું જરૂરી છે. ચાલો એક લાક્ષણિક કમ્પોનન્ટ જોઈએ જે 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(() => {
// નવા userId માટે સ્ટેટ રીસેટ કરો
setIsLoading(true);
setUser(null);
setError(null);
const fetchUser = async () => {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error('નેટવર્ક પ્રતિસાદ બરાબર ન હતો');
}
const data = await response.json();
setUser(data);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
};
fetchUser();
}, [userId]); // જ્યારે userId બદલાય ત્યારે ફરીથી ફેચ કરો
if (isLoading) {
return <p>પ્રોફાઇલ લોડ થઈ રહી છે...</p>;
}
if (error) {
return <p>ભૂલ: {error.message}</p>;
}
return (
<div>
<h1>{user.name}</h1>
<p>ઇમેઇલ: {user.email}</p>
</div>
);
}
આ પેટર્ન કાર્યાત્મક છે, પરંતુ તેના ઘણા ગેરફાયદા છે:
- બોઇલરપ્લેટ: દરેક એક અસિંક્રોનસ ઓપરેશન માટે આપણને ઓછામાં ઓછા ત્રણ સ્ટેટ વેરિયેબલ્સ (
data
,isLoading
,error
) ની જરૂર પડે છે. આ એક જટિલ એપ્લિકેશનમાં સારી રીતે સ્કેલ થતું નથી. - વિખરાયેલું લોજિક: રેન્ડરિંગ લોજિક શરતી તપાસ (
if (isLoading)
,if (error)
) સાથે વિભાજિત છે. મુખ્ય "હેપ્પી પાથ" રેન્ડર લોજિક સૌથી નીચે ધકેલાઈ જાય છે, જે કમ્પોનન્ટને વાંચવામાં મુશ્કેલ બનાવે છે. - રેસ કન્ડિશન્સ:
useEffect
હુકને સાવચેતીપૂર્વક ડિપેન્ડન્સી મેનેજમેન્ટની જરૂર છે. યોગ્ય ક્લીનઅપ વિના, જોuserId
પ્રોપ ઝડપથી બદલાય તો એક ઝડપી પ્રતિસાદ ધીમા પ્રતિસાદ દ્વારા ઓવરરાઇટ થઈ શકે છે. જોકે અમારું ઉદાહરણ સરળ છે, જટિલ પરિસ્થિતિઓમાં સૂક્ષ્મ બગ્સ સરળતાથી આવી શકે છે. - વોટરફોલ ફેચેસ: જો ચાઇલ્ડ કમ્પોનન્ટને પણ ડેટા ફેચ કરવાની જરૂર હોય, તો તે પેરેન્ટનું લોડિંગ પૂરું ન થાય ત્યાં સુધી રેન્ડરિંગ (અને તેથી ફેચિંગ) શરૂ કરી શકતું નથી. આનાથી બિનકાર્યક્ષમ ડેટા-લોડિંગ વોટરફોલ્સ થાય છે.
React સસ્પેન્સનો પ્રવેશ: એક આમૂલ પરિવર્તન
સસ્પેન્સ આ મોડેલને ઊંધું કરી દે છે. કમ્પોનન્ટ આંતરિક રીતે લોડિંગ સ્ટેટનું સંચાલન કરવાને બદલે, તે અસિંક્રોનસ ઓપરેશન પર તેની નિર્ભરતા સીધી React ને જણાવે છે. જો તેને જોઈતો ડેટા હજી ઉપલબ્ધ નથી, તો કમ્પોનન્ટ રેન્ડરિંગને "સસ્પેન્ડ" કરે છે.
જ્યારે કોઈ કમ્પોનન્ટ સસ્પેન્ડ થાય છે, ત્યારે React નજીકની સસ્પેન્સ બાઉન્ડ્રી શોધવા માટે કમ્પોનન્ટ ટ્રીમાં ઉપર જાય છે. સસ્પેન્સ બાઉન્ડ્રી એ એક કમ્પોનન્ટ છે જે તમે તમારા ટ્રીમાં <Suspense>
નો ઉપયોગ કરીને વ્યાખ્યાયિત કરો છો. આ બાઉન્ડ્રી પછી એક ફોલબેક UI (જેમ કે સ્પિનર અથવા સ્કેલેટન લોડર) રેન્ડર કરશે જ્યાં સુધી તેની અંદરના બધા કમ્પોનન્ટ્સ તેમની ડેટા નિર્ભરતાઓનું નિરાકરણ ન કરી લે.
મુખ્ય વિચાર એ છે કે ડેટા નિર્ભરતાને તે કમ્પોનન્ટ સાથે સહ-સ્થિત કરવી જેને તેની જરૂર છે, જ્યારે લોડિંગ UI ને કમ્પોનન્ટ ટ્રીમાં ઉચ્ચ સ્તરે કેન્દ્રિત કરવું. આ કમ્પોનન્ટ લોજિકને સાફ કરે છે અને તમને યુઝરના લોડિંગ અનુભવ પર શક્તિશાળી નિયંત્રણ આપે છે.
કમ્પોનન્ટ કેવી રીતે "સસ્પેન્ડ" થાય છે?
સસ્પેન્સ પાછળનો જાદુ એક પેટર્નમાં રહેલો છે જે શરૂઆતમાં અસામાન્ય લાગી શકે છે: પ્રોમિસ (Promise) થ્રો કરવું. સસ્પેન્સ-સક્ષમ ડેટા સ્રોત આ રીતે કાર્ય કરે છે:
- જ્યારે કોઈ કમ્પોનન્ટ ડેટા માટે પૂછે છે, ત્યારે ડેટા સ્રોત તપાસે છે કે તેની પાસે ડેટા કેશ્ડ છે કે નહીં.
- જો ડેટા ઉપલબ્ધ હોય, તો તે તેને સિંક્રોનસલી પરત કરે છે.
- જો ડેટા ઉપલબ્ધ ન હોય (એટલે કે, તે હાલમાં ફેચ થઈ રહ્યો છે), તો ડેટા સ્રોત ચાલુ ફેચ વિનંતીને રજૂ કરતું પ્રોમિસ થ્રો કરે છે.
React આ થ્રો થયેલ પ્રોમિસને પકડે છે. તે તમારી એપ્લિકેશનને ક્રેશ કરતું નથી. તેના બદલે, તે તેને એક સંકેત તરીકે અર્થઘટન કરે છે: "આ કમ્પોનન્ટ હજી રેન્ડર કરવા માટે તૈયાર નથી. તેને થોભાવો, અને ફોલબેક બતાવવા માટે તેની ઉપર સસ્પેન્સ બાઉન્ડ્રી શોધો." એકવાર પ્રોમિસ રિઝોલ્વ થઈ જાય, React કમ્પોનન્ટને ફરીથી રેન્ડર કરવાનો પ્રયાસ કરશે, જે હવે તેનો ડેટા મેળવશે અને સફળતાપૂર્વક રેન્ડર થશે.
<Suspense>
બાઉન્ડ્રી: તમારું લોડિંગ UI ડિક્લેરેટર
<Suspense>
કમ્પોનન્ટ આ પેટર્નનું હૃદય છે. તેનો ઉપયોગ કરવો અત્યંત સરળ છે, તે એક જ, જરૂરી પ્રોપ લે છે: fallback
.
import { Suspense } from 'react';
function App() {
return (
<div>
<h1>મારી એપ્લિકેશન</h1>
<Suspense fallback={<p>કન્ટેન્ટ લોડ થઈ રહ્યું છે...</p>}>
<SomeComponentThatFetchesData />
</Suspense>
</div>
);
}
આ ઉદાહરણમાં, જો SomeComponentThatFetchesData
સસ્પેન્ડ થાય, તો યુઝરને "કન્ટેન્ટ લોડ થઈ રહ્યું છે..." સંદેશ દેખાશે જ્યાં સુધી ડેટા તૈયાર ન થાય. ફોલબેક કોઈ પણ માન્ય React નોડ હોઈ શકે છે, એક સરળ સ્ટ્રિંગથી માંડીને જટિલ સ્કેલેટન કમ્પોનન્ટ સુધી.
ક્લાસિક ઉપયોગ: React.lazy()
સાથે કોડ સ્પ્લિટિંગ
સસ્પેન્સનો સૌથી સ્થાપિત ઉપયોગ કોડ સ્પ્લિટિંગ માટે છે. તે તમને કમ્પોનન્ટ માટે JavaScript લોડ કરવાનું મુલતવી રાખવાની મંજૂરી આપે છે જ્યાં સુધી તેની ખરેખર જરૂર ન હોય.
import React, { Suspense, lazy } from 'react';
// આ કમ્પોનન્ટનો કોડ પ્રારંભિક બંડલમાં નહીં હોય.
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<div>
<h2>કેટલુંક કન્ટેન્ટ જે તરત જ લોડ થાય છે</h2>
<Suspense fallback={<div>કમ્પોનન્ટ લોડ થઈ રહ્યું છે...</div>}>
<HeavyComponent />
</Suspense>
</div>
);
}
અહીં, React ફક્ત ત્યારે જ HeavyComponent
માટે JavaScript ફેચ કરશે જ્યારે તે પ્રથમ વખત તેને રેન્ડર કરવાનો પ્રયાસ કરશે. જ્યારે તે ફેચ અને પાર્સ થઈ રહ્યું હોય, ત્યારે સસ્પેન્સ ફોલબેક પ્રદર્શિત થાય છે. આ પ્રારંભિક પેજ લોડ સમયને સુધારવા માટે એક શક્તિશાળી તકનીક છે.
આધુનિક સીમા: સસ્પેન્સ સાથે ડેટા ફેચિંગ
જ્યારે React સસ્પેન્સ મિકેનિઝમ પ્રદાન કરે છે, તે કોઈ વિશિષ્ટ ડેટા-ફેચિંગ ક્લાયંટ પ્રદાન કરતું નથી. ડેટા ફેચિંગ માટે સસ્પેન્સનો ઉપયોગ કરવા માટે, તમારે એક ડેટા સ્રોતની જરૂર છે જે તેની સાથે સંકલિત થાય (એટલે કે, જે ડેટા પેન્ડિંગ હોય ત્યારે પ્રોમિસ થ્રો કરે).
Relay અને Next.js જેવા ફ્રેમવર્ક્સમાં સસ્પેન્સ માટે બિલ્ટ-ઇન, ફર્સ્ટ-ક્લાસ સપોર્ટ છે. TanStack Query (પહેલાં React Query) અને SWR જેવી લોકપ્રિય ડેટા-ફેચિંગ લાઇબ્રેરીઓ પણ તેના માટે પ્રાયોગિક અથવા સંપૂર્ણ સપોર્ટ આપે છે.
આ ખ્યાલને સમજવા માટે, ચાલો fetch
API ની આસપાસ એક ખૂબ જ સરળ, વૈચારિક રેપર બનાવીએ જેથી તે સસ્પેન્સ-સુસંગત બને. નોંધ: આ શૈક્ષણિક હેતુઓ માટે એક સરળ ઉદાહરણ છે અને તે પ્રોડક્શન-રેડી નથી. તેમાં યોગ્ય કેશિંગ અને એરર હેન્ડલિંગની જટિલતાઓનો અભાવ છે.
// data-fetcher.js
// પરિણામો સંગ્રહવા માટે એક સરળ કેશ
const cache = new Map();
export function fetchData(url) {
if (!cache.has(url)) {
cache.set(url, { status: 'pending', promise: fetchAndCache(url) });
}
const record = cache.get(url);
if (record.status === 'pending') {
throw record.promise; // આ જાદુ છે!
}
if (record.status === 'error') {
throw record.error;
}
if (record.status === 'success') {
return record.data;
}
}
async function fetchAndCache(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`સ્ટેટસ ${response.status} સાથે ફેચ નિષ્ફળ ગયું`);
}
const data = await response.json();
cache.set(url, { status: 'success', data });
} catch (e) {
cache.set(url, { status: 'error', error: e });
}
}
આ રેપર દરેક URL માટે એક સરળ સ્ટેટસ જાળવે છે. જ્યારે fetchData
ને કોલ કરવામાં આવે છે, ત્યારે તે સ્ટેટસ તપાસે છે. જો તે પેન્ડિંગ હોય, તો તે પ્રોમિસ થ્રો કરે છે. જો તે સફળ થાય, તો તે ડેટા પરત કરે છે. હવે, ચાલો આનો ઉપયોગ કરીને આપણા UserProfile
કમ્પોનન્ટને ફરીથી લખીએ.
// UserProfile.js
import React, { Suspense } from 'react';
import { fetchData } from './data-fetcher';
// કમ્પોનન્ટ જે ખરેખર ડેટાનો ઉપયોગ કરે છે
function ProfileDetails({ userId }) {
// ડેટા વાંચવાનો પ્રયાસ કરો. જો તે તૈયાર ન હોય, તો આ સસ્પેન્ડ થશે.
const user = fetchData(`https://api.example.com/users/${userId}`);
return (
<div>
<h1>{user.name}</h1>
<p>ઇમેઇલ: {user.email}</p>
</div>
);
}
// પેરેન્ટ કમ્પોનન્ટ જે લોડિંગ સ્ટેટ UI ને વ્યાખ્યાયિત કરે છે
export function UserProfile({ userId }) {
return (
<Suspense fallback={<p>પ્રોફાઇલ લોડ થઈ રહી છે...</p>}>
<ProfileDetails userId={userId} />
</Suspense>
);
}
તફાવત જુઓ! ProfileDetails
કમ્પોનન્ટ સ્વચ્છ છે અને ફક્ત ડેટા રેન્ડર કરવા પર કેન્દ્રિત છે. તેમાં કોઈ isLoading
અથવા error
સ્ટેટ્સ નથી. તે ફક્ત તેને જોઈતા ડેટાની વિનંતી કરે છે. લોડિંગ ઇન્ડિકેટર બતાવવાની જવાબદારી પેરેન્ટ કમ્પોનન્ટ, UserProfile
પર ખસેડવામાં આવી છે, જે ડિક્લેરેટિવ રીતે જણાવે છે કે રાહ જોતી વખતે શું બતાવવું.
જટિલ લોડિંગ સ્ટેટ્સનું આયોજન
સસ્પેન્સની સાચી શક્તિ ત્યારે સ્પષ્ટ થાય છે જ્યારે તમે બહુવિધ અસિંક્રોનસ નિર્ભરતાઓ સાથે જટિલ UIs બનાવો છો.
એક સ્ટેગર્ડ UI માટે નેસ્ટેડ સસ્પેન્સ બાઉન્ડ્રીઝ
વધુ સુધારેલ લોડિંગ અનુભવ બનાવવા માટે તમે સસ્પેન્સ બાઉન્ડ્રીઝને નેસ્ટ કરી શકો છો. એક ડેશબોર્ડ પેજની કલ્પના કરો જેમાં સાઇડબાર, મુખ્ય કન્ટેન્ટ એરિયા, અને તાજેતરની પ્રવૃત્તિઓની સૂચિ હોય. આમાંના દરેકને પોતાના ડેટા ફેચની જરૂર પડી શકે છે.
function DashboardPage() {
return (
<div>
<h1>ડેશબોર્ડ</h1>
<div className="layout">
<Suspense fallback={<p>નેવિગેશન લોડ થઈ રહ્યું છે...</p>}>
<Sidebar />
</Suspense>
<main>
<Suspense fallback={<ProfileSkeleton />}>
<MainContent />
</Suspense>
<Suspense fallback={<ActivityFeedSkeleton />}>
<ActivityFeed />
</Suspense>
</main>
</div>
</div>
);
}
આ માળખા સાથે:
Sidebar
જેવો તેનો ડેટા તૈયાર થાય કે તરત જ દેખાઈ શકે છે, ભલે મુખ્ય કન્ટેન્ટ હજી લોડ થઈ રહ્યું હોય.MainContent
અનેActivityFeed
સ્વતંત્ર રીતે લોડ થઈ શકે છે. યુઝર દરેક વિભાગ માટે વિગતવાર સ્કેલેટન લોડર જુએ છે, જે એક જ, પેજ-વાઇડ સ્પિનર કરતાં વધુ સારો સંદર્ભ પૂરો પાડે છે.
આ તમને યુઝરને શક્ય તેટલી ઝડપથી ઉપયોગી કન્ટેન્ટ બતાવવાની મંજૂરી આપે છે, જે અનુભવાયેલ પર્ફોર્મન્સમાં નાટકીય રીતે સુધારો કરે છે.
UI "પોપકોર્નિંગ" ટાળવું
કેટલીકવાર, સ્ટેગર્ડ અભિગમ એક ખલેલજનક અસર તરફ દોરી શકે છે જ્યાં બહુવિધ સ્પિનર્સ ઝડપી ઉત્તરાધિકારમાં દેખાય છે અને અદૃશ્ય થઈ જાય છે, આ અસરને ઘણીવાર "પોપકોર્નિંગ" કહેવામાં આવે છે. આને ઉકેલવા માટે, તમે સસ્પેન્સ બાઉન્ડ્રીને ટ્રીમાં ઉપર ખસેડી શકો છો.
function DashboardPage() {
return (
<div>
<h1>ડેશબોર્ડ</h1>
<Suspense fallback={<DashboardSkeleton />}>
<div className="layout">
<Sidebar />
<main>
<MainContent />
<ActivityFeed />
</main>
</div>
</Suspense>
</div>
);
}
આ સંસ્કરણમાં, એક જ DashboardSkeleton
બતાવવામાં આવે છે જ્યાં સુધી બધા ચાઇલ્ડ કમ્પોનન્ટ્સ (Sidebar
, MainContent
, ActivityFeed
) નો ડેટા તૈયાર ન થઈ જાય. પછી આખું ડેશબોર્ડ એક જ સમયે દેખાય છે. નેસ્ટેડ બાઉન્ડ્રીઝ અને એક જ ઉચ્ચ-સ્તરની બાઉન્ડ્રી વચ્ચેની પસંદગી એ UX ડિઝાઇનનો નિર્ણય છે જેને સસ્પેન્સ અમલમાં મૂકવો તુચ્છ બનાવે છે.
એરર બાઉન્ડ્રીઝ સાથે એરર હેન્ડલિંગ
સસ્પેન્સ પ્રોમિસની પેન્ડિંગ સ્થિતિને સંભાળે છે, પરંતુ રિજેક્ટેડ સ્થિતિનું શું? જો કોઈ કમ્પોનન્ટ દ્વારા થ્રો કરાયેલ પ્રોમિસ રિજેક્ટ થાય છે (દા.ત., નેટવર્ક એરર), તો તેને React માં કોઈપણ અન્ય રેન્ડરિંગ એરરની જેમ ગણવામાં આવશે.
આનો ઉકેલ એરર બાઉન્ડ્રીઝ (Error Boundaries) નો ઉપયોગ કરવાનો છે. એરર બાઉન્ડ્રી એ એક ક્લાસ કમ્પોનન્ટ છે જે એક વિશિષ્ટ લાઇફસાયકલ મેથડ, componentDidCatch()
અથવા સ્ટેટિક મેથડ getDerivedStateFromError()
ને વ્યાખ્યાયિત કરે છે. તે તેના ચાઇલ્ડ કમ્પોનન્ટ ટ્રીમાં ક્યાંય પણ JavaScript એરર્સને પકડે છે, તે એરર્સને લોગ કરે છે, અને ફોલબેક UI પ્રદર્શિત કરે છે.
અહીં એક સરળ એરર બાઉન્ડ્રી કમ્પોનન્ટ છે:
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
// સ્ટેટ અપડેટ કરો જેથી આગલું રેન્ડર ફોલબેક UI બતાવે.
return { hasError: true, error: error };
}
componentDidCatch(error, errorInfo) {
// તમે એરરને એરર રિપોર્ટિંગ સેવામાં પણ લોગ કરી શકો છો
console.error("એક એરર પકડાઈ:", error, errorInfo);
}
render() {
if (this.state.hasError) {
// તમે કોઈપણ કસ્ટમ ફોલબેક UI રેન્ડર કરી શકો છો
return <h1>કંઈક ખોટું થયું. કૃપા કરીને ફરી પ્રયાસ કરો.</h1>;
}
return this.props.children;
}
}
પછી તમે એરર બાઉન્ડ્રીઝને સસ્પેન્સ સાથે જોડીને એક મજબૂત સિસ્ટમ બનાવી શકો છો જે ત્રણેય સ્થિતિઓને સંભાળે છે: પેન્ડિંગ, સફળતા અને એરર.
import { Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';
import { UserProfile } from './UserProfile';
function App() {
return (
<div>
<h2>યુઝર માહિતી</h2>
<ErrorBoundary>
<Suspense fallback={<p>લોડ થઈ રહ્યું છે...</p>}>
<UserProfile userId={123} />
</Suspense>
</ErrorBoundary>
</div>
);
}
આ પેટર્ન સાથે, જો UserProfile
ની અંદર ડેટા ફેચ સફળ થાય, તો પ્રોફાઇલ બતાવવામાં આવે છે. જો તે પેન્ડિંગ હોય, તો સસ્પેન્સ ફોલબેક બતાવવામાં આવે છે. જો તે નિષ્ફળ જાય, તો એરર બાઉન્ડ્રીનો ફોલબેક બતાવવામાં આવે છે. લોજિક ડિક્લેરેટિવ, કમ્પોઝિશનલ અને સમજવામાં સરળ છે.
ટ્રાન્ઝિશન્સ: નોન-બ્લોકિંગ UI અપડેટ્સની ચાવી
આ કોયડાનો એક અંતિમ ભાગ છે. એક યુઝર ઇન્ટરેક્શનનો વિચાર કરો જે નવો ડેટા ફેચ ટ્રિગર કરે છે, જેમ કે અલગ યુઝર પ્રોફાઇલ જોવા માટે "આગળ" બટન પર ક્લિક કરવું. ઉપરના સેટઅપ સાથે, જે ક્ષણે બટન પર ક્લિક કરવામાં આવે છે અને userId
પ્રોપ બદલાય છે, UserProfile
કમ્પોનન્ટ ફરીથી સસ્પેન્ડ થશે. આનો અર્થ એ છે કે હાલમાં દૃશ્યમાન પ્રોફાઇલ અદૃશ્ય થઈ જશે અને લોડિંગ ફોલબેક દ્વારા બદલાઈ જશે. આ અચાનક અને વિક્ષેપકારક લાગી શકે છે.
અહીં ટ્રાન્ઝિશન્સ (transitions) આવે છે. ટ્રાન્ઝિશન્સ React 18 માં એક નવી સુવિધા છે જે તમને અમુક સ્ટેટ અપડેટ્સને બિન-તાકીદના તરીકે ચિહ્નિત કરવા દે છે. જ્યારે કોઈ સ્ટેટ અપડેટ ટ્રાન્ઝિશનમાં લપેટાયેલું હોય, ત્યારે React જૂના UI (જૂનું કન્ટેન્ટ) પ્રદર્શિત કરવાનું ચાલુ રાખશે જ્યારે તે બેકગ્રાઉન્ડમાં નવા કન્ટેન્ટની તૈયારી કરે છે. તે ફક્ત ત્યારે જ UI અપડેટને કમિટ કરશે જ્યારે નવું કન્ટેન્ટ પ્રદર્શિત કરવા માટે તૈયાર હોય.
આ માટે પ્રાથમિક API useTransition
હુક છે.
import React, { useState, useTransition, Suspense } from 'react';
import { UserProfile } from './UserProfile';
function ProfileSwitcher() {
const [userId, setUserId] = useState(1);
const [isPending, startTransition] = useTransition();
const handleNextClick = () => {
startTransition(() => {
setUserId(id => id + 1);
});
};
return (
<div>
<button onClick={handleNextClick} disabled={isPending}>
આગલો યુઝર
</button>
{isPending && <span> નવી પ્રોફાઇલ લોડ થઈ રહી છે...</span>}
<ErrorBoundary>
<Suspense fallback={<p>પ્રારંભિક પ્રોફાઇલ લોડ થઈ રહી છે...</p>}>
<UserProfile userId={userId} />
</Suspense>
</ErrorBoundary>
</div>
);
}
હવે શું થાય છે તે અહીં છે:
userId: 1
માટે પ્રારંભિક પ્રોફાઇલ લોડ થાય છે, જે સસ્પેન્સ ફોલબેક બતાવે છે.- યુઝર "આગલો યુઝર" પર ક્લિક કરે છે.
setUserId
કોલstartTransition
માં લપેટાયેલો છે.- React મેમરીમાં નવા
userId
2 સાથેUserProfile
રેન્ડર કરવાનું શરૂ કરે છે. આનાથી તે સસ્પેન્ડ થાય છે. - મહત્વપૂર્ણ રીતે, સસ્પેન્સ ફોલબેક બતાવવાને બદલે, React જૂના UI (યુઝર 1 માટેની પ્રોફાઇલ) ને સ્ક્રીન પર રાખે છે.
useTransition
દ્વારા પરત કરાયેલisPending
બુલિયનtrue
બને છે, જે આપણને જૂના કન્ટેન્ટને અનમાઉન્ટ કર્યા વિના એક સૂક્ષ્મ, ઇનલાઇન લોડિંગ ઇન્ડિકેટર બતાવવાની મંજૂરી આપે છે.- એકવાર યુઝર 2 માટે ડેટા ફેચ થઈ જાય અને
UserProfile
સફળતાપૂર્વક રેન્ડર કરી શકે, React અપડેટને કમિટ કરે છે, અને નવી પ્રોફાઇલ સરળતાથી દેખાય છે.
ટ્રાન્ઝિશન્સ નિયંત્રણનું અંતિમ સ્તર પ્રદાન કરે છે, જે તમને અત્યાધુનિક અને યુઝર-ફ્રેન્ડલી લોડિંગ અનુભવો બનાવવામાં સક્ષમ બનાવે છે જે ક્યારેય ખલેલજનક લાગતા નથી.
શ્રેષ્ઠ પ્રયાસો અને વૈશ્વિક વિચારણાઓ
- બાઉન્ડ્રીઝને વ્યૂહાત્મક રીતે મૂકો: દરેક નાના કમ્પોનન્ટને સસ્પેન્સ બાઉન્ડ્રીમાં ન લપેટો. તેમને તમારી એપ્લિકેશનમાં તાર્કિક બિંદુઓ પર મૂકો જ્યાં લોડિંગ સ્ટેટ યુઝર માટે અર્થપૂર્ણ હોય, જેમ કે પેજ, મોટો પેનલ, અથવા મહત્વપૂર્ણ વિજેટ.
- અર્થપૂર્ણ ફોલબેક્સ ડિઝાઇન કરો: સામાન્ય સ્પિનર્સ સરળ છે, પરંતુ સ્કેલેટન લોડર્સ જે લોડ થઈ રહેલા કન્ટેન્ટના આકારનું અનુકરણ કરે છે તે વધુ સારો યુઝર અનુભવ પ્રદાન કરે છે. તેઓ લેઆઉટ શિફ્ટ ઘટાડે છે અને યુઝરને કયું કન્ટેન્ટ દેખાશે તેની અપેક્ષા રાખવામાં મદદ કરે છે.
- ઍક્સેસિબિલિટીનો વિચાર કરો: લોડિંગ સ્ટેટ્સ બતાવતી વખતે, ખાતરી કરો કે તે ઍક્સેસિબલ છે. સ્ક્રીન રીડર યુઝર્સને જાણ કરવા માટે કે કન્ટેન્ટ અપડેટ થઈ રહ્યું છે, કન્ટેન્ટ કન્ટેનર પર
aria-busy="true"
જેવા ARIA એટ્રિબ્યુટ્સનો ઉપયોગ કરો. - સર્વર કમ્પોનન્ટ્સને અપનાવો: સસ્પેન્સ એ React સર્વર કમ્પોનન્ટ્સ (RSC) માટે એક પાયાની ટેકનોલોજી છે. Next.js જેવા ફ્રેમવર્ક્સનો ઉપયોગ કરતી વખતે, સસ્પેન્સ તમને સર્વર પરથી HTML સ્ટ્રીમ કરવાની મંજૂરી આપે છે કારણ કે ડેટા ઉપલબ્ધ થાય છે, જે વૈશ્વિક પ્રેક્ષકો માટે અત્યંત ઝડપી પ્રારંભિક પેજ લોડ તરફ દોરી જાય છે.
- ઇકોસિસ્ટમનો લાભ લો: અંતર્ગત સિદ્ધાંતોને સમજવું મહત્વપૂર્ણ છે, પરંતુ પ્રોડક્શન એપ્લિકેશન્સ માટે, TanStack Query, SWR, અથવા Relay જેવી યુદ્ધ-પરીક્ષિત લાઇબ્રેરીઓ પર આધાર રાખો. તેઓ કેશિંગ, ડિડુપ્લિકેશન અને અન્ય જટિલતાઓને સંભાળે છે જ્યારે સીમલેસ સસ્પેન્સ ઇન્ટિગ્રેશન પ્રદાન કરે છે.
નિષ્કર્ષ
React સસ્પેન્સ ફક્ત એક નવી સુવિધા કરતાં વધુ રજૂ કરે છે; તે React એપ્લિકેશન્સમાં આપણે અસિંક્રોનિસિટીનો કેવી રીતે સંપર્ક કરીએ છીએ તેમાં એક મૂળભૂત ઉત્ક્રાંતિ છે. મેન્યુઅલ, ઇમ્પેરેટિવ લોડિંગ ફ્લેગ્સથી દૂર જઈને અને ડિક્લેરેટિવ મોડેલને અપનાવીને, આપણે એવા કમ્પોનન્ટ્સ લખી શકીએ છીએ જે વધુ સ્વચ્છ, વધુ સ્થિતિસ્થાપક અને કમ્પોઝ કરવા માટે સરળ હોય.
પેન્ડિંગ સ્ટેટ્સ માટે <Suspense>
, નિષ્ફળતા સ્ટેટ્સ માટે એરર બાઉન્ડ્રીઝ, અને સીમલેસ અપડેટ્સ માટે useTransition
ને જોડીને, તમારી પાસે એક સંપૂર્ણ અને શક્તિશાળી ટૂલકિટ ઉપલબ્ધ છે. તમે સરળ લોડિંગ સ્પિનર્સથી માંડીને જટિલ, સ્ટેગર્ડ ડેશબોર્ડ રિવિલ્સ સુધી બધું જ ન્યૂનતમ, અનુમાનિત કોડ સાથે ગોઠવી શકો છો. જેમ જેમ તમે તમારા પ્રોજેક્ટ્સમાં સસ્પેન્સને એકીકૃત કરવાનું શરૂ કરશો, તેમ તમને જણાશે કે તે ફક્ત તમારી એપ્લિકેશનના પર્ફોર્મન્સ અને યુઝર અનુભવને સુધારતું નથી, પરંતુ તમારા સ્ટેટ મેનેજમેન્ટ લોજિકને પણ નાટકીય રીતે સરળ બનાવે છે, જે તમને ખરેખર મહત્વની બાબતો પર ધ્યાન કેન્દ્રિત કરવાની મંજૂરી આપે છે: શ્રેષ્ઠ સુવિધાઓ બનાવવી.