React Native Academy · Lektion

Undvika prestandaproblem med kontext

Identifiera onödiga omrenderingar som orsakas av ändringar i kontextvärden, dela upp kontexten i flera providers och memoisera kontextvärden för bättre prestanda.

Lektion 4 av 413 steg

Undvika prestandaproblem med kontext är en gratis lektion i React Native Academy på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för React Native Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i React Native Academy innehåller totalt 4 lektioner.

Problemet med omrendering i kontext

När en Context Provider omrenderas med ett nytt value omrenderas alla komponenter som anropar useContext för den kontexten, oavsett om den specifika del av värdet som de använder har ändrats. I stora appar med många konsumenter kan detta leda till betydande prestandaproblem.

Identifiera onödiga omrenderingar i kontext

Använd React DevTools Profiler för att identifiera komponenter som omrenderas för ofta. Spela in en interaktion som bara borde påverka en del av gränssnittet och undersök sedan vilka komponenter som markeras i flödesschemat. Om komponenter som bara läser en del av kontexten omrenderas när en orelaterad del ändras har du ett prestandaproblem.

Antimönstret med inline-objekt

Den vanligaste orsaken till onödiga omrenderingar i kontext är att värdeobjektet skapas inline i JSX. Då skapas en ny objektreferens vid varje omrendering av Providern, vilket React behandlar som ett ändrat värde – även när innehållet är identiskt – och det utlöser en kedja av omrenderingar hos alla konsumenter.

// 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}>

Memorera kontextvärden med useMemo

Omslut kontextens värdeobjekt med useMemo inuti Providern. React skapar då bara ett nytt objekt och meddelar konsumenterna när ett av de angivna beroendena ändras. Detta är den enklaste och mest effektiva åtgärden mot prestandaproblem i kontext.

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>;
}

Dela upp kontexter för oberoende ansvarsområden

Om kontexten innehåller både värden som ändras ofta, till exempel antal varor i kundvagnen, och värden som ändras sällan, till exempel användarprofilen, tvingas konsumenter som bara behöver stabila data att omrenderas när de föränderliga värdena ändras. Lösningen är att dela upp kontexten i två separata providers – en för varje ansvarsområde.

// 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

Separera tillstånd från dispatch

Ett beprövat mönster är att dela upp kontexten i en tillståndskontext och en dispatch-kontext. Dispatch-funktioner ändras aldrig (useCallback eller dispatch från useReducer är stabila), så komponenter som bara skickar åtgärder omrenderas aldrig av tillståndsändringar. Endast komponenter som läser tillståndet omrenderas när tillståndet ändras.

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 hjälper INTE kontextkonsumenter

Ett vanligt misstag är att omsluta kontextkonsumenter med React.memo i tron att det förhindrar omrenderingar som orsakas av kontextändringar. Det gör det inte – React.memo jämför bara props, inte kontextprenumerationer. En komponent som använder kontext omrenderas alltid när kontextvärdet ändras, oavsett React.memo.

// 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

Selektormönstret för kontext

Om du behöver detaljerade prenumerationer som liknar useSelector i Redux kan du implementera ett enkelt selektormönster. En anpassad hook tar emot en selektorfunktion och memorerar det valda värdet med useMemo. Omrenderingar sker bara när det valda värdet ändras, inte när hela kontexten ändras.

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>;
}

Håll providers enkla

Provider-komponenten bör vara så enkel som möjligt. Flytta kostsamma beräkningar från Providerns renderingslogik till useMemo eller till reducern. Undvik att hämta data, köra omfattande transformeringar eller skapa stora objekt inline i Providerns JSX vid varje omrendering.

Komposition framför en enda jättestor kontext

Undvik frestelsen att lägga hela appens globala tillstånd i en enda kontext. En bättre arkitektur använder många små, fokuserade kontexter: AuthContext för autentisering, ThemeContext för färger, CartContext för kundvagnen och NotificationContext för aviseringar. Varje kontext omrenderar bara sina egna konsumenter, vilket håller omfattningen av varje omrendering liten och förutsägbar.

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

När du bör överväga Zustand eller Redux

Om optimeringar av kontextens prestanda blir för komplexa – eller om du märker att du bygger ett avancerat selectorsysten – kan du överväga att byta till Zustand eller Redux Toolkit. Dessa bibliotek erbjuder detaljerade prenumerationer direkt och är utformade för storskalig tillståndshantering. Kontext är fortfarande idealiskt för enkla globala värden som tema, autentisering och inställningar.

Snabb kontroll

Testa dina kunskaper om hur du undviker prestandaproblem med kontext från den här lektionen.

Sammanfattning av lektionen

I den här lektionen lärde du dig att inline-värdeobjekt i Providerns JSX orsakar onödiga omrenderingar – använd useMemo för att stabilisera dem, dela upp stora kontexter i mindre, fokuserade kontexter för att begränsa omrenderingarnas omfattning samt separera tillstånd och dispatch i två kontexter så att komponenter som bara skickar åtgärder aldrig omrenderas vid tillståndsändringar. Härnäst utforskar vi useEffect-hooken och beroendearrayen för datahämtning.

Gratis att börja

Lär dig JavaScript med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Undvika prestandaproblem med kontext” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen React Native Academy, inklusive ”Undvika prestandaproblem med kontext”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i React Native Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Undvika prestandaproblem med kontext”?

Identifiera onödiga omrenderingar som orsakas av ändringar i kontextvärden, dela upp kontexten i flera providers och memoisera kontextvärden för bättre prestanda. Ni övar på React Native Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig React Native Academy?

Du behöver inga förkunskaper. Utbildningen i React Native Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Undvika prestandaproblem med kontext”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här React Native Academy-lektionen?

Ja. Varje React Native Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Skapa och tillhandahålla en kontext
  2. Använda kontext med useContext
  3. En temakontext med växlare för mörkt läge
  4. Undvika prestandaproblem med kontext
← Tillbaka till React Native Academy