മലയാളം

ഡാറ്റാ ഫെച്ചിംഗിനായി റിയാക്റ്റ് സസ്പെൻസ് ഉപയോഗിക്കുന്നതിൽ വൈദഗ്ദ്ധ്യം നേടുക. ലോഡിംഗ് സ്റ്റേറ്റുകൾ ഡിക്ലറേറ്റീവ് ആയി കൈകാര്യം ചെയ്യാനും ട്രാൻസിഷനുകളിലൂടെ UX മെച്ചപ്പെടുത്താനും എറർ ബൗണ്ടറികൾ ഉപയോഗിച്ച് പിശകുകൾ കൈകാര്യം ചെയ്യാനും പഠിക്കുക.

റിയാക്റ്റ് സസ്പെൻസ് ബൗണ്ടറികൾ: ഡിക്ലറേറ്റീവ് ലോഡിംഗ് സ്റ്റേറ്റ് മാനേജ്മെൻ്റിനെക്കുറിച്ചുള്ള ഒരു സമഗ്രമായ വിലയിരുത്തൽ

ആധുനിക വെബ് ഡെവലപ്‌മെൻ്റിൻ്റെ ലോകത്ത്, തടസ്സമില്ലാത്തതും പ്രതികരണശേഷിയുള്ളതുമായ ഒരു ഉപയോക്തൃ അനുഭവം സൃഷ്ടിക്കുന്നത് പരമപ്രധാനമാണ്. ഡെവലപ്പർമാർ നേരിടുന്ന ഏറ്റവും സ്ഥിരമായ വെല്ലുവിളികളിലൊന്ന് ലോഡിംഗ് സ്റ്റേറ്റുകൾ കൈകാര്യം ചെയ്യുക എന്നതാണ്. ഒരു ഉപയോക്തൃ പ്രൊഫൈലിനായി ഡാറ്റ ലഭ്യമാക്കുന്നത് മുതൽ ഒരു ആപ്ലിക്കേഷൻ്റെ പുതിയ വിഭാഗം ലോഡുചെയ്യുന്നത് വരെ, കാത്തിരിപ്പിൻ്റെ നിമിഷങ്ങൾ നിർണ്ണായകമാണ്. ചരിത്രപരമായി, ഇത് നമ്മുടെ കമ്പോണൻ്റുകളിൽ ചിതറിക്കിടക്കുന്ന isLoading, isFetching, hasError പോലുള്ള ബൂളിയൻ ഫ്ലാഗുകളുടെ ഒരു സങ്കീർണ്ണമായ വലയായിരുന്നു. ഈ ഇംപറേറ്റീവ് സമീപനം നമ്മുടെ കോഡിനെ അലങ്കോലപ്പെടുത്തുന്നു, ലോജിക്കിനെ സങ്കീർണ്ണമാക്കുന്നു, കൂടാതെ റേസ് കണ്ടീഷനുകൾ പോലുള്ള ബഗുകളുടെ ഒരു സാധാരണ ഉറവിടവുമാണ്.

ഇവിടെയാണ് റിയാക്റ്റ് സസ്പെൻസ് വരുന്നത്. തുടക്കത്തിൽ React.lazy() ഉപയോഗിച്ച് കോഡ്-സ്പ്ലിറ്റിംഗിനായി അവതരിപ്പിച്ചെങ്കിലും, ഇതിൻ്റെ കഴിവുകൾ റിയാക്റ്റ് 18-ൽ അസിൻക്രണസ് പ്രവർത്തനങ്ങൾ, പ്രത്യേകിച്ച് ഡാറ്റാ ഫെച്ചിംഗ്, കൈകാര്യം ചെയ്യുന്നതിനുള്ള ശക്തവും ഫസ്റ്റ്-ക്ലാസ് സംവിധാനവുമായി ഗണ്യമായി വികസിച്ചു. ലോഡിംഗ് സ്റ്റേറ്റുകൾ ഡിക്ലറേറ്റീവ് രീതിയിൽ കൈകാര്യം ചെയ്യാൻ സസ്പെൻസ് നമ്മെ അനുവദിക്കുന്നു, ഇത് നമ്മുടെ കമ്പോണൻ്റുകളെക്കുറിച്ച് എഴുതുകയും ചിന്തിക്കുകയും ചെയ്യുന്ന രീതിയെ അടിസ്ഥാനപരമായി മാറ്റുന്നു. "ഞാൻ ലോഡ് ചെയ്യുകയാണോ?" എന്ന് ചോദിക്കുന്നതിനു പകരം, നമ്മുടെ കമ്പോണൻ്റുകൾക്ക് ലളിതമായി പറയാൻ കഴിയും, "റെൻഡർ ചെയ്യാൻ എനിക്ക് ഈ ഡാറ്റ ആവശ്യമാണ്. ഞാൻ കാത്തിരിക്കുമ്പോൾ, ദയവായി ഈ ഫാൾബാക്ക് UI കാണിക്കുക."

