Project Rongtuli- A Social Media App
Auth Context and Private Route

এই প্রজেক্ট করার পর, আপনাদের Aprroch যেন এমন হয়ে যায়। যেন যেকোনো প্রজেক্ট করতে গেলে, ঠিক এই একই এপ্রোচে আগাতে পারি।

এখন আমাদের লগইন ইউজারের ইনফরমেশন স্টোর করতে হবে। এই প্রজেক্টে আমরা ইন মেমরি স্টোর করব। আগের ডকুমেন্টে ইন মেমরি কিভাবে ডাটা স্টোর করা যায়। বিস্তারিত বলেছি।

১। এখন Context API দিয়ে, আমরা AuthContext তৈরি করব।

২। এবং AuthProvider তৈরি করে, পুরো এপ্লিকেশনকে মুড়িয়ে দিবো।

৩। এবং useAuth নামে একটি কাস্টম হুক বানাবো, যার মাধ্যমে আমরা login user এর তথ্য নিয়ে সকল পেজে খেলতে পারবো। যাতে করে বার বার useContext এবং AuthContext সব পেজে import করা না লাগে।

যাতে accross the page অর্থাৎ ওয়েবসাইটের সব পেযে আমরা এই ডাটা শেয়ার করতে পারি।

context >> AuthContext.jsx

import { createContext } from "react";
const AuthContext = createContext();
 
export default AuthContext;

providers >> AuthProvider.jsx

import { useState } from "react";
import AuthContext from "../context/AuthContext";
 
export default function AuthProvider({ children }) {
  const [auth, setAuth] = useState("");
 
  return (
    <AuthContext.Provider value={{ auth, setAuth }}>
      {children}
    </AuthContext.Provider>
  );
}

hooks >> useAuth.js

import { useContext } from "react";
import AuthContext from "../context/AuthContext";
 
export default function useAuth() {
  return useContext(AuthContext);
}

এখন আমরা Private Route তৈরি করব। যার মাধ্যমে কিছু কিছু রাউট প্রাইভেট করব। যদি auth এর মধ্যে user থাকে, তাহলে প্রাইভেট রাউটে ঢুকতে পারবে। তা না হলে ধাক্কা মেরে লগইন পেজে নিয়ে যাবো।

routes >> PrivateRoutes.jsx

import { Navigate, Outlet } from "react-router-dom";
import Header from "../components/common/Header";
import useAuth from "../hooks/useAuth";
export default function PrivateRoutes() {
  const { auth } = useAuth();
  return (
    <>
      {auth.user ? (
        <>
          <Header />
          <main className="mx-auto max-w-[1020px] py-8">
            <div className="container">
              <Outlet />
            </div>
          </main>
        </>
      ) : (
        <Navigate to="/login" />
      )}
    </>
  );
}
  • auth.user: যদি ব্যবহারকারী লগইন করা থাকে, তাহলে চাইল্ড রাউটগুলো (যা Outlet এর মাধ্যমে রেন্ডার হয়) দেখাবে।
  • <Navigate to="/login" />: যদি ব্যবহারকারী লগইন না থাকে, তাহলে তাকে /login পেজে পাঠানো হবে।

Outlet এর কাজ কী?

<Outlet /> React Router-এ nested routes রেন্ডার করার জন্য ব্যবহৃত হয়। এটি মূলত চাইল্ড রাউটগুলোর জন্য একটি জায়গা তৈরি করে, যেখানে রাউট অনুযায়ী ডাইনামিক কন্টেন্ট দেখানো যায়।

উদাহরণ:

<Route path="/dashboard" element={<PrivateRoute />}>
  <Route path="profile" element={<ProfilePage />} />
  <Route path="settings" element={<SettingsPage />} />
</Route>
  • এখানে PrivateRoute এর মধ্যে <Outlet /> রেন্ডার হবে, এবং path অনুযায়ী কখনো <ProfilePage />, কখনো <SettingsPage /> দেখাবে।

<Outlet /> ট্যাগকে div এবং main দিয়ে মুড়িয়ে দিলাম কেন?

  1. স্টাইল এবং লেআউটের জন্য:

    • <main>: HTML এর একটি সেম্যান্টিক ট্যাগ। এটি মূল কনটেন্টের জন্য ব্যবহৃত হয়। সার্চ ইঞ্জিন এবং স্ক্রিন রিডার বুঝতে পারে এটি মূল কন্টেন্ট।
    • <div>: এটি নির্দিষ্ট সেকশনের স্টাইল এবং লেআউট ম্যানেজ করার জন্য।
  2. রেসপন্সিভ লেআউট:

    • className="mx-auto max-w-[1020px] py-8": এখানে রেসপন্সিভ লেআউট তৈরি করার জন্য main এবং div ব্যবহার করা হয়েছে। এটি কন্টেন্টকে কেন্দ্রস্থলে রাখে এবং একটি নির্দিষ্ট প্রস্থ দেয়।
  3. কোডের রিডেবিলিটি:

    • এটি কোডকে আরও গঠনমূলক ও রিডেবল করে। ভবিষ্যতে নতুন ক্লাস বা লেআউট অ্যাড করাও সহজ হয়।

সংক্ষেপে:

  • Outlet: চাইল্ড রাউট রেন্ডার করার জন্য।
  • divmain মুড়ানো হয়েছে: লেআউট ম্যানেজ ও রেসপন্সিভ ডিজাইনের জন্য।
  • কোডের কাজ: যদি ব্যবহারকারী লগইন থাকে, তাহলে চাইল্ড পেজ দেখাবে। না থাকলে লগইন পেজে পাঠাবে।

Protected Routes (Guard Routes) and Public Routes Structure

import { Route, BrowserRouter as Router, Routes } from "react-router-dom";
import HomePage from "./components/HomePage";
import LoginPage from "./components/LoginPage";
import AuthProvider from "./providers/AuthProvider";
import PrivateRoutes from "./routes/PrivateRoutes";
export default function App() {
  return (
    <AuthProvider>
      <Router>
        <Routes>
          {/* Private Routes */}
          <Route element={<PrivateRoutes />}>
            <Route path="/" element={<HomePage />} />
          </Route>
 
          {/* Public Routes */}
          <Route path="/login" element={<LoginPage />} />
        </Routes>
      </Router>
    </AuthProvider>
  );
}