Eesti

Õppige, kuidas Reacti automaatne pakendamine optimeerib mitmeid olekumuudatusi, parandades rakenduse jõudlust ja vältides tarbetuid uuesti renderdusi. Avastage näiteid ja parimaid tavasid.

Reacti automaatne pakendamine: olekumuudatuste optimeerimine jõudluse parandamiseks

Reacti jõudlus on sujuvate ja tundlike kasutajaliideste loomisel ülioluline. Üks jõudluse parandamiseks kasutusele võetud põhiomadusi on automaatne pakendamine. See optimeerimistehnika rühmitab automaatselt mitu olekumuudatust üheks uuesti renderduseks, mis toob kaasa olulise jõudluse kasvu. See on eriti oluline keerukates rakendustes, kus olek muutub sageli.

Mis on Reacti automaatne pakendamine?

Pakendamine (batching) Reacti kontekstis on protsess, kus mitu olekumuudatust rühmitatakse üheks uuenduseks. Enne React 18-t rakendati pakendamist ainult uuendustele, mis toimusid Reacti sündmuste käsitlejate sees. Sündmuste käsitlejatest väljaspool toimunud uuendused, nagu need, mis olid sees setTimeout, lubadused või algsed sündmuste käsitlejad, ei olnud pakendatud. See võis põhjustada tarbetuid uuesti renderdusi ja jõudluse kitsaskohti.

React 18 tõi sisse automaatse pakendamise, mis laiendab seda optimeerimist kõikidele olekumuudatustele, olenemata nende asukohast. See tähendab, et olenemata sellest, kas teie olekumuudatused toimuvad Reacti sündmuse käsitleja sees, setTimeout tagasikutses või lubaduse lahendamisel, pakendab React need automaatselt üheks uuesti renderduseks.

Miks on automaatne pakendamine oluline?

Automaatne pakendamine pakub mitmeid olulisi eeliseid:

Kuidas automaatne pakendamine töötab

React saavutab automaatse pakendamise, lükates olekumuudatuste täitmise edasi praeguse täitmiskonteksti lõpuni. See võimaldab Reactil koguda kõik selle konteksti jooksul toimunud olekumuudatused ja pakendada need kokku üheks uuenduseks.

Vaatleme seda lihtsustatud näidet:

function ExampleComponent() {
  const [count1, setCount1] = useState(0);
  const [count2, setCount2] = useState(0);

  function handleClick() {
    setTimeout(() => {
      setCount1(count1 + 1);
      setCount2(count2 + 1);
    }, 0);
  }

  return (
    <div>
      <p>Loendur 1: {count1}</p>
      <p>Loendur 2: {count2}</p>
      <button onClick={handleClick}>Suurenda</button>
    </div>
  );
}

Enne React 18-t käivitaks nupule klõpsamine kaks uuesti renderdust: ühe setCount1 jaoks ja teise setCount2 jaoks. React 18 automaatse pakendamisega pakendatakse mõlemad olekumuudatused kokku, mille tulemuseks on ainult üks uuesti renderdus.

Näited automaatse pakendamise tööst

1. Asünkroonsed uuendused

Asünkroonsed toimingud, nagu andmete toomine API-st, hõlmavad sageli oleku värskendamist pärast toimingu lõppemist. Automaatne pakendamine tagab, et need olekumuudatused pakendatakse kokku, isegi kui need esinevad asünkroonse tagasikutse sees.

function DataFetchingComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch('https://api.example.com/data');
        const jsonData = await response.json();
        setData(jsonData);
        setLoading(false);
      } catch (error) {
        console.error('Andmete toomise viga:', error);
        setLoading(false);
      }
    }

    fetchData();
  }, []);

  if (loading) {
    return <p>Laadimine...</p>;
  }

  return <div>Andmed: {JSON.stringify(data)}</div>;
}

Selles näites kutsutakse nii setData kui ka setLoading asünkroonse fetchData funktsiooni sees. React pakendab need uuendused kokku, mille tulemuseks on üksik uuesti renderdamine, kui andmed on toodud ja laadimisolek on värskendatud.

2. Lubadused (Promises)

Sarnaselt asünkroonsetele uuendustele hõlmavad lubadused sageli oleku värskendamist, kui lubadus laheneb või lükatakse tagasi. Automaatne pakendamine tagab, et need olekumuudatused pakendatakse samuti kokku.