ഈ സമഗ്രമായ ഗൈഡ് നിങ്ങളെ സ്റ്റേറ്റ് മാനേജ്മെൻ്റിൻ്റെ പരമ്പരാഗത രീതികളിൽ നിന്ന് റിയാക്റ്റ് സസ്പെൻസിൻ്റെ ഡിക്ലറേറ്റീവ് മാതൃകയിലേക്ക് ഒരു യാത്ര കൊണ്ടുപോകും. സസ്പെൻസ് ബൗണ്ടറികൾ എന്താണെന്നും, കോഡ്-സ്പ്ലിറ്റിംഗിനും ഡാറ്റാ ഫെച്ചിംഗിനും അവ എങ്ങനെ പ്രവർത്തിക്കുന്നുവെന്നും, നിങ്ങളുടെ ഉപയോക്താക്കളെ നിരാശപ്പെടുത്തുന്നതിനു പകരം അവരെ സന്തോഷിപ്പിക്കുന്ന സങ്കീർണ്ണമായ ലോഡിംഗ് UI-കൾ എങ്ങനെ ക്രമീകരിക്കാമെന്നും നമ്മൾ പര്യവേക്ഷണം ചെയ്യും.

പഴയ രീതി: മാനുവൽ ലോഡിംഗ് സ്റ്റേറ്റുകളുടെ ബുദ്ധിമുട്ട്

സസ്പെൻസിൻ്റെ ഭംഗി പൂർണ്ണമായി മനസ്സിലാക്കുന്നതിന് മുമ്പ്, അത് പരിഹരിക്കുന്ന പ്രശ്നം മനസ്സിലാക്കേണ്ടത് അത്യാവശ്യമാണ്. 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(() => {
    // Reset state for new 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('Network response was not ok');
        }
        const data = await response.json();
        setUser(data);
      } catch (err) {
        setError(err);
      } finally {
        setIsLoading(false);
      }
    };

    fetchUser();
  }, [userId]); // Re-fetch when userId changes

  if (isLoading) {
    return <p>Loading profile...</p>;
  }

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

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
    </div>
  );
}

ഈ പാറ്റേൺ പ്രവർത്തനക്ഷമമാണ്, പക്ഷേ ഇതിന് നിരവധി പോരായ്മകളുണ്ട്:

റിയാക്റ്റ് സസ്പെൻസിൻ്റെ വരവ്: ഒരു മാതൃകാപരമായ മാറ്റം

സസ്പെൻസ് ഈ മോഡലിനെ തലകീഴായി മാറ്റുന്നു. കമ്പോണൻ്റ് ആന്തരികമായി ലോഡിംഗ് സ്റ്റേറ്റ് കൈകാര്യം ചെയ്യുന്നതിനു പകരം, ഒരു അസിൻക്രണസ് പ്രവർത്തനത്തിലുള്ള അതിൻ്റെ ആശ്രിതത്വം അത് നേരിട്ട് റിയാക്റ്റുമായി ആശയവിനിമയം നടത്തുന്നു. അതിന് ആവശ്യമായ ഡാറ്റ ഇതുവരെ ലഭ്യമല്ലെങ്കിൽ, കമ്പോണൻ്റ് റെൻഡറിംഗ് "സസ്പെൻഡ്" ചെയ്യുന്നു.

ഒരു കമ്പോണൻ്റ് സസ്പെൻഡ് ചെയ്യുമ്പോൾ, റിയാക്റ്റ് ഏറ്റവും അടുത്തുള്ള സസ്പെൻസ് ബൗണ്ടറി കണ്ടെത്താൻ കമ്പോണൻ്റ് ട്രീയിലൂടെ മുകളിലേക്ക് പോകുന്നു. <Suspense> ഉപയോഗിച്ച് നിങ്ങളുടെ ട്രീയിൽ നിർവചിക്കുന്ന ഒരു കമ്പോണൻ്റാണ് സസ്പെൻസ് ബൗണ്ടറി. ഈ ബൗണ്ടറി അതിനുള്ളിലെ എല്ലാ കമ്പോണൻ്റുകളും അവയുടെ ഡാറ്റാ ഡിപൻഡൻസികൾ പരിഹരിക്കുന്നതുവരെ ഒരു ഫാൾബാക്ക് UI (ഒരു സ്പിന്നർ അല്ലെങ്കിൽ ഒരു സ്കെലിട്ടൺ ലോഡർ പോലെ) റെൻഡർ ചെയ്യും.

