React 18 Suspense fetch data from a headless CMS PlatoBlockchain Data Intelligence. Vertical Search. Ai.

React 18 Suspense hente data fra et hovedløst CMS

For at levere en god hjemmesidebrugeroplevelse skal vi optimere den første indledende sideindlæsningstid og sidens reaktionsevne over for interaktion. Jo hurtigere din side reagerer på brugerinput – jo bedre.

Reager 18 blev designet til at hjælpe med at forbedre interaktivitet med funktioner som selektiv hydrering med Suspense at gøre hydrering ikke-blokerende og give os mere gennemsigtighed om, hvordan vores arkitektonisk valg vil påvirke vores apps brugervenlighed og ydeevne. React 18 laver store præstationsforbedringer og tilføjer support til Suspense på server-side rendering (SSR), der tillader betjening af dele af en app asynkront muligt, kan du pakke en langsom del af din app ind i Suspense-komponenten og bede React om at forsinke indlæsningen af ​​den langsomme komponent.

Reager 18 blev for nylig udgivet med funktioner designet til at hjælpe med at forbedre interaktivitet. Funktioner som selektiv hydrering med Suspense at gøre hydrering ikke-blokerende og give os mere gennemsigtighed om, hvordan vores arkitektonisk valg vil påvirke vores apps brugervenlighed og ydeevne. React 18 tilføjer understøttelse til Suspense på server-side rendering (SSR), der tillader betjening af dele af en app asynkront muligt, kan du pakke en langsom del af din app ind i Suspense-komponenten og bede React om at forsinke indlæsningen af ​​den langsomme komponent.

Gengivelse på serversiden lader dig generere HTML fra React-komponenter på serveren og sende denne HTML til dine brugere. SSR lader dine brugere se sidens indhold, før din JavaScript-pakke indlæses og kører, hvorefter JavaScript-koden indlæses og flettes sammen med HTML, ved at vedhæfte hændelseshandlere – hvilket er hydrering. I modsætning til traditionel HTML-streaming behøver det ikke at ske i top-down rækkefølge.

React-18-Suspense.jpeg
Med Suspense, kan du bede React om at sende HTML for andre komponenter først sammen med HTML for pladsholderen, som en indlæsningsspinner. Det forbedrer brugeroplevelsen og brugeropfattet latens markant.

Der er to store SSR-funktioner i React 18 låst op af Suspense:

  • Streaming af HTML på serveren.
  • Selektiv hydrering på klienten.

Lad os udforske React Datahentningsmetoder med useEffect , Suspense prøv at sammenligne praktiske løsninger til hentning af backend-data, i vores tilfælde vælger vi et hurtigt og intuitivt hovedløst CMS Cosmic. Vores kodeeksempler kan du tjekke ved et link StackBlitz.
React18

Integration Cosmic Headless CMS

Til at hente data bruger vi Kosmisk hovedløst CMS is a back-end only content management system (CMS) er et back-end-only content management system (CMS), som er bygget fra bunden som et indholdslager, der gør indhold tilgængeligt. For at integrere og få værdier fra Cosmic skal vi installere Cosmic-modulet i dit projekt.

npm i cosmicjs

yarn add cosmicjs

Opret derefter en Gratis Cosmic konto og gå til Kosmisk Dashboard Your Bucket > Settings > API Access og find din Bucket slug og API-læsenøgle og tilføj dem til at skabe Cosmic fetch-funktion fetchDataByType anmod din Cosmic bucket og hent oprettet kategoriindhold af Kosmisk forespørgsel typen categories.


import Cosmic from 'cosmicjs';

const bucket = Cosmic().bucket({
  slug: 'your_cosmic_slug',
  read_key: 'your_cosmic_read_key',
});

export async function fetchDataByType(objectType = 'categories') {
  const params = {
    query: {
      type: objectType,
    },
    props: 'title,slug,id,metadata',
    sort: '-created_at',
  };

  try {
    const data = await bucket.getObjects(params);
    return data.objects;
  } catch (error) {
    return { error };
  }
}

Cosmic leverer også kraftfulde indholdsmodelleringsfunktioner, der lader dig skabe enhver form for indhold superhurtig og multi-kanal publicering, for at realisere oprette én gang og publicere overalt.

Hent-på-render

