KembaliBelajar Full-stack Dengan React Router v7
Pembahasan

Streaming

Ketika lo bikin halaman yang nge-load beberapa data sekaligus, lo bisa pake streaming supaya halaman tersebut bisa ditampilkan lebih cepat alias nggak nge-block proses rendering. Konsepnya sama kayak yang ada di Next.js, cuman beda caranya aja.

Anggap aja lo punya halaman detail produk yang nampilin inforasi produk dan review produk. Dari kedua data tersebut, yang paling penting adalah informasi produk, sedangkan review produk bisa ditampilin belakangan.

Contohnya kayak gini:

app/routes/product.tsx
import type { Route } from "./+types/product";
import { Await } from "react-router";
import { Suspense } from "react";

export async function loader({ params }: Route.LoaderArgs) {
  const product = await db.getProduct(params.pid);
  // yang ini nggak usah lo `await`, biar bisa di-stream
  const reviews = db.getProductReviews(params.pid);

  return { product, reviews };
}

export default function Product({ loaderData }: Route.ComponentProps) {
  return (
    <div>
      <h1>{loaderData.product.name}</h1>
      <p>{loaderData.product.description}</p>

      <Suspense fallback={<p>Loading reviews...</p>}>
        <Await resolve={loaderData.reviews}>
          {(reviews) => (
            <ul>
              {reviews.map((review) => (
                <li key={review.id}>{review.content}</li>
              ))}
            </ul>
          )}
        </Await>
      </Suspense>
    </div>
  );
}

Penjelasannya gini:

  • Di loader, kita ambil data produk dan review produk.
    • Data informasi produk ini penting, jadi kita await supaya bisa langsung ditampilin.
    • Sedangkan review produk kita nggak await, supaya bisa di-stream.
  • Di dalam component Product, kita pake <Await> dan <Suspense> buat nge-handle data review yang di-stream.
    • <Await> bakal nunggu data review resolve dan nge-render list review lewat pattern render props.
    • <Suspense> bakal nampilin fallback UI (dalam hal ini, "Loading reviews...") selama data review belum tersedia.

Basic-nya kayak gitu. Kalo seaindainya lo pake React 19, lo bisa pke React.use. Tapi, perlu diabstrak jadi dua komponen:

app/routes/product.tsx
import type { Route } from "./+types/product";
import { Suspense } from "react-router";
import { ProductReviews } from "~/components/ProductReviews";

// kode loader yang sama

export default function Product({ loaderData }: Route.ComponentProps) {
  return (
    <div>
      <h1>{loaderData.product.name}</h1>
      <p>{loaderData.product.description}</p>

      <Suspense fallback={<p>Loading reviews...</p>}>
        <ProductReviews reviews={loaderData.reviews} />
      </Suspense>
    </div>
  );
}

Sementara isi dari komponen ProductReviews adalah:

app/components/ProductReviews.tsx
import React from "react";
import { Review } from "~/libs/db/schema";

export function ProductReviews({ reviews }: { reviews: Promise<Review[]> }) {
  const reviews = React.use(reviews);

  return (
    <ul>
      {reviews.map((review) => (
        <li key={review.id}>{review.content}</li>
      ))}
    </ul>
  );
}

Bebas aja lo mau pake yang mana.

Progres kursus

Sudah paham pelajaran ini?

Tandai selesai untuk menyimpan progresmu di kursus ini.

Diskusi

0 komentar

Belum ada komentar.

Mulai diskusi