Next.js এর হাতেখড়ি (পর্ব ৬) – Loading ও Error States: loading.js, error.js, Suspense

Next.js Loading ও Error States loading.js error.js Suspense

পর্ব ৪-এ বলেছিলাম, Server Component-এ isLoading state ম্যানুয়ালি লেখার দরকার নেই। এই পর্বে দেখব কীভাবে — Next.js-এর দুটো বিশেষ ফাইল, loading.js আর error.js, আর React-এর Suspense দিয়ে।

loading.js — স্বয়ংক্রিয় লোডিং UI

একটা রুট ফোল্ডারে page.js-এর পাশে loading.js রাখলেই, সেই পেজের fetch শেষ না হওয়া পর্যন্ত Next.js স্বয়ংক্রিয়ভাবে এই ফাইলের কনটেন্ট দেখায়।

app/
└── books/
    ├── loading.js   # /books লোড হওয়ার সময় দেখানো হবে
    └── page.js      # আসল পেজ, fetch করছে
// app/books/loading.js
export default function Loading() {
  return <p>বই লোড হচ্ছে...</p>;
}
// app/books/page.js
async function getBooks() {
  const res = await fetch("https://.../books.json");
  return res.json();
}

export default async function BooksPage() {
  const books = await getBooks(); // এই সময়টুকু loading.js দেখানো হবে
  return <div>{/* ... */}</div>;
}

কোনো isLoading state, কোনো conditional rendering — Next.js নিজে থেকেই বুঝে নেয় কখন page.js এখনো ডেটার জন্য অপেক্ষা করছে, আর তখন loading.js দেখায়।

error.js — স্বয়ংক্রিয় এরর UI

একইভাবে, error.js রাখলে সেই রুটে কোনো এরর হলে (fetch ব্যর্থ হলে, কোনো এক্সেপশন থ্রো হলে) Next.js স্বয়ংক্রিয়ভাবে এই ফাইলের কনটেন্ট দেখায়, পুরো সাইট ক্র্যাশ না করিয়ে।

// app/books/error.js
"use client"; // error.js সবসময় Client Component হতে হয়

export default function Error({ error, reset }) {
  return (
    <div>
      <p>কিছু একটা সমস্যা হয়েছে: {error.message}</p>
      <button onClick={() => reset()}>আবার চেষ্টা করো</button>
    </div>
  );
}

গুরুত্বপূর্ণ: error.js-এ অবশ্যই "use client" লাগবে (পর্ব ৩-এর নিয়ম), কারণ এতে reset ফাংশনের মতো একটা ইন্টারঅ্যাক্টিভ বাটন থাকে, যা ক্লিক করলে সেই অংশটা আবার রেন্ডার করার চেষ্টা করে।

// app/books/page.js — এরর হলে error.js দেখাবে
async function getBooks() {
  const res = await fetch("https://.../books.json");
  if (!res.ok) {
    throw new Error("বই লোড করা যায়নি"); // এটাই error.js-এ ধরা পড়বে
  }
  return res.json();
}

Nested Loading/Error — ফোল্ডার অনুযায়ী প্রযোজ্য

পর্ব ২-এর নেস্টেড লেআউটের মতোই, loading.js/error.js-ও নির্দিষ্ট ফোল্ডারে রাখলে শুধু সেই সেকশনেই প্রযোজ্য হয়।

app/
├── loading.js          # পুরো সাইটের ডিফল্ট লোডিং
├── books/
│   ├── loading.js      # শুধু /books-এর জন্য আলাদা লোডিং UI
│   └── page.js
└── dashboard/
    ├── error.js        # শুধু /dashboard-এর জন্য আলাদা এরর UI
    └── page.js

Suspense — পেজের একটা অংশের জন্য লোডিং

loading.js পুরো পেজের জন্য কাজ করে। কিন্তু একটা পেজে যদি কিছু কনটেন্ট দ্রুত রেডি হয় আর কিছু ধীরে, পুরো পেজ অপেক্ষা করানোর বদলে React-এর Suspense দিয়ে নির্দিষ্ট অংশ আলাদাভাবে লোড দেখানো যায়।

import { Suspense } from "react";

async function BookList() {
  const res = await fetch("https://.../books.json", { cache: "no-store" });
  const books = await res.json();
  return (
    <ul>
      {Object.values(books || {}).map((b, i) => <li key={i}>{b.title}</li>)}
    </ul>
  );
}

export default function BooksPage() {
  return (
    <div>
      <h1>বইয়ের তালিকা</h1> {/* সাথে সাথেই দেখা যাবে */}

      <Suspense fallback={<p>বই লোড হচ্ছে...</p>}>
        <BookList /> {/* এইটুকু আলাদাভাবে লোড হবে */}
      </Suspense>
    </div>
  );
}

এখানে <h1> সাথে সাথে দেখা যায়, শুধু BookList-এর ডেটা রেডি না হওয়া পর্যন্ত সেই অংশে fallback দেখানো হয় — এটা পুরো পেজ ব্লক করার চেয়ে অনেক ভালো ইউজার এক্সপিরিয়েন্স দেয়।

loading.js vs Suspense — কখন কোনটা

পরিস্থিতি ব্যবহার করুন
পুরো পেজই একটা fetch-এর ওপর নির্ভরশীল loading.js
পেজের কিছু অংশ দ্রুত, কিছু ধীর Suspense নির্দিষ্ট অংশে
একই পেজে একাধিক স্বাধীন ডেটা সোর্স একাধিক Suspense, প্রতিটা আলাদা

ইন্টারেক্টিভ — Suspense কীভাবে কাজ করে

নিচে দেখো একটা পেজে দ্রুত আর ধীর দুটো কনটেন্ট থাকলে Suspense কীভাবে সেগুলো আলাদাভাবে দেখায়।

ভালো অভ্যাস

  • প্রতিটা মূল রুটে একটা loading.js রাখুন — না থাকলে ইউজার সাদা স্ক্রিন দেখবে, খারাপ অভিজ্ঞতা
  • error.js-এ সবসময় reset বাটন দিন — ইউজারকে পুরো পেজ রিফ্রেশ না করেই আবার চেষ্টা করার সুযোগ দিন
  • ধীর আর দ্রুত ডেটা একসাথে থাকলে Suspense দিয়ে আলাদা করুন — একটা ধীর fetch-এর জন্য পুরো পেজ আটকে রাখাটা এড়ানো যায়

নিজে চেষ্টা করো

Exercise:

  1. নিজের একটা পেজে loading.js যোগ করো, একটা ধীর API (বা setTimeout-স্টাইল দেরি) দিয়ে টেস্ট করো।
  2. একটা error.js বানাও, ইচ্ছাকৃতভাবে একটা এরর থ্রো করে টেস্ট করো, reset বাটন কাজ করছে কিনা যাচাই করো।
  3. একটা পেজে দুটো আলাদা কম্পোনেন্ট রাখো — একটা দ্রুত, একটা ধীর ডেটা আনে — Suspense দিয়ে আলাদাভাবে র‍্যাপ করো।

পরের পর্বে যা থাকছে

পরের পর্বে আমরা শিখব API Routes — Next.js প্রজেক্টের ভেতরেই নিজের ব্যাকএন্ড এন্ডপয়েন্ট কীভাবে বানাতে হয়, ঠিক Cloudflare এর হাতেখড়ি পর্ব ৪-৫-এর Workers-এর মতোই, কিন্তু একই প্রজেক্টে।

একটি মন্তব্য পোস্ট করুন

নবীনতর পূর্বতন

যোগাযোগ ফর্ম