പ്രധാന ആശയം, ഡാറ്റാ ഡിപൻഡൻസിയെ അത് ആവശ്യമുള്ള കമ്പോണൻ്റുമായി ഒരുമിച്ച് സ്ഥാപിക്കുകയും, ലോഡിംഗ് UI-യെ കമ്പോണൻ്റ് ട്രീയിലെ ഉയർന്ന തലത്തിൽ കേന്ദ്രീകരിക്കുകയും ചെയ്യുക എന്നതാണ്. ഇത് കമ്പോണൻ്റ് ലോജിക് വൃത്തിയാക്കുകയും ഉപയോക്താവിൻ്റെ ലോഡിംഗ് അനുഭവത്തിൽ നിങ്ങൾക്ക് ശക്തമായ നിയന്ത്രണം നൽകുകയും ചെയ്യുന്നു.

ഒരു കമ്പോണൻ്റ് എങ്ങനെയാണ് "സസ്പെൻഡ്" ചെയ്യുന്നത്?

സസ്പെൻസിൻ്റെ പിന്നിലെ മാന്ത്രികത ഒറ്റനോട്ടത്തിൽ അസാധാരണമായി തോന്നിയേക്കാവുന്ന ഒരു പാറ്റേണിലാണ്: ഒരു പ്രോമിസ് ത്രോ ചെയ്യുക (throwing a Promise). സസ്പെൻസ്-എനേബിൾഡ് ഡാറ്റാ സോഴ്സ് ഇങ്ങനെ പ്രവർത്തിക്കുന്നു:

  1. ഒരു കമ്പോണൻ്റ് ഡാറ്റ ആവശ്യപ്പെടുമ്പോൾ, ഡാറ്റാ സോഴ്സ് അത് കാഷെ ചെയ്തിട്ടുണ്ടോ എന്ന് പരിശോധിക്കുന്നു.
  2. ഡാറ്റ ലഭ്യമാണെങ്കിൽ, അത് സിൻക്രണസ് ആയി തിരികെ നൽകുന്നു.
  3. ഡാറ്റ ലഭ്യമല്ലെങ്കിൽ (അതായത്, അത് നിലവിൽ ഫെച്ച് ചെയ്യുകയാണെങ്കിൽ), ഡാറ്റാ സോഴ്സ് നടന്നുകൊണ്ടിരിക്കുന്ന ഫെച്ച് അഭ്യർത്ഥനയെ പ്രതിനിധീകരിക്കുന്ന പ്രോമിസ് ത്രോ ചെയ്യുന്നു.

റിയാക്റ്റ് ഈ ത്രോ ചെയ്ത പ്രോമിസിനെ പിടിക്കുന്നു. ഇത് നിങ്ങളുടെ ആപ്പിനെ ക്രാഷ് ചെയ്യുന്നില്ല. പകരം, ഇത് ഒരു സിഗ്നലായി വ്യാഖ്യാനിക്കുന്നു: "ഈ കമ്പോണൻ്റ് ഇതുവരെ റെൻഡർ ചെയ്യാൻ തയ്യാറായിട്ടില്ല. ഇത് താൽക്കാലികമായി നിർത്തി, ഒരു ഫാൾബാക്ക് കാണിക്കുന്നതിന് മുകളിൽ ഒരു സസ്പെൻസ് ബൗണ്ടറിക്കായി തിരയുക." പ്രോമിസ് റിസോൾവ് ചെയ്തുകഴിഞ്ഞാൽ, റിയാക്റ്റ് കമ്പോണൻ്റിനെ വീണ്ടും റെൻഡർ ചെയ്യാൻ ശ്രമിക്കും, അത് ഇപ്പോൾ അതിൻ്റെ ഡാറ്റ സ്വീകരിക്കുകയും വിജയകരമായി റെൻഡർ ചെയ്യുകയും ചെയ്യും.

<Suspense> ബൗണ്ടറി: നിങ്ങളുടെ ലോഡിംഗ് UI ഡിക്ലറേറ്റർ

<Suspense> കമ്പോണൻ്റാണ് ഈ പാറ്റേണിൻ്റെ ഹൃദയം. ഇത് ഉപയോഗിക്കാൻ അവിശ്വസനീയമാംവിധം ലളിതമാണ്, ആവശ്യമായ ഒരൊറ്റ പ്രോപ്പ് എടുക്കുന്നു: fallback.


import { Suspense } from 'react';

function App() {
  return (
    <div>
      <h1>My Application</h1>
      <Suspense fallback={<p>Loading content...</p>}>
        <SomeComponentThatFetchesData />
      </Suspense>
    </div>
  );
}

