React Native Academy · Oppitunti

Kontekstin suorituskykyongelmien välttäminen

Tunnistakaa kontekstin arvon muutosten aiheuttamat tarpeettomat uudelleenrenderöinnit, jakakaa konteksti useiksi providereiksi ja optimoikaa suorituskyky välimuistittamalla kontekstin arvot.

Oppitunti 4/413 vaihetta

Kontekstin suorituskykyongelmien välttäminen on ilmainen React Native Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu React Native Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. React Native Academy-kurssilla on yhteensä 4 oppituntia.

Kontekstin uudelleenrenderöintiongelma

Kun Context Provider renderöidään uudelleen uuden value-arvon kanssa, jokainen kyseisen kontekstin useContext-hookia kutsuva komponentti renderöidään uudelleen, riippumatta siitä, onko sen käyttämä arvon osa muuttunut. Suurissa sovelluksissa, joissa on paljon kuluttajia, tästä voi seurata merkittäviä suorituskykyongelmia.

Tarpeettomien kontekstin uudelleenrenderöintien tunnistaminen

Tunnistakaa liian usein uudelleenrenderöityvät komponentit React DevTools Profilerilla. Tallentakaa vuorovaikutus, jonka pitäisi vaikuttaa vain yhteen käyttöliittymän osaan, ja tarkastelkaa sitten liekkikaaviosta, mitkä komponentit on korostettu. Jos vain yhtä kontekstin osaa lukevat komponentit renderöidään uudelleen, kun toiseen, niihin liittymättömään osaan tehdään muutos, kyseessä on suorituskykyongelma.

Inline-objektin haitallinen käyttötapa

Yleisin tarpeettomien kontekstin uudelleenrenderöintien lähde on arvo-objektin luominen suoraan JSX:ssä. Tämä luo uuden objektiviitteen jokaisella Providerin renderöintikerralla. React tulkitsee sen muuttuneeksi arvoksi – vaikka sisältö olisi sama – ja käynnistää kaikkien kuluttajien uudelleenrenderöintiketjun.

// Bad: new object on every render
<MyContext.Provider value={{ user, logout }}>

// Good: stable reference with useMemo
const value = useMemo(() => ({ user, logout }), [user, logout]);
<MyContext.Provider value={value}>

Kontekstiarvojen memoisoiminen useMemo-hookilla

Käärikää kontekstin arvo-objekti useMemo-hookiin Providerin sisällä. React luo uuden objektin ja ilmoittaa siitä kuluttajille vain, kun jokin luetelluista riippuvuuksista muuttuu. Tämä on yksinkertaisin ja vaikuttavin korjaus kontekstin suorituskykyongelmiin.

function CartProvider({ children }) {
  const [items, setItems] = useState([]);

  const addItem = useCallback((item) => {
    setItems((prev) => [...prev, item]);
  }, []);

  const value = useMemo(() => ({
    items,
    addItem,
    total: items.reduce((sum, i) => sum + i.price, 0),
  }), [items, addItem]);

  return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}

Kontekstien jakaminen toisistaan riippumattomien vastuualueiden mukaan

Jos kontekstinne sisältää sekä usein muuttuvia arvoja (kuten ostoskorin nimikemäärän) että harvoin muuttuvia arvoja (kuten käyttäjäprofiilin), vain vakaata tietoa tarvitsevat kuluttajat pakotetaan renderöitymään uudelleen aina, kun muuttuva tieto muuttuu. Ratkaisu on jakaa konteksti kahdeksi erilliseksi provideriksi, yksi kutakin vastuualuetta varten.

// Instead of one big UserContext:
export const UserDataContext = createContext(null);    // changes rarely
export const UserActionsContext = createContext(null); // changes rarely
export const CartItemsContext = createContext([]);     // changes often

// Consumers only subscribe to what they use

Tilan ja dispatchin erottaminen

Hyväksi todettu käytäntö on jakaa konteksti tilakontekstiin ja dispatch-kontekstiin. Dispatch-funktiot eivät koskaan muutu (useCallback tai useReducer-dispatch ovat vakaita), joten vain toimintoja lähettäviä komponentteja ei renderöidä uudelleen tilan muutosten vuoksi. Vain tilaa lukevat komponentit renderöidään uudelleen tilan muuttuessa.

export const AppStateContext = createContext(null);
export const AppDispatchContext = createContext(null);

function AppProvider({ children }) {
  const [state, dispatch] = useReducer(appReducer, initialState);

  return (
    <AppStateContext.Provider value={state}>
      <AppDispatchContext.Provider value={dispatch}>
        {children}
      </AppDispatchContext.Provider>
    </AppStateContext.Provider>
  );
}

React.memo EI auta kontekstin kuluttajia

Yleinen virhe on kääriä kontekstin kuluttajat React.memo-kutsuun siinä uskossa, että se estää kontekstin muutosten aiheuttamat uudelleenrenderöinnit. Näin ei käy – React.memo vertailee vain propseja, ei kontekstitilauksia. Kontekstia käyttävä komponentti renderöidään aina uudelleen kontekstiarvon muuttuessa React.memosta riippumatta.

