হাই 👋🏻,
এই নিবন্ধটি বিশেষভাবে নতুনদের জন্য তৈরি করা হয়েছে যারা একাধিক উপাদানের মধ্যে অবস্থা পরিচালনার জন্য আরও কার্যকর পদ্ধতি শিখতে আগ্রহী। এটি প্রপ ড্রিলিংয়ের সাধারণ সমস্যাকেও সমাধান করার লক্ষ্য রাখে যা আপনার কোড বজায় রাখা এবং বোঝা কঠিন করে তুলতে পারে। চলুন শুরু করা যাক কি ধরনের সমস্যা প্রসঙ্গ API সমাধান করে।
আপনি যদি ভিডিও ফরম্যাট পছন্দ করেন, তাহলে এখানে টিউটোরিয়াল রয়েছে যা আপনি আমার YouTube চ্যানেলে দেখতে পারেন।👇🏻
আপনি জানেন কিভাবে কখনও কখনও আপনাকে একটি প্যারেন্ট কম্পোনেন্ট থেকে একটি শিশু উপাদানে ডেটা পাস করতে হয় এবং আপনি এর মধ্যে একগুচ্ছ উপাদানের মধ্য দিয়ে প্রপস পাস করেন? এটিকে প্রপ ড্রিলিং বলা হয় এবং এটি দ্রুত অগোছালো হতে পারে। আসুন এটি স্পষ্ট করার জন্য একটি উদাহরণ দিয়ে হাঁটা যাক।
ডায়াগ্রামে দেখানো হিসাবে, কল্পনা করুন যে আপনি App
উপাদানে কিছু ডেটা এনেছেন, যা আপনার অ্যাপ্লিকেশনের মূলে বসে। এখন, যদি একটি গভীরভাবে নেস্টেড কম্পোনেন্ট, Grandchild
কম্পোনেন্টকে এই ডেটা অ্যাক্সেস করতে হয়, তাহলে Grandchild
কাছে পৌঁছানোর আগে আপনি সাধারণত এটিকে Parent
এবং Child
কম্পোনেন্টের মাধ্যমে প্রপস হিসেবে পাঠাবেন। আপনার অ্যাপ বাড়ার সাথে সাথে এটি কুৎসিত হতে পারে।
এখানে আরেকটি চাক্ষুষ উপস্থাপনা আছে:
উপরের উদাহরণে, Profile
উপাদানটির ব্যবহারকারীর ডেটা প্রয়োজন, কিন্তু এই ডেটাটিকে প্রথমে App
এবং Navigation
উপাদানগুলির মাধ্যমে ভ্রমণ করতে হবে, যদিও এই মধ্যবর্তী উপাদানগুলি নিজেরাই ডেটা ব্যবহার করে না। সুতরাং, আমরা কিভাবে এটি পরিষ্কার করব? সেখানেই কনটেক্সট এপিআই কাজে আসে।
প্রপস ড্রিলিং:
React.js-এ কনটেক্সট এপিআই আপনাকে কম্পোনেন্ট ট্রির প্রতিটি স্তরের মধ্য দিয়ে প্রপস হিসাবে পাস করার প্রয়োজন ছাড়াই উপাদানগুলির মধ্যে ডেটা পাস করতে দেয়। এটি একটি গ্লোবাল স্টেট ম্যানেজমেন্ট সিস্টেমের মতো কাজ করে যেখানে আপনি একটি প্রসঙ্গ অবজেক্টে আপনার রাজ্যকে সংজ্ঞায়িত করেন এবং তারপরে আপনি উপাদান ট্রির যেকোনো জায়গায় সহজেই এটি অ্যাক্সেস করতে পারেন। একটি উদাহরণ দিয়ে বিষয়টি বোঝা যাক।
আপনি ডায়াগ্রামে দেখতে পাচ্ছেন, আমাদের কাছে একটি প্রসঙ্গ বস্তু রয়েছে যা একাধিক উপাদান দ্বারা অ্যাক্সেস করার জন্য ডেটা সংরক্ষণ করে। এই ডেটা APIs বা তৃতীয় পক্ষের পরিষেবাগুলি থেকে আনা হয়৷ যেকোনো উপাদানে এই প্রসঙ্গ ডেটা অ্যাক্সেস করার আগে, আমাদের একটি প্রসঙ্গ সরবরাহকারী উপাদানে এই ডেটার প্রয়োজন এমন সমস্ত উপাদানগুলিকে মোড়ানো দরকার।
যদি আমাদের শুধুমাত্র নেভিগেশন এবং প্রোফাইল উপাদানগুলিতে ডেটা অ্যাক্সেস করতে হয়, তাহলে আমাদের অ্যাপের উপাদানটি গুটিয়ে নেওয়ার দরকার নেই। একবার আপনি প্রাসঙ্গিক উপাদানগুলিকে ContextProvider
এর সাথে মোড়ানো হয়ে গেলে, আপনি এটি ব্যবহার করে এমন যে কোনও উপাদানের প্রসঙ্গ ডেটা সরাসরি অ্যাক্সেস করতে পারেন৷ চিন্তা করবেন না যদি আপনি এখনও এটি বুঝতে না পারেন; আসুন কোডের মধ্যে ডুব দেওয়া যাক এবং এটিকে কার্যত দেখি।
প্রথমে Vite.js ব্যবহার করে একটি React অ্যাপ তৈরি করা যাক। প্রকল্প সেট আপ করতে নিম্নলিখিত কমান্ডগুলি অনুলিপি করুন।
npm create vite@latest
cd project_name // to change to project directory npm install npm run dev
তারপর আপনি আপনার ব্রাউজারে আপনার ডেভেলপমেন্ট সার্ভার http://localhost:5173
খুলতে পারেন।
প্রথমে প্রয়োজনীয় ফোল্ডার তৈরি করা যাক। এখানে আমাদের প্রকল্পের ফোল্ডার গঠন.
src | components | context
কম্পোনেন্ট ফোল্ডারে Profile.jsx
ফাইল তৈরি করা যাক, এবং নিম্নলিখিত কোড যোগ করুন।
import React from 'react' const Profile = () => { return ( <div>Profile</div> ) } export default Profile
কম্পোনেন্ট ফোল্ডারে Navbar.jsx
নামে আরও একটি কম্পোনেন্ট তৈরি করুন।
import Profile from './Profile' const Navbar = () => { return ( <nav style={{ display: "flex", justifyContent: "space-between", alignItems: "center", width: "90%", height: "10vh", backgroundColor: theme === "light" ? "#fff" : "#1b1b1b", color: theme === "light" ? "#1b1b1b" : "#fff", border: "1px solid #fff", borderRadius: "5px", padding: "0 20px", marginTop: "40px", }}> <h1>LOGO</h1> <Profile /> </nav> ) } export default Navbar
আসুন App.jsx
ফাইলে এই <Navbar />
উপাদানটি আমদানি করি।
import Navbar from "./components/Navbar"; function App() { return ( <main style={{ display: "flex", flexDirection: "column", justifyContent: "start", alignItems: "center", height: "100vh", width: "100vw", }} > <Navbar /> </main> ); } export default App;
তাই মূলত, <Profile />
component হল <Navbar />
এর সন্তান এবং <Navbar />
হল <App />
উপাদানের সন্তান।
context
ফোল্ডারে UserContext.jsx
ফাইল তৈরি করা যাক। ফাইলে নিম্নলিখিত কোড যোগ করুন।
import { createContext, useEffect, useState } from "react"; export const UserContext = createContext(); export const UserProvider = ({ children }) => { const [user, setUser] = useState(null); const fetchUserData = async (id) => { const response = await fetch( `https://jsonplaceholder.typicode.com/users/${id}` ).then((response) => response.json()); console.log(response); setUser(response); }; useEffect(() => { fetchUserData(1); }, []); return ( <UserContext.Provider value={{ user, fetchUserData }} > {children} </UserContext.Provider> ); };
createContext
ব্যবহার করে একটি খালি UserContext
অবজেক্ট তৈরি করি। আমরা react
থেকে এটি আমদানি নিশ্চিত করি। আমরা কনটেক্সট অবজেক্টের ভিতরে ডিফল্ট মান যোগ করতে পারি, কিন্তু আমরা এটিকে আপাতত শূন্য রাখি।
UserProvider
তৈরি করি, যা UserContext
ব্যবহার করে একটি প্রদানকারী প্রদান করে, যেমন UserContext.Provider
। এটি শিশুদের উপাদানগুলির চারপাশে মোড়ানো, এবং মান অনুযায়ী, আমরা চাইল্ড উপাদানগুলিতে ব্যবহার করতে চাই এমন কিছু পাস করতে পারি।
fetchUserData
ফাংশন id
গ্রহণ করে এবং ব্যবহারকারীর ডেটা আনতে সেই ID ব্যবহার করে। তারপরে আমরা প্রতিক্রিয়াটি user
অবস্থায় সংরক্ষণ করি।
useEffect
এ fetchUserData
ফাংশনকে কল করছি তাই পৃষ্ঠা লোড হলে, এটি ফাংশনটিকে কল করে এবং এটি user
অবস্থায় ডেটা ইনজেক্ট করে।
এখন, <App />
কম্পোনেন্টে এই প্রসঙ্গটি ব্যবহার করা যাক। <UserProvider />
ব্যবহার করে <NavBar />
উপাদানটি মোড়ানো; নিম্নলিখিত কোড হিসাবে একই:
<UserProvider> <Navbar /> </UserProvider>
আসুন <Profile />
কম্পোনেন্টে user
স্টেট ব্যবহার করি। এর জন্য, আমরা useContext
হুক ব্যবহার করব। এটি UserContext
নেয় এবং user
অবস্থা এবং fetchUserData
ফাংশনের মতো UserProvider
এ আমরা পাস করেছি এমন মানগুলি প্রদান করে। মনে রাখবেন, আমাদের <Profile />
উপাদানটি মোড়ানোর দরকার নেই কারণ এটি ইতিমধ্যেই <Navbar />
উপাদানে রয়েছে যা সরবরাহকারীর সাথে ইতিমধ্যেই মোড়ানো রয়েছে।
Profile.jsx
খুলুন, এবং নিম্নলিখিত কোড যোগ করুন.
const { user } = useContext(UserContext); if (user) { return ( <span style={{ fontWeight: "bold", }} > {user.name} </span> ); } else { return <span>Login</span>; }
এখানে, আমরা UserContext
থেকে user
স্টেট ব্যবহার করছি। অন্যথায় user
থাকলে আমরা ব্যবহারকারীর নাম প্রদর্শন করব, আমরা শুধু একটি লগইন বার্তা প্রদর্শন করব। এখন, আপনি যদি আউটপুট দেখতে পান তাহলে navbar কম্পোনেন্টে একটি ব্যবহারকারীর নাম থাকা উচিত। এইভাবে আমরা সরাসরি যে কোনও উপাদানের প্রসঙ্গে যে কোনও রাজ্য ব্যবহার করতে পারি। যে উপাদানটি এই অবস্থাটি ব্যবহার করে সেটিকে <Provider />
মধ্যে আবৃত করা উচিত।
আপনি পাশাপাশি একাধিক প্রসঙ্গও ব্যবহার করতে পারেন। নিম্নলিখিত উদাহরণে দেখানো হিসাবে আপনাকে কেবল অন্য প্রদানকারী উপাদানগুলির মধ্যে প্রদানকারী উপাদানগুলিকে মোড়ানো দরকার।
<ThemeProvider> <UserProvider> <Navbar /> </UserProvider> </ThemeProvider>
উপরের উদাহরণে, আমরা <ThemeProvider />
ব্যবহার করছি যা থিম অবস্থা পরিচালনা করে।
একাধিক প্রসঙ্গ সরবরাহকারী ব্যবহার করার সম্পূর্ণ উদাহরণ দেখতে আপনি উপরের ইউটিউব ভিডিওটি দেখতে পারেন।
আপনি যখন একাধিক উপাদানে প্রসঙ্গ API ব্যবহার করেন তখন একটি সমস্যা হয়। যখনই প্রসঙ্গ API-এ রাষ্ট্র বা মান পরিবর্তিত হয়, এটি সেই নির্দিষ্ট প্রসঙ্গে সদস্যতা নেওয়া সমস্ত উপাদানকে পুনরায় রেন্ডার করে, এমনকি সমস্ত উপাদান পরিবর্তিত অবস্থা ব্যবহার না করলেও। এই রি-রেন্ডারিং সমস্যাটি বোঝার জন্য, আসুন একটি <Counter />
উপাদান তৈরি করি যা গণনা মান সংরক্ষণ এবং প্রদর্শন করতে প্রসঙ্গ ব্যবহার করে।
নিম্নলিখিত উদাহরণ দেখুন. আপনি উপাদান ফোল্ডারে একটি Counter.jsx
ফাইল তৈরি করতে পারেন এবং নিম্নলিখিত কোডটি পেস্ট করতে পারেন।
import { createContext, memo, useContext, useState } from "react"; const CountContext = createContext(); const CountProvider = ({ children }) => { const [count, setCount] = useState(0); return ( <CountContext.Provider value={{ count, setCount }}> {children} </CountContext.Provider> ); }; function CountTitle() { console.log("This is Count Title component"); return <h1>Counter Title</h1>; } function CountDisplay() { console.log("This is CountDisplay component"); const { count } = useContext(CountContext); return <div>Count: {count}</div>; } function CounterButton() { console.log("This is CounterButton component"); const { count, setCount } = useContext(CountContext); return ( <> <CountTitle /> <CountDisplay /> <button onClick={() => setCount(count + 1)}>Increase</button> </> ); } export default function Counter() { return ( <CountProvider> <CounterButton /> </CountProvider> ); }
উপরের কোডে:
createContext.
ব্যবহার করে একটি CountContext
অবজেক্ট তৈরি করি।
CountProvider,
গণনার মান সংরক্ষণ করার জন্য আমাদের একটি রাজ্য আছে। আমরা ভ্যালু প্রপের মাধ্যমে চাইল্ড কম্পোনেন্টে count
এবং setCount
পদ্ধতি পাঠাচ্ছি।
পৃথক পৃথক উপাদান কতবার পুনরায় রেন্ডার হয় তা দেখার জন্য আমরা আলাদাভাবে উপাদান তৈরি করেছি।
<CountTitle />
: এই উপাদানটি শুধুমাত্র শিরোনাম প্রদর্শন করে এবং এমনকি প্রসঙ্গ থেকে কোনো মান ব্যবহার করে না।
<CountDisplay />
: এই উপাদানটি গণনা মান প্রদর্শন করে এবং প্রসঙ্গ থেকে count
অবস্থা ব্যবহার করে।
<CounterButton />
: এই উপাদানটি উপরের উপাদান এবং একটি বোতাম উভয়ই রেন্ডার করে যা setCount
ব্যবহার করে গণনার মান বাড়ায়।
শেষে, আমরা CountProvider
কম্পোনেন্টের মধ্যে <CounterButton />
কম্পোনেন্টটি গুটিয়ে রাখছি যাতে অন্যান্য উপাদানগুলি গণনার মানগুলি অ্যাক্সেস করতে পারে।
এখন, যদি আপনি কোডটি চালান এবং Increase
বোতামে ক্লিক করেন, আপনি লগগুলিতে দেখতে পাবেন যে প্রতিটি উপাদান প্রতিবার রাষ্ট্র পরিবর্তন করার সময় পুনরায় রেন্ডার করছে। <CountTitle />
এমনকি গণনা মান ব্যবহার করছে না তবুও এটি পুনরায় রেন্ডার হচ্ছে। এটি ঘটছে কারণ <CountTitle />
এর মূল উপাদান যা <CounterButton />
ব্যবহার করছে এবং গণনার মান আপডেট করছে এবং সেই কারণেই পুনরায় রেন্ডার করা হচ্ছে।
কিভাবে আমরা এই আচরণ অপ্টিমাইজ করতে পারি? উত্তর memo
. রিঅ্যাক্ট memo
আপনাকে কোনো কম্পোনেন্টের প্রপস অপরিবর্তিত থাকলে রি-রেন্ডারিং এড়িয়ে যেতে দেয়। <CountTitle />
উপাদানের পরে, আসুন নিম্নলিখিত লাইনটি যোগ করি।
const MemoizedCountTitle = React.memo(CountTitle)
এখন, <CounterButton />
কম্পোনেন্টে, যেখানে আমরা <CountTitle />
কম্পোনেন্ট রেন্ডার করছি, নিচের কোডের মত <CountTitle />
কে <MemoizedCountTitle />
দিয়ে প্রতিস্থাপন করুন:
<> <MemoizedCountTitle /> <CountDisplay /> <button onClick={() => setCount(count + 1)}>Increase</button> </>
এখন, আপনি যদি গণনা বাড়ান এবং লগগুলি পরীক্ষা করেন, আপনি দেখতে সক্ষম হবেন যে এটি আর <CountTitle />
উপাদান রেন্ডার করছে না।
Redux
হল একটি স্টেট ম্যানেজমেন্ট লাইব্রেরি যা জটিল স্টেট ম্যানেজমেন্টের জন্য আরও অনুমানযোগ্য স্টেট ট্রানজিশন সহ। যদিও কনটেক্সট এপিআই সাধারণ স্টেট ম্যানেজমেন্টের জন্য ডিজাইন করা হয়েছে এবং প্রপ ড্রিলিং ছাড়াই কম্পোনেন্ট ট্রির মাধ্যমে ডেটা পাস করার জন্য ডিজাইন করা হয়েছে। সুতরাং, কখন কোনটি বেছে নেবেন?
এছাড়াও আরও একটি গ্রন্থাগার রয়েছে যা রাষ্ট্র পরিচালনার জন্য একটি জনপ্রিয় বিকল্প। রিঅ্যাক্ট রিকোয়েল ।
আপনি যদি React Recoil সম্পর্কে আরও জানতে আগ্রহী হন, তাহলে মন্তব্যে আমাকে জানান এবং আমি আপনার প্রতিক্রিয়ার উপর ভিত্তি করে এই বিষয়ে গভীরভাবে টিউটোরিয়াল তৈরি করব।
React.js
কনটেক্সট API একাধিক উপাদান জুড়ে রাজ্যগুলি পরিচালনা করার একটি শক্তিশালী এবং দক্ষ উপায় অফার করে, কার্যকরভাবে প্রপ ড্রিলিংয়ের সমস্যাটি সমাধান করে। প্রসঙ্গ API ব্যবহার করে, আপনি আপনার কোড সরলীকরণ করতে পারেন, অপ্রয়োজনীয় রি-রেন্ডার কমাতে পারেন এবং সামগ্রিক অ্যাপ্লিকেশন কর্মক্ষমতা উন্নত করতে পারেন।
যদিও কনটেক্সট API সাধারণ স্টেট ম্যানেজমেন্টের জন্য আদর্শ, আরও জটিল অ্যাপ্লিকেশনগুলি Redux
বা React Recoil
এর মতো অন্যান্য স্টেট ম্যানেজমেন্ট লাইব্রেরি ব্যবহার করে উপকৃত হতে পারে। কখন এবং কীভাবে এই সরঞ্জামগুলি ব্যবহার করবেন তা বোঝা আপনাকে আরও রক্ষণাবেক্ষণযোগ্য এবং স্কেলযোগ্য প্রতিক্রিয়া অ্যাপ্লিকেশন তৈরি করতে সক্ষম করবে।
এই নিবন্ধটি পড়ার জন্য ধন্যবাদ, আমি আশা করি আপনি এটি সহায়ক পেয়েছেন। আপনি যদি React, Redux, এবং Next.js ব্যবহার করে প্রজেক্ট শিখতে এবং তৈরি করতে আগ্রহী হন, আপনি এখানে আমার YouTube চ্যানেল দেখতে পারেন: CodeBucks
এখানে আমার অন্যান্য নিবন্ধ রয়েছে যা আপনি পড়তে পছন্দ করতে পারেন:
Lenis এবং GSAP এর সাথে Next.js-এ মসৃণ স্ক্রলিং কিভাবে বাস্তবায়ন করা যায়
সেরা 10টি জনপ্রিয় ভিএস কোড থিম আপনার চেষ্টা করা উচিত
আমার ব্যক্তিগত ব্লগ দেখুন: DevDreaming