ഈ ഉദാഹരണത്തിൽ, SomeComponentThatFetchesData സസ്പെൻഡ് ചെയ്യുകയാണെങ്കിൽ, ഡാറ്റ തയ്യാറാകുന്നതുവരെ ഉപയോക്താവിന് "Loading content..." എന്ന സന്ദേശം കാണാനാകും. ഫാൾബാക്ക് ഒരു ലളിതമായ സ്ട്രിംഗ് മുതൽ സങ്കീർണ്ണമായ ഒരു സ്കെലിട്ടൺ കമ്പോണൻ്റ് വരെ സാധുവായ ഏത് റിയാക്റ്റ് നോഡും ആകാം.

ക്ലാസിക് ഉപയോഗം: React.lazy() ഉപയോഗിച്ച് കോഡ് സ്പ്ലിറ്റിംഗ്

സസ്പെൻസിൻ്റെ ഏറ്റവും സ്ഥാപിതമായ ഉപയോഗം കോഡ് സ്പ്ലിറ്റിംഗിനാണ്. ഒരു കമ്പോണൻ്റിൻ്റെ ജാവാസ്ക്രിപ്റ്റ് യഥാർത്ഥത്തിൽ ആവശ്യമുള്ളതുവരെ ലോഡുചെയ്യുന്നത് മാറ്റിവയ്ക്കാൻ ഇത് നിങ്ങളെ അനുവദിക്കുന്നു.


import React, { Suspense, lazy } from 'react';

// This component's code won't be in the initial bundle.
const HeavyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <div>
      <h2>Some content that loads immediately</h2>
      <Suspense fallback={<div>Loading component...</div>}>
        <HeavyComponent />
      </Suspense>
    </div>
  );
}

ഇവിടെ, റിയാക്റ്റ് HeavyComponent-നെ ആദ്യമായി റെൻഡർ ചെയ്യാൻ ശ്രമിക്കുമ്പോൾ മാത്രമേ അതിൻ്റെ ജാവാസ്ക്രിപ്റ്റ് ഫെച്ച് ചെയ്യുകയുള്ളൂ. ഇത് ഫെച്ച് ചെയ്യുകയും പാഴ്സ് ചെയ്യുകയും ചെയ്യുമ്പോൾ, സസ്പെൻസ് ഫാൾബാക്ക് പ്രദർശിപ്പിക്കും. പ്രാരംഭ പേജ് ലോഡ് സമയം മെച്ചപ്പെടുത്തുന്നതിനുള്ള ശക്തമായ ഒരു സാങ്കേതികതയാണിത്.

ആധുനിക അതിർത്തി: സസ്പെൻസ് ഉപയോഗിച്ച് ഡാറ്റാ ഫെച്ചിംഗ്

റിയാക്റ്റ് സസ്പെൻസ് മെക്കാനിസം നൽകുമ്പോൾ, അത് ഒരു പ്രത്യേക ഡാറ്റാ-ഫെച്ചിംഗ് ക്ലയൻ്റ് നൽകുന്നില്ല. ഡാറ്റാ ഫെച്ചിംഗിനായി സസ്പെൻസ് ഉപയോഗിക്കുന്നതിന്, അതുമായി സംയോജിപ്പിക്കുന്ന ഒരു ഡാറ്റാ സോഴ്സ് നിങ്ങൾക്ക് ആവശ്യമാണ് (അതായത്, ഡാറ്റ പെൻഡിംഗ് ആയിരിക്കുമ്പോൾ ഒരു പ്രോമിസ് ത്രോ ചെയ്യുന്നത്).

റിലേ, നെക്സ്റ്റ്.ജെഎസ് പോലുള്ള ഫ്രെയിംവർക്കുകൾക്ക് സസ്പെൻസിനായി ബിൽറ്റ്-ഇൻ, ഫസ്റ്റ്-ക്ലാസ് പിന്തുണയുണ്ട്. ടാൻസ്റ്റാക്ക് ക്വറി (മുമ്പ് റിയാക്റ്റ് ക്വറി), എസ്.ഡബ്ല്യു.ആർ പോലുള്ള ജനപ്രിയ ഡാറ്റാ-ഫെച്ചിംഗ് ലൈബ്രറികളും ഇതിനായി പരീക്ഷണാത്മകമോ പൂർണ്ണമോ ആയ പിന്തുണ വാഗ്ദാനം ചെയ്യുന്നു.

ആശയം മനസ്സിലാക്കാൻ, fetch API-യെ സസ്പെൻസ്-അനുയോജ്യമാക്കുന്നതിന് വളരെ ലളിതവും ആശയപരവുമായ ഒരു റാപ്പർ നമുക്ക് ഉണ്ടാക്കാം. ശ്രദ്ധിക്കുക: ഇത് വിദ്യാഭ്യാസപരമായ ആവശ്യങ്ങൾക്കായുള്ള ഒരു ലളിതമായ ഉദാഹരണമാണ്, ഇത് പ്രൊഡക്ഷന് തയ്യാറല്ല. ഇതിന് ശരിയായ കാഷിംഗും എറർ ഹാൻഡ്ലിംഗ് സങ്കീർണ്ണതകളും ഇല്ല.