// React.memo does NOT prevent context-driven re-renders
const MyComponent = React.memo(() => {
  const { value } = useContext(MyContext);
  // Still re-renders every time MyContext changes
  return <Text>{value}</Text>;
});

// Solution: Split context or memoize the value in the Provider

Kontekstin selektorimalli

Jos tarvitsette Reduxin useSelector-hookin kaltaisia tarkkarajaisia tilauksia, voitte toteuttaa yksinkertaisen selektorimallin. Mukautettu hook vastaanottaa selektorifunktion ja memoisi valitun arvon useMemo-hookilla. Uudelleenrenderöintejä tapahtuu vain, kun valittu arvo muuttuu, ei koko kontekstin muuttuessa.

function useCartTotal() {
  const { items } = useContext(CartContext);
  // Only recomputes when items changes
  return useMemo(
    () => items.reduce((sum, item) => sum + item.price, 0),
    [items]
  );
}

// Component only re-renders when the total number changes
function CartBadge() {
  const total = useCartTotal();
  return <Text>${total.toFixed(2)}</Text>;
}

Providerien pitäminen kevyinä

Provider-komponentin tulisi itsessään olla mahdollisimman yksinkertainen. Siirtäkää raskaat laskutoimitukset Providerin renderöinnistä useMemo-hookiin tai reducereihin. Välttäkää tietojen hakemista, raskaita muunnoksia tai suurten objektien luomista suoraan Providerin JSX:ssä jokaisella renderöintikerralla.

Koostaminen yhden suuren kontekstin sijaan

Välttäkää kiusausta sijoittaa kaikki sovelluksen globaali tila yhteen kontekstiin. Parempi arkkitehtuuri käyttää monia pieniä ja tarkasti kohdennettuja konteksteja: AuthContext todennusta varten, ThemeContext värejä varten, CartContext ostoskoria varten ja NotificationContext ilmoituksia varten. Kukin konteksti renderöi uudelleen vain omat kuluttajansa, jolloin jokaisen uudelleenrenderöinnin vaikutusalue pysyy pienenä ja ennakoitavana.

// Architecture with focused contexts
export default function App() {
  return (
    <AuthProvider>
      <ThemeProvider>
        <CartProvider>
          <NotificationProvider>
            <AppContent />
          </NotificationProvider>
        </CartProvider>
      </ThemeProvider>
    </AuthProvider>
  );
}

Milloin Zustandia tai Redoxia kannattaa harkita

Jos kontekstin suorituskyvyn optimoinnit muuttuvat liian monimutkaisiksi tai huomaatte rakentavanne monimutkaista selektorijärjestelmää, harkitkaa siirtymistä Zustainiin tai Redux Toolkitiin. Nämä kirjastot tarjoavat tarkkarajaiset tilaukset valmiina ja on suunniteltu laajamittaiseen tilanhallintaan. Konteksti sopii edelleen erinomaisesti yksinkertaisille globaaleille arvoille, kuten teemalle, todennukselle ja asetuksille.

Pikatesti

Testatkaa tämän oppitunnin ymmärrystänne kontekstin suorituskykyongelmien välttämisestä.

Oppitunnin yhteenveto

Tässä oppitunnissa opitte: Providerin JSX:ään suoraan kirjoitetut arvo-objektit aiheuttavat tarpeettomia uudelleenrenderöintejä – vakauttakaa ne useMemo-hookilla, jakamaan suuret kontekstit pienempiin, tarkasti kohdennettuihin konteksteihin uudelleenrenderöinnin vaikutusalueen rajoittamiseksi sekä erottamaan tilan ja dispatchin kahdeksi kontekstiksi, jotta vain toimintoja lähettäviä komponentteja ei renderöidä uudelleen tilan muuttuessa. Seuraavaksi tutustumme useEffect-hookiin ja tietojen hakemisen riippuvuustaulukoihin.

Aloita maksutta

Opi JavaScript tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”Kontekstin suorituskykyongelmien välttäminen” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa React Native Academy-oppimispolun 3 oppituntia, myös oppitunnin “Kontekstin suorituskykyongelmien välttäminen”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. React Native Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Kontekstin suorituskykyongelmien välttäminen”?

Tunnistakaa kontekstin arvon muutosten aiheuttamat tarpeettomat uudelleenrenderöinnit, jakakaa konteksti useiksi providereiksi ja optimoikaa suorituskyky välimuistittamalla kontekstin arvot. Harjoittelet React Native Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni React Native Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin React Native Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Kontekstin suorituskykyongelmien välttäminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä React Native Academy-oppitunnilla?

Kyllä. Jokainen React Native Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Kontekstin luominen ja tarjoaminen
  2. Kontekstin käyttäminen useContextilla
  3. Teemakonteksti ja tumman tilan vaihtokytkin
  4. Kontekstin suorituskykyongelmien välttäminen
← Takaisin: React Native Academy