function PromiseComponent() {
  const [result, setResult] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    const myPromise = new Promise((resolve, reject) => {
      setTimeout(() => {
        const success = Math.random() > 0.5;
        if (success) {
          resolve('Lubadus täidetud!');
        } else {
          reject('Lubadus tagasi lükatud!');
        }
      }, 1000);
    });

    myPromise
      .then((value) => {
        setResult(value);
        setError(null);
      })
      .catch((err) => {
        setError(err);
        setResult(null);
      });
  }, []);

  if (error) {
    return <p>Viga: {error}</p>;
  }

  if (result) {
    return <p>Tulemus: {result}</p>;
  }

  return <p>Laadimine...</p>;
}

Sel juhul kutsutakse kas setResult ja setError(null) edu korral või setError ja setResult(null) ebaõnnestumise korral. Sõltumata sellest ühendab automaatne pakendamine need üheks uuesti renderduseks.

3. Algkeele sündmuste käsitlejad (Native Event Handlers)

Mõnikord võite vajada Reacti sünteetiliste sündmuste käsitlejate asemel algkeele sündmuste käsitlejate (nt addEventListener) kasutamist. Automaatne pakendamine töötab ka nendel juhtudel.

function NativeEventHandlerComponent() {
  const [scrollPosition, setScrollPosition] = useState(0);

  useEffect(() => {
    function handleScroll() {
      setScrollPosition(window.scrollY);
    }

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  return <p>Kerimise asukoht: {scrollPosition}</p>;
}

Isegi kui setScrollPosition kutsutakse algkeele sündmuse käsitleja sees, pakendab React uuendused ikkagi kokku, vältides liigseid uuesti renderdusi, kui kasutaja kerib.

Automaatsest pakendamisest loobumine

Harvadel juhtudel võite soovida automaatsest pakendamisest loobuda. Näiteks võite soovida sundida sünkroonset uuendust tagamaks, et kasutajaliides värskendatakse kohe. React pakub selleks flushSync API-t.

Märkus: flushSync-i tuleks kasutada säästlikult, kuna see võib jõudlust negatiivselt mõjutada. Üldiselt on parem tugineda automaatsele pakendamisele alati, kui see on võimalik.

import { flushSync } from 'react-dom';

function ExampleComponent() {
  const [count, setCount] = useState(0);

  function handleClick() {
    flushSync(() => {
      setCount(count + 1);
    });
  }

  return (<button onClick={handleClick}>Suurenda</button>);
}

Selles näites sunnib flushSync Reacti olekut koheselt värskendama ja komponenti uuesti renderdama, möödudes automaatsest pakendamisest.

Parimad tavad olekumuudatuste optimeerimiseks

Kuigi automaatne pakendamine pakub märkimisväärset jõudluse paranemist, on siiski oluline järgida parimaid tavasid olekumuudatuste optimeerimisel:

Automaatne pakendamine ja globaalsed kaalutlused

Automaatne pakendamine, olles Reacti põhjõudluse optimeerimine, toob kasu rakendustele globaalselt, olenemata kasutaja asukohast, võrgu kiirusest või seadmest. Kuid selle mõju võib olla märgatavam stsenaariumides, kus on aeglasemad internetiühendused või vähem võimsad seadmed. Rahvusvahelistele publikutele kaaluge järgmisi punkte:

Kokkuvõte

Reacti automaatne pakendamine on võimas optimeerimistehnika, mis võib märkimisväärselt parandada teie Reacti rakenduste jõudlust. Rühmitades automaatselt mitu olekumuudatust üheks uuesti renderduseks, vähendab see renderduskulu, väldib ebajärjekindlaid olekuid ning viib sujuvama ja tundlikuma kasutuskogemuseni. Mõistes, kuidas automaatne pakendamine töötab ja järgides parimaid tavasid olekumuudatuste optimeerimiseks, saate luua suure jõudlusega Reacti rakendusi, mis pakuvad suurepärast kasutuskogemust kasutajatele üle kogu maailma. Tööriistade nagu React DevTools kasutamine aitab teie rakenduse jõudlusprofiile erinevates globaalsetes seadetes veelgi täiustada ja optimeerida.