// data-fetcher.js
// A simple cache to store results
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; // This is the magic!
  }
  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(`Fetch failed with status ${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';

// The component that actually uses the data
function ProfileDetails({ userId }) {
  // Try to read the data. If it's not ready, this will suspend.
  const user = fetchData(`https://api.example.com/users/${userId}`);

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
    </div>
  );
}

// The parent component that defines the loading state UI
export function UserProfile({ userId }) {
  return (
    <Suspense fallback={<p>Loading profile...</p>}>
      <ProfileDetails userId={userId} />
    </Suspense>
  );
}

വ്യത്യാസം നോക്കൂ! ProfileDetails കമ്പോണൻ്റ് വൃത്തിയുള്ളതും ഡാറ്റ റെൻഡർ ചെയ്യുന്നതിൽ മാത്രം ശ്രദ്ധ കേന്ദ്രീകരിക്കുന്നതുമാണ്. ഇതിന് isLoading അല്ലെങ്കിൽ error സ്റ്റേറ്റുകളില്ല. അത് ആവശ്യമായ ഡാറ്റ അഭ്യർത്ഥിക്കുക മാത്രം ചെയ്യുന്നു. ഒരു ലോഡിംഗ് ഇൻഡിക്കേറ്റർ കാണിക്കുന്നതിനുള്ള ഉത്തരവാദിത്തം പാരൻ്റ് കമ്പോണൻ്റായ UserProfile-ലേക്ക് മാറ്റിയിരിക്കുന്നു, അത് കാത്തിരിക്കുമ്പോൾ എന്ത് കാണിക്കണമെന്ന് ഡിക്ലറേറ്റീവ് ആയി പ്രസ്താവിക്കുന്നു.

സങ്കീർണ്ണമായ ലോഡിംഗ് സ്റ്റേറ്റുകൾ ക്രമീകരിക്കുന്നു

ഒന്നിലധികം അസിൻക്രണസ് ഡിപൻഡൻസികളുള്ള സങ്കീർണ്ണമായ UI-കൾ നിർമ്മിക്കുമ്പോൾ സസ്പെൻസിൻ്റെ യഥാർത്ഥ ശക്തി വ്യക്തമാകും.

ഒരു സ്റ്റാഗേർഡ് UI-യ്ക്കായി നെസ്റ്റഡ് സസ്പെൻസ് ബൗണ്ടറികൾ

കൂടുതൽ മെച്ചപ്പെട്ട ലോഡിംഗ് അനുഭവം സൃഷ്ടിക്കാൻ നിങ്ങൾക്ക് സസ്പെൻസ് ബൗണ്ടറികൾ നെസ്റ്റ് ചെയ്യാൻ കഴിയും. ഒരു സൈഡ്ബാർ, ഒരു പ്രധാന ഉള്ളടക്ക ഏരിയ, സമീപകാല പ്രവർത്തനങ്ങളുടെ ഒരു ലിസ്റ്റ് എന്നിവയുള്ള ഒരു ഡാഷ്ബോർഡ് പേജ് സങ്കൽപ്പിക്കുക. ഇവയോരോന്നിനും അതിൻ്റേതായ ഡാറ്റ ഫെച്ച് ആവശ്യമായി വന്നേക്കാം.


function DashboardPage() {
  return (
    <div>
      <h1>Dashboard</h1>
      <div className="layout">
        <Suspense fallback={<p>Loading navigation...</p>}>
          <Sidebar />
        </Suspense>

        <main>
          <Suspense fallback={<ProfileSkeleton />}>
            <MainContent />
          </Suspense>

          <Suspense fallback={<ActivityFeedSkeleton />}>
            <ActivityFeed />
          </Suspense>
        </main>
      </div>
    </div>
  );
}

ഈ ഘടന ഉപയോഗിച്ച്:

ഇത് ഉപയോക്താവിന് ഉപയോഗപ്രദമായ ഉള്ളടക്കം എത്രയും വേഗം കാണിക്കാൻ നിങ്ങളെ അനുവദിക്കുന്നു, ഇത് പെർസീവ്ഡ് പെർഫോമൻസ് ഗണ്യമായി മെച്ചപ്പെടുത്തുന്നു.

UI "പോപ്പ്കോണിംഗ്" ഒഴിവാക്കുന്നു

