<KodLexikon/>
Illustration för javascript-programmering
← Alla artiklar
javascript12 min läsning2026-03-14

React Server Components: En praktisk guide

Server Components förändrar hur vi bygger React-appar. Så fungerar de, när du ska använda dem, och hur du undviker de vanligaste fallgroparna.

React Server Components (RSC) förändrar fundamentalt hur vi tänker kring React-applikationer. Istället för att skicka JavaScript till webbläsaren för varje komponent, renderas Server Components på servern och skickar färdig HTML. Resultatet: mindre JavaScript, snabbare sidladdning och direkt åtkomst till serverns resurser.

Men övergången från "allt renderas i webbläsaren" till "vissa saker renderas på servern" kräver ett nytt mentalt ramverk. Den här guiden ger dig det.

Server Components vs Client Components

I Next.js App Router är alla komponenter Server Components som standard. Du behöver bara markera de komponenter som behöver interaktivitet, state eller browser-API:er med "use client".

// Server Component (standard i App Router)
// Kan: hämta data direkt, läsa filer, använda databas
// Kan inte: useState, useEffect, onClick, browser-API:er

// app/products/page.tsx — Server Component
import { db } from "@/lib/database";

export default async function ProductsPage() {
  // Direkt databasåtkomst — ingen API-route behövs
  const products = await db.products.findMany({
    orderBy: { createdAt: "desc" },
    take: 20,
  });

  return (
    <div>
      <h1>Produkter</h1>
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
      {/* Interaktiv komponent */}
      <AddToCartButton />
    </div>
  );
}

// ProductCard är också en Server Component
function ProductCard({ product }) {
  return (
    <div>
      <h2>{product.name}</h2>
      <p>{product.price} kr</p>
    </div>
  );
}
// Client Component — markeras explicit
"use client";

import { useState } from "react";

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

  return (
    <button onClick={() => setCount(c => c + 1)}>
      Lägg i varukorg ({count})
    </button>
  );
}

// Tumregel: "use client" ska vara så långt ner
// i komponentträdet som möjligt.
// Bara den knapp som behöver state ska vara client.

Data-hämtning utan useEffect

En av de största fördelarna med Server Components är att data-hämtning sker med vanliga async/await — direkt i komponenten. Inga useEffect-loopar, inga loading states att hantera manuellt, inga race conditions.

// Traditionellt (Client Component)
"use client";
import { useState, useEffect } from "react";

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch("/api/users/" + userId)
      .then(res => res.json())
      .then(data => setUser(data))
      .catch(err => setError(err))
      .finally(() => setLoading(false));
  }, [userId]);

  if (loading) return <p>Laddar...</p>;
  if (error) return <p>Fel: {error.message}</p>;
  return <h1>{user.name}</h1>;
}

// Med Server Components — mycket enklare
import { db } from "@/lib/database";

async function UserProfile({ userId }: { userId: string }) {
  const user = await db.users.findUnique({
    where: { id: userId },
  });

  if (!user) return <p>Användaren hittades inte</p>;
  return <h1>{user.name}</h1>;
}

// Loading-state? Använd loading.tsx:
// app/users/[id]/loading.tsx
export default function Loading() {
  return <p>Laddar profil...</p>;
}

Streaming med Suspense

Server Components stödjer streaming — du behöver inte vänta på att all data ska vara klar innan sidan börjar visas. Wrap långsamma delar i Suspenseså streamar React in dem när de är redo.

// Sidan renderas direkt med fallback
// för den långsamma delen
import { Suspense } from "react";

export default function DashboardPage() {
  return (
    <div>
      <h1>Dashboard</h1>

      {/* Renderas direkt */}
      <QuickStats />

      {/* Streamar in när datan är klar */}
      <Suspense fallback={<p>Laddar diagram...</p>}>
        <RevenueChart />
      </Suspense>

      <Suspense fallback={<p>Laddar aktivitet...</p>}>
        <RecentActivity />
      </Suspense>
    </div>
  );
}

// Denna komponent tar 3 sekunder att hämta data
// men blockerar inte resten av sidan
async function RevenueChart() {
  const data = await fetchRevenueData(); // 3s
  return <Chart data={data} />;
}

async function RecentActivity() {
  const events = await fetchActivityLog(); // 1s
  return (
    <ul>
      {events.map(e => <li key={e.id}>{e.title}</li>)}
    </ul>
  );
}

Server Actions — formulär utan API-routes

Server Actions ersätter behovet av API-routes för formulärhantering. Definiera en funktion med "use server" och använd den direkt i ett formulärsaction-attribut. Data skickas automatiskt till servern.

// Server Action — direkt i filen
async function createProduct(formData: FormData) {
  "use server";

  const name = formData.get("name") as string;
  const price = Number(formData.get("price"));

  // Validering
  if (!name || price <= 0) {
    throw new Error("Ogiltig data");
  }

  // Direkt databasåtkomst
  await db.products.create({
    data: { name, price },
  });

  // Uppdatera sidan
  revalidatePath("/products");
  redirect("/products");
}

export default function NewProductPage() {
  return (
    <form action={createProduct}>
      <input name="name" placeholder="Produktnamn" required />
      <input name="price" type="number" step="0.01" required />
      <button type="submit">Skapa produkt</button>
    </form>
  );
}

Vanliga fallgropar

Felet: Lägga "use client" på toppnivån i ett layout. Det tvingar alla barnkomponenter att bli Client Components — och du förlorar fördelarna med Server Components helt.

Felet: Försöka använda React-context i Server Components. Context är en Client Component-feature. Lösning: skicka data som props eller använd server-side patterns som cookies och headers.

Felet: Importera stora bibliotek i Server Components som sedan inte tree-shakas korrekt. Kontrollera din bundle-storlek regelbundet.

Läs mer om modern JavaScript i vår JavaScript-guide och webbutveckling 2026.