Hent-på-render tilgang netværksanmodningen udløses i selve komponenten efter montering, anmodningen udløses ikke, før komponenten gengives. Hvis du ikke skriver en oprydningsfunktion, der ignorerer forældede svar, vil du bemærke en løbets tilstand (i React) fejl, når der er lavet to lidt forskellige anmodninger om data, og applikationen viser et andet resultat afhængigt af hvilken anmodning, der fuldføres først. Faktisk på React 18, hvis du aktiverer StrictMode i din applikation, vil du i udviklingstilstand finde ud af, at brug af useEffect vil blive påkaldt to gange, for nu vil React montere din komponent, afmontere og derefter montere den igen for at kontrollere, om din kode fungerer korrekt.

Lad os rette en datahentningsracetilstand ved at drage fordel af useEffect oprydningsfunktion. Hvis vi er okay med at lave flere anmodninger, men kun gengiver det sidste resultat, kan vi bruge et boolesk flag isMount:


import React, { useEffect, useState } from 'react';
import Category from './components/Category';
import { fetchDataByType } from './cosmic.js';

const App = () => {
  const [categories, setCategories] = useState([]);

  const getCategories = async () => {
    const result = await fetchDataByType('categories');
    if (result.length) {
      setCategories(result);
    }
  };

  useEffect(() => {
    let isMount = true;

    if (isMount) {
      getCategories();
    }

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

  return (
    <div className={cn('container', styles.container)}>
     <div className={styles.sidebar}>
      <div className={styles.collections}>
       {categories?.map((category) => (
         <Category key={category.id} info={category} />
        ))}
       </div>
      </div>
     </div>
  );
};

export default App;

Derudover, hvis en komponent gengives flere gange (som de typisk gør), bliver den forrige effekt ryddet op, før den næste effekt udføres.

I dette tilfælde har vi stadig en race-tilstand i den forstand, at flere anmodninger til Cosmic vil være under flyvningen, men kun resultaterne fra den sidste vil blive brugt.

FetchWithusEffect

useEffekt

Også som Dan Abramov forklarer, Hent-på-render giver langsom navigation mellem skærme. Hvis du har forældre- og underordnede komponenter begge er ved at hente ind useEffects, så kan den underordnede komponent ikke engang begynde at hente, før den overordnede komponent er færdig med at hente. Disse typer af ydeevneproblemer er meget almindelige i apps på én side og forårsager meget mere langsommelighed end "overdreven gengivelse", og hvis vi har en kompleks applikation med flere parallelle anmodninger, vil vi se forskellige dele af applikationen indlæses i tilfældig rækkefølge . Den mere naturlige adfærd for en applikation er at gengive ting fra top til bund.

Render-som-du-henter

Render-as-you-fetch-tilgang lader os begynde at rendere vores komponent umiddelbart efter at have udløst netværksanmodningen, og vi begynder at rendere stort set umiddelbart efter at have startet netværksanmodningen.

Suspense til datahentning

Med Suspense venter vi ikke på, at svaret kommer tilbage, før vi begynder at gengive og reducerer den samlede blokeringstid (TBT) i vores eksempel fra 106 ms til 56 ms.

Spænding

React-kerneteamets sæt af samtidige funktioner for at gøre datahentning i React nemmere. Spænding er blandt disse, og det har til formål at forenkle håndteringen af ​​indlæsningstilstande i React-komponenter. Det er en funktion til styring af asynkrone operationer i en React-app og lader dig også bruge <Suspense> at deklarativt "vente" på noget andet, inklusive data, og ikke længere skal vente på, at al JavaScript er indlæst for at begynde at hydrere dele af siden.

Først udløser vi netværksanmodningen, før vi gengiver nogen komponenter på linje et. I hovedsagen App komponent, vi pakker begge ind  CategoryCards, Main komponenter adskilt Suspense komponenter med deres reservedele.

ReactDataFetchSuspense

SuspenseCall

Hvornår App monteres for første gang, forsøger den at gengive Category og dette udløser resourseCategories.read() linje. Hvis dataene ikke er klar endnu (dvs. anmodningen er ikke blevet løst), kommunikeres de tilbage til Suspense, som derefter gengiver <p>Loading…</p>. Det samme sker for Cards , Main


import React, { Suspense } from 'react';

const App = () => {
  return (
    <main>
      <Suspense fallback={<p>Loading.....</p>}>
        <Cards />
      </Suspense>
      <div>
        <Suspense fallback={<p>Loading.....</p>}>
          <Category />
        </Suspense>
      </div>
    </main>
  );
};

export default App;

Suspense det er ikke en ny grænseflade til at hente data, da det job stadig er uddelegeret til biblioteker som f.eks. fetch eller Axios, og Suspense Det rigtige job er bare at sige "vis denne kode, mens den indlæses, og vis det, når den er færdig", intet mere end det.

Indpak din hentelogik wrapPromise.js

Vi har også brug for indpakningshentningslogik, for at kaste en undtagelse, når vores komponenter indlæser dataene, eller det mislykkedes, men returnerer derefter blot svaret, når Promise er løst med succes, og hvis det stadig afventer, kaster det løftet tilbage.




function wrapPromise(promise) {
  let status = 'pending';
  let response;

  const suspender = promise.then(
    res => {
      status = 'success';
      response = res.objects;
    },
    err => {
      status = 'error';
      response = err;
    },
  );

  const handler = {
    pending: () => {
      throw suspender;
    },
    error: () => {
      throw response;
    },
    default: () => response,
  };

  const read = () => {
    const result = handler[status] ? handler[status]() :
    handler.default();
    return result;
  };

  return { read };
}

export default wrapPromise;

I slutningen af wrapPromise funktion vil kontrollere vores løftes tilstand, og derefter returnere et objekt, der indeholder read fungere som en metode, og det er det, vores React-komponenter vil interagere med for at hente værdien af ​​løftet.

Nu bliver vi nødt til at ombryde de kosmiske opkaldsfunktioner til wrapPromise:



export function fetchDataByType(objectType = 'categories') {
  const params = {
    query: {
      type: objectType,
    },
    props: 'title,slug,id,metadata',
    sort: '-created_at',
  };

  const data = bucket.getObjects(params);
  return wrapPromise(data);
}

Ovenstående er blot en abstraktion for kosmiske hentefunktioner med Suspense og hente en gang.

Læs dataene i komponenten

Når alt er pakket ind på den hentende side af tingene, vil vi bruge det i vores komponent. Så hvad sker der, når vi kalder komponenten, den read() funktion vil begynde at kaste undtagelser, indtil den er fuldt løst, og når det sker, vil den fortsætte med resten af ​​koden, i vores tilfælde for at gengive den.


import React from 'react';
import { fetchDataByType } from '../../cosmic.js';
import styles from '../../styles/Collection.module.scss';

const resourseCategories = fetchDataByType();

const Category = () => {
  const categories = resourseCategories.read();

  const renderCategories = categories?.map((info) => (
    <div key={info?.id} className={styles.user}>
      <div className={styles.avatar}>
        <img
          className={styles.image}
          src={info?.metadata?.image?.imgix_url}
          alt="Avatar"
        />
      </div>
      <div className={styles.description}>
        <div className={styles.name}>{info?.metadata?.title}</div>
        <div
          className={styles.money}
          dangerouslySetInnerHTML={{ __html: info?.content }}
        />
      </div>
    </div>
  ));

  return <div className={styles.collections}>{renderCategories}</div>;
};

export default Category;

Den overordnede komponent

Suspense giver React adgang til ventende tilstande i vores applikationer, og det er derfor, React ved, at der sker et netværksopkald. Dette giver os mulighed for at gengive en fallback-komponent deklarativt, mens vi venter.


import React, { Suspense } from 'react';
import Cards from './components/Cards';
import Category from './components/Category';
import Main from './components/Main';
import styles from './styles/Collection.module.scss';

const App = () => {
  return (
    <div className={styles.wrapper}>
      <div className={cn('section-pb', styles.section)}>
        <div className={cn('container', styles.container)}>
          <div className={styles.row}>
            <Suspense fallback={<p>Loading.....</p>}>
              <Main />
              <Cards />
            </Suspense>
          </div>
          <div className={styles.sidebar}>
            <div className={styles.info}>
              Collections
              <span className={styles.smile} role="img" aria-label="fire">
                🔥
              </span>
            </div>
            <Suspense fallback={<p>Loading.....</p>}>
              <Category />
            </Suspense>
          </div>
        </div>
      </div>
    </div>
  );
};

export default App;

Konklusion

Nu med Suspense, kan du opdele din app i små, selvstændige enheder, der kan gengives på egen hånd uden resten af ​​appen, så indholdet bliver tilgængeligt for din bruger endnu meget hurtigere end før. Vi undersøgte de forskellige metoder til datahentning til sammenligning.

Prøv det i dit eget projekt og giv os din feedback. Du kan komme i gang med Cosmic for et hurtigt CMS at teste datahentning med Suspense til hjemmesider og apps.

Tidsstempel:

Mere fra Kodementor-reaktionsfakta