ചിലപ്പോൾ, സ്റ്റാഗേർഡ് സമീപനം ഒന്നിലധികം സ്പിന്നറുകൾ പെട്ടെന്ന് പ്രത്യക്ഷപ്പെടുകയും അപ്രത്യക്ഷമാവുകയും ചെയ്യുന്ന ഒരു അസുഖകരമായ ഫലത്തിലേക്ക് നയിച്ചേക്കാം, ഇതിനെ "പോപ്പ്കോണിംഗ്" എന്ന് വിളിക്കുന്നു. ഇത് പരിഹരിക്കാൻ, നിങ്ങൾക്ക് സസ്പെൻസ് ബൗണ്ടറി ട്രീയിൽ മുകളിലേക്ക് നീക്കാൻ കഴിയും.


function DashboardPage() {
  return (
    <div>
      <h1>Dashboard</h1>
      <Suspense fallback={<DashboardSkeleton />}>
        <div className="layout">
          <Sidebar />
          <main>
            <MainContent />
            <ActivityFeed />
          </main>
        </div>
      </Suspense>
    </div>
  );
}

ഈ പതിപ്പിൽ, എല്ലാ ചൈൽഡ് കമ്പോണൻ്റുകളും (Sidebar, MainContent, ActivityFeed) അവയുടെ ഡാറ്റ തയ്യാറാക്കുന്നതുവരെ ഒരൊറ്റ DashboardSkeleton കാണിക്കുന്നു. തുടർന്ന് മുഴുവൻ ഡാഷ്ബോർഡും ഒരേസമയം ദൃശ്യമാകുന്നു. നെസ്റ്റഡ് ബൗണ്ടറികൾക്കും ഒരൊറ്റ ഉയർന്ന-തല ബൗണ്ടറിക്കും ഇടയിലുള്ള തിരഞ്ഞെടുപ്പ് ഒരു UX ഡിസൈൻ തീരുമാനമാണ്, അത് സസ്പെൻസ് നടപ്പിലാക്കാൻ നിസ്സാരമാക്കുന്നു.

എറർ ബൗണ്ടറികൾ ഉപയോഗിച്ച് എറർ ഹാൻഡ്ലിംഗ്

സസ്പെൻസ് ഒരു പ്രോമിസിൻ്റെ പെൻഡിംഗ് സ്റ്റേറ്റ് കൈകാര്യം ചെയ്യുന്നു, എന്നാൽ റിജക്റ്റഡ് സ്റ്റേറ്റിൻ്റെ കാര്യമോ? ഒരു കമ്പോണൻ്റ് ത്രോ ചെയ്ത പ്രോമിസ് റിജക്റ്റ് ചെയ്യുകയാണെങ്കിൽ (ഉദാഹരണത്തിന്, ഒരു നെറ്റ്‌വർക്ക് പിശക്), അത് റിയാക്റ്റിലെ മറ്റേതൊരു റെൻഡറിംഗ് പിശകും പോലെ പരിഗണിക്കപ്പെടും.

എറർ ബൗണ്ടറികൾ ഉപയോഗിക്കുക എന്നതാണ് പരിഹാരം. ഒരു എറർ ബൗണ്ടറി എന്നത് ഒരു പ്രത്യേക ലൈഫ് സൈക്കിൾ മെത്തേഡ്, componentDidCatch() അല്ലെങ്കിൽ ഒരു സ്റ്റാറ്റിക് മെത്തേഡ് getDerivedStateFromError() നിർവചിക്കുന്ന ഒരു ക്ലാസ് കമ്പോണൻ്റാണ്. ഇത് അതിൻ്റെ ചൈൽഡ് കമ്പോണൻ്റ് ട്രീയിൽ എവിടെയെങ്കിലും ജാവാസ്ക്രിപ്റ്റ് പിശകുകൾ പിടികൂടുകയും ആ പിശകുകൾ ലോഗ് ചെയ്യുകയും ഒരു ഫാൾബാക്ക് UI പ്രദർശിപ്പിക്കുകയും ചെയ്യുന്നു.

ഇവിടെ ഒരു ലളിതമായ എറർ ബൗണ്ടറി കമ്പോണൻ്റ് ഉണ്ട്:


import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true, error: error };
  }

  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service
    console.error("Caught an error:", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong. Please try again.</h1>;
    }

    return this.props.children; 
  }
}

പെൻഡിംഗ്, സക്സസ്, എറർ എന്നീ മൂന്ന് സ്റ്റേറ്റുകളും കൈകാര്യം ചെയ്യുന്ന ഒരു ശക്തമായ സിസ്റ്റം ഉണ്ടാക്കാൻ നിങ്ങൾക്ക് എറർ ബൗണ്ടറികളെ സസ്പെൻസുമായി സംയോജിപ്പിക്കാം.


import { Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';
import { UserProfile } from './UserProfile';

function App() {
  return (
    <div>
      <h2>User Information</h2>
      <ErrorBoundary>
        <Suspense fallback={<p>Loading...</p>}>
          <UserProfile userId={123} />
        </Suspense>
      </ErrorBoundary>
    </div>
  );
}

ഈ പാറ്റേൺ ഉപയോഗിച്ച്, UserProfile-നുള്ളിലെ ഡാറ്റാ ഫെച്ച് വിജയിച്ചാൽ, പ്രൊഫൈൽ കാണിക്കും. അത് പെൻഡിംഗ് ആണെങ്കിൽ, സസ്പെൻസ് ഫാൾബാക്ക് കാണിക്കും. അത് പരാജയപ്പെട്ടാൽ, എറർ ബൗണ്ടറിയുടെ ഫാൾബാക്ക് കാണിക്കും. ലോജിക് ഡിക്ലറേറ്റീവും, കമ്പോസിഷണലും, ചിന്തിക്കാൻ എളുപ്പവുമാണ്.

ട്രാൻസിഷനുകൾ: നോൺ-ബ്ലോക്കിംഗ് UI അപ്‌ഡേറ്റുകളുടെ താക്കോൽ

ഈ പസിലിന് ഒരു അവസാന ഭാഗം കൂടിയുണ്ട്. ഒരു പുതിയ ഡാറ്റാ ഫെച്ചിന് കാരണമാകുന്ന ഒരു ഉപയോക്തൃ ഇടപെടൽ പരിഗണിക്കുക, ഉദാഹരണത്തിന് മറ്റൊരു ഉപയോക്തൃ പ്രൊഫൈൽ കാണുന്നതിന് "അടുത്തത്" ബട്ടൺ ക്ലിക്കുചെയ്യുന്നത്. മുകളിലുള്ള സജ്ജീകരണം ഉപയോഗിച്ച്, ബട്ടൺ ക്ലിക്കുചെയ്ത് userId പ്രോപ്പ് മാറുമ്പോൾ, UserProfile കമ്പോണൻ്റ് വീണ്ടും സസ്പെൻഡ് ചെയ്യും. ഇതിനർത്ഥം നിലവിൽ ദൃശ്യമാകുന്ന പ്രൊഫൈൽ അപ്രത്യക്ഷമാവുകയും പകരം ലോഡിംഗ് ഫാൾബാക്ക് വരികയും ചെയ്യും. ഇത് പെട്ടെന്നുള്ളതും തടസ്സപ്പെടുത്തുന്നതുമായി തോന്നാം.

ഇവിടെയാണ് ട്രാൻസിഷനുകൾ വരുന്നത്. റിയാക്റ്റ് 18-ലെ ഒരു പുതിയ ഫീച്ചറാണ് ട്രാൻസിഷനുകൾ. ഇത് ചില സ്റ്റേറ്റ് അപ്‌ഡേറ്റുകളെ അടിയന്തിരമല്ലാത്തതായി അടയാളപ്പെടുത്താൻ നിങ്ങളെ അനുവദിക്കുന്നു. ഒരു സ്റ്റേറ്റ് അപ്‌ഡേറ്റ് ഒരു ട്രാൻസിഷനിൽ പൊതിയുമ്പോൾ, റിയാക്റ്റ് പശ്ചാത്തലത്തിൽ പുതിയ ഉള്ളടക്കം തയ്യാറാക്കുമ്പോൾ പഴയ 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}>
        Next User
      </button>

      {isPending && <span> Loading new profile...</span>}

      <ErrorBoundary>
        <Suspense fallback={<p>Loading initial profile...</p>}>
          <UserProfile userId={userId} />
        </Suspense>
      </ErrorBoundary>
    </div>
  );
}

ഇപ്പോൾ സംഭവിക്കുന്നത് ഇതാ:

  1. userId: 1-ൻ്റെ പ്രാരംഭ പ്രൊഫൈൽ ലോഡ് ചെയ്യുന്നു, സസ്പെൻസ് ഫാൾബാക്ക് കാണിക്കുന്നു.
  2. ഉപയോക്താവ് "Next User" ക്ലിക്കുചെയ്യുന്നു.
  3. setUserId കോൾ startTransition-ൽ പൊതിഞ്ഞിരിക്കുന്നു.
  4. റിയാക്റ്റ് മെമ്മറിയിൽ പുതിയ userId 2 ഉപയോഗിച്ച് UserProfile റെൻഡർ ചെയ്യാൻ തുടങ്ങുന്നു. ഇത് അതിനെ സസ്പെൻഡ് ചെയ്യാൻ കാരണമാകുന്നു.
  5. പ്രധാനമായി, സസ്പെൻസ് ഫാൾബാക്ക് കാണിക്കുന്നതിനു പകരം, റിയാക്റ്റ് പഴയ UI (ഉപയോക്താവ് 1-ൻ്റെ പ്രൊഫൈൽ) സ്ക്രീനിൽ നിലനിർത്തുന്നു.
  6. useTransition നൽകുന്ന isPending ബൂളിയൻ true ആകുന്നു, ഇത് പഴയ ഉള്ളടക്കം അൺമൗണ്ട് ചെയ്യാതെ തന്നെ സൂക്ഷ്മമായ, ഇൻലൈൻ ലോഡിംഗ് ഇൻഡിക്കേറ്റർ കാണിക്കാൻ നമ്മെ അനുവദിക്കുന്നു.
  7. ഉപയോക്താവ് 2-ൻ്റെ ഡാറ്റ ഫെച്ച് ചെയ്ത് UserProfile വിജയകരമായി റെൻഡർ ചെയ്യാൻ കഴിഞ്ഞാൽ, റിയാക്റ്റ് അപ്‌ഡേറ്റ് ചെയ്യുന്നു, പുതിയ പ്രൊഫൈൽ തടസ്സമില്ലാതെ ദൃശ്യമാകുന്നു.

ട്രാൻസിഷനുകൾ നിയന്ത്രണത്തിൻ്റെ അവസാന പാളി നൽകുന്നു, ഒരിക്കലും അസുഖകരമായി തോന്നാത്ത സങ്കീർണ്ണവും ഉപയോക്തൃ-സൗഹൃദവുമായ ലോഡിംഗ് അനുഭവങ്ങൾ നിർമ്മിക്കാൻ നിങ്ങളെ പ്രാപ്തരാക്കുന്നു.

മികച്ച രീതികളും ആഗോള പരിഗണനകളും

ഉപസംഹാരം

റിയാക്റ്റ് സസ്പെൻസ് ഒരു പുതിയ ഫീച്ചറിനേക്കാൾ ഉപരി, റിയാക്റ്റ് ആപ്ലിക്കേഷനുകളിൽ നമ്മൾ അസിൻക്രണിയെ സമീപിക്കുന്ന രീതിയിലെ ഒരു അടിസ്ഥാനപരമായ പരിണാമത്തെ പ്രതിനിധീകരിക്കുന്നു. മാനുവൽ, ഇംപറേറ്റീവ് ലോഡിംഗ് ഫ്ലാഗുകളിൽ നിന്ന് മാറി ഒരു ഡിക്ലറേറ്റീവ് മോഡൽ സ്വീകരിക്കുന്നതിലൂടെ, നമുക്ക് വൃത്തിയുള്ളതും, കൂടുതൽ പ്രതിരോധശേഷിയുള്ളതും, കമ്പോസ് ചെയ്യാൻ എളുപ്പമുള്ളതുമായ കമ്പോണൻ്റുകൾ എഴുതാൻ കഴിയും.

പെൻഡിംഗ് സ്റ്റേറ്റുകൾക്കായി <Suspense>, പരാജയ സ്റ്റേറ്റുകൾക്കായി എറർ ബൗണ്ടറികൾ, തടസ്സമില്ലാത്ത അപ്‌ഡേറ്റുകൾക്കായി useTransition എന്നിവ സംയോജിപ്പിക്കുന്നതിലൂടെ, നിങ്ങളുടെ പക്കൽ സമ്പൂർണ്ണവും ശക്തവുമായ ഒരു ടൂൾകിറ്റ് ഉണ്ട്. ലളിതമായ ലോഡിംഗ് സ്പിന്നറുകൾ മുതൽ സങ്കീർണ്ണവും, സ്റ്റാഗേർഡ് ഡാഷ്ബോർഡ് വെളിപ്പെടുത്തലുകളും വരെ കുറഞ്ഞതും പ്രവചിക്കാവുന്നതുമായ കോഡ് ഉപയോഗിച്ച് നിങ്ങൾക്ക് ക്രമീകരിക്കാൻ കഴിയും. നിങ്ങളുടെ പ്രോജക്റ്റുകളിൽ സസ്പെൻസ് സംയോജിപ്പിക്കാൻ തുടങ്ങുമ്പോൾ, ഇത് നിങ്ങളുടെ ആപ്ലിക്കേഷൻ്റെ പ്രകടനവും ഉപയോക്തൃ അനുഭവവും മെച്ചപ്പെടുത്തുക മാത്രമല്ല, നിങ്ങളുടെ സ്റ്റേറ്റ് മാനേജ്മെൻ്റ് ലോജിക് ഗണ്യമായി ലളിതമാക്കുകയും, അതുവഴി മികച്ച ഫീച്ചറുകൾ നിർമ്മിക്കുന്നതിൽ ശ്രദ്ധ കേന്ദ്രീകരിക്കാൻ നിങ്ങളെ അനുവദിക്കുകയും ചെയ്യും.