ReactJS অ্যাপ্লিকেশনগুলির পারফরম্যান্স অপটিমাইজেশন খুবই গুরুত্বপূর্ণ, বিশেষ করে যখন অ্যাপ্লিকেশন বড় হয়ে ওঠে এবং এতে অনেক কম্পোনেন্ট এবং ডেটা পরিচালনা করতে হয়। পারফরম্যান্স অপটিমাইজেশন মানে হলো, React অ্যাপ্লিকেশনটির গতিকে বৃদ্ধি করা, লোড টাইম কমানো এবং ইউজারের জন্য আরও স্ন্যাপি এবং প্রতিক্রিয়া-দায়ী অভিজ্ঞতা প্রদান করা।
ReactJS-এ পারফরম্যান্স অপটিমাইজ করার জন্য বেশ কিছু টেকনিক এবং উপায় রয়েছে, যেগুলি আপনাকে অ্যাপ্লিকেশন আরও দ্রুত এবং কার্যকরী করতে সাহায্য করবে।
১. React.memo ব্যবহার করা
React.memo একটি হাইয়ার অর্ডার কম্পোনেন্ট (HOC) যা একটি কম্পোনেন্টের রেন্ডারিংকে মেমোরাইজ করতে সাহায্য করে। এটি শুধুমাত্র তখনই কম্পোনেন্টকে পুনরায় রেন্ডার করবে যখন তার props পরিবর্তিত হবে। এটি সাধারণত Functional কম্পোনেন্টে ব্যবহৃত হয়।
React.memo ব্যবহারের মাধ্যমে আপনি unnecessary re-renders কমাতে পারেন, যেহেতু React শুধুমাত্র props পরিবর্তিত হলে কম্পোনেন্টকে রেন্ডার করবে।
উদাহরণ:
const MyComponent = React.memo(function MyComponent(props) {
console.log('Component Rendered');
return <div>{props.value}</div>;
});
এখানে, MyComponent কম্পোনেন্টটি শুধুমাত্র তখনই রেন্ডার হবে যখন props.value পরিবর্তিত হবে।
২. useCallback হুক ব্যবহার করা
React-এ useCallback হুক ব্যবহার করে আপনি ফাংশনগুলোকে মেমোরাইজ করতে পারেন, যাতে ফাংশন পুনরায় তৈরি না হয় এবং unnecessary re-renders এড়ানো যায়। এটি মূলত function props বা event handlers এর ক্ষেত্রে ব্যবহৃত হয়।
useCallback হুকটি শুধুমাত্র সেই ফাংশনগুলো মেমোরাইজ করে, যেগুলো কোনো নির্দিষ্ট dependency এর উপর ভিত্তি করে পরিবর্তিত হয়।
উদাহরণ:
import React, { useState, useCallback } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const memoizedCallback = useCallback(() => {
console.log('Function called');
}, []);
return (
<ChildComponent onClick={memoizedCallback} />
);
}
function ChildComponent({ onClick }) {
return <button onClick={onClick}>Click me</button>;
}
এখানে, memoizedCallback ফাংশনটি শুধুমাত্র একবার তৈরি হবে এবং পরবর্তীতে প্রতিটি রেন্ডারিংয়ের সময় এটি পুনরায় তৈরি হবে না।
৩. useMemo হুক ব্যবহার করা
useMemo হুকটি একটি value কে মেমোরাইজ করতে ব্যবহৃত হয়, যাতে expensive computation বার বার না করা হয়। এটি ডেটা বা calculation যেগুলি শুধুমাত্র নির্দিষ্ট dependencies পরিবর্তিত হলে পুনরায় রেন্ডার হয়, সেগুলোর জন্য খুবই কার্যকরী।
উদাহরণ:
import React, { useState, useMemo } from 'react';
function ExpensiveCalculationComponent({ num }) {
const calculateFactorial = (n) => {
let result = 1;
for (let i = 1; i <= n; i++) {
result *= i;
}
return result;
};
const memoizedValue = useMemo(() => calculateFactorial(num), [num]);
return <div>Factorial of {num} is {memoizedValue}</div>;
}
এখানে, calculateFactorial ফাংশনটি শুধুমাত্র num পরিবর্তিত হলে পুনরায় রান করবে, অর্থাৎ এটি unnecessary recomputation এড়াতে সাহায্য করবে।
৪. Lazy Loading এবং Code Splitting
ReactJS-এ Lazy Loading এবং Code Splitting ব্যবহার করে অ্যাপ্লিকেশনের লোড টাইম কমানো সম্ভব। এই পদ্ধতিগুলির মাধ্যমে আপনি অ্যাপ্লিকেশনের শুধুমাত্র প্রয়োজনীয় অংশগুলি প্রথমে লোড করতে পারেন এবং বাকি অংশগুলি ব্যবহারকারীর ইন্টারঅ্যাকশনের ভিত্তিতে ধাপে ধাপে লোড হবে।
React-এ React.lazy এবং Suspense ব্যবহার করে কম্পোনেন্ট লোডিং বিলম্বিত করা সম্ভব।
উদাহরণ:
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}
এখানে, LazyComponent শুধুমাত্র তখনই লোড হবে যখন এটি ব্যবহারকারীর দ্বারা দেখা হবে।
৫. Virtualization (Windowing) ব্যবহার করা
Virtualization একটি পদ্ধতি যেখানে শুধুমাত্র দৃশ্যমান অংশের উপাদানগুলো রেন্ডার করা হয় এবং অবশিষ্ট অংশগুলোর জন্য শুধুমাত্র placeholder রাখা হয়। এটি বড় তালিকা বা বড় ডেটাসেট রেন্ডার করার সময় পারফরম্যান্স অপটিমাইজ করার একটি অত্যন্ত কার্যকরী পদ্ধতি।
React-এ react-window বা react-virtualized লাইব্রেরি ব্যবহার করে আপনি এই virtualization করতে পারেন।
উদাহরণ:
import { FixedSizeList as List } from 'react-window';
function MyList({ items }) {
return (
<List
height={150}
itemCount={items.length}
itemSize={35}
width={300}
>
{({ index, style }) => (
<div style={style}>
{items[index]}
</div>
)}
</List>
);
}
এখানে, শুধুমাত্র দৃশ্যমান তালিকা আইটেমগুলো রেন্ডার করা হচ্ছে, বাকিগুলো নয়, যা পারফরম্যান্সে উল্লেখযোগ্য উন্নতি ঘটায়।
৬. Avoiding Inline Functions in Render
React-এ inline function ব্যবহার করলে প্রতিটি রেন্ডারিংয়ে নতুন ফাংশন তৈরি হয়, যা unnecessary re-renders সৃষ্টি করতে পারে। তাই, render method বা JSX-এর মধ্যে inline ফাংশন না লিখে, ফাংশনগুলো কম্পোনেন্ট লেভেলে ডিফাইন করা উচিত।
Inline function avoid করা:
// Avoid this:
<button onClick={() => setCount(count + 1)}>Click me</button>
// Instead do this:
const handleClick = () => setCount(count + 1);
<button onClick={handleClick}>Click me</button>
এখানে, handleClick ফাংশনটি বার বার নতুন করে তৈরি হবে না, তাই unnecessary re-renders কমবে।
সারাংশ
ReactJS পারফরম্যান্স অপটিমাইজেশনের জন্য কিছু গুরুত্বপূর্ণ পদ্ধতি যেমন React.memo, useCallback, useMemo, Code Splitting, Lazy Loading, Virtualization ইত্যাদি ব্যবহার করা যেতে পারে। এই পদ্ধতিগুলো React অ্যাপ্লিকেশনকে দ্রুত এবং আরও কার্যকরী করতে সাহায্য করবে, বিশেষ করে যখন অ্যাপ্লিকেশনটি বড় হয়ে ওঠে। Proper optimization techniques ব্যবহারের মাধ্যমে, আপনি ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে পারবেন এবং অ্যাপ্লিকেশনের লোড টাইম কমাতে সক্ষম হবেন।
ReactJS-এর উন্নত পারফরম্যান্স নিশ্চিত করা একটি গুরুত্বপূর্ণ বিষয়, বিশেষত বড় অ্যাপ্লিকেশনের ক্ষেত্রে। React অ্যাপ্লিকেশন যখন বড় হয়ে যায়, তখন অনেকটা ডেটা এবং রেন্ডারিং অপারেশন একসাথে পরিচালনা করা হয়, যা পারফরম্যান্স সমস্যার সৃষ্টি করতে পারে। সুতরাং, React অ্যাপ্লিকেশনের পারফরম্যান্স অপটিমাইজ করার জন্য বিভিন্ন পদ্ধতি এবং কৌশল রয়েছে।
এখানে ReactJS-এর পারফরম্যান্স সমস্যা এবং এগুলোর সমাধান করার জন্য বিভিন্ন অপটিমাইজেশন কৌশল আলোচনা করা হলো।
ReactJS Performance Issues
- Unnecessary Re-renders: একে বলা হয় রেন্ডারিং অপটিমাইজেশন সমস্যা, যখন কম্পোনেন্টগুলি প্রয়োজনীয়তা ছাড়াই বারবার রেন্ডার হয়। এটির কারণ হতে পারে কম্পোনেন্টের স্টেট বা প্রপ্স পরিবর্তন যা রেন্ডারিং ট্রিগার করে।
- Heavy Component Trees: খুব বড় কম্পোনেন্ট ট্রি (Component Tree) পারফরম্যান্সে প্রভাব ফেলতে পারে, কারণ React সার্ভারের মধ্যে প্রতিটি কম্পোনেন্ট আপডেট করলে পুরো কম্পোনেন্ট ট্রি পুনরায় রেন্ডার হতে পারে।
- State Management: সঠিকভাবে স্টেট ম্যানেজ না করলে অ্যাপ্লিকেশন স্লো হয়ে যেতে পারে, বিশেষ করে যখন কোনো কম্পোনেন্টের স্টেট পরিবর্তন হয় এবং সেটি অনেক অংশে প্রপ্স হিসাবে পাস হয়।
- Large Lists and Tables: বড় ডেটা সেট (যেমন, বড় লিস্ট বা টেবিল) রেন্ডার করলে পারফরম্যান্স সমস্যা হতে পারে। প্রতিটি আইটেম রেন্ডার করার সময় অনেক বেশি রেন্ডারিং অপারেশন হতে পারে।
- Excessive use of useEffect and useState:
useEffectএবংuseStateহুকগুলি বেশি ব্যবহার করলে অবাঞ্ছিত রেন্ডারিং ট্রিগার হতে পারে, বিশেষ করে যখন ডিপেনডেন্সি অ্যারে ঠিকমতো কনফিগার না করা হয়।
ReactJS Performance Optimization Techniques
React অ্যাপ্লিকেশনের পারফরম্যান্স উন্নত করার জন্য কিছু সাধারণ কৌশল এবং টিপস রয়েছে। এগুলো ব্যবহার করলে আপনার অ্যাপ্লিকেশন আরও দ্রুত এবং রেসপন্সিভ হয়ে উঠবে।
1. Memoization (React.memo, useMemo, useCallback)
React.memo
React কম্পোনেন্ট যদি একই প্রপ্সে পুনরায় রেন্ডার হয়, তবে এটি আবারও রেন্ডার করতে পারে, যা অপ্রয়োজনীয় রেন্ডারিং ঘটায়। React.memo ব্যবহার করলে এটি কেবল তখনই রেন্ডার হবে যখন প্রপ্সে পরিবর্তন হবে, অন্যথায় রেন্ডারটি এড়িয়ে যাবে।
উদাহরণ:
const MyComponent = React.memo((props) => {
console.log('Rendering MyComponent');
return <div>{props.text}</div>;
});
useMemo
useMemo হুকটি গাণিতিক বা কঠিন হিসাব করা ফাংশনগুলো মেমোরাইজ (cache) করতে ব্যবহৃত হয়, যাতে তারা পুনরায় কল না হয়।
উদাহরণ:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
useCallback
useCallback হুকটি মেমোরাইজড ফাংশন তৈরির জন্য ব্যবহৃত হয়, যাতে প্রতিবার রেন্ডার হওয়ার সময় নতুন ফাংশন তৈরি না হয়।
উদাহরণ:
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
2. Code Splitting (Lazy Loading)
React অ্যাপ্লিকেশনের কোডকে ছোট ছোট ভাগে ভাগ করা, বা Code Splitting, অ্যাপ্লিকেশন লোডিং টাইম কমাতে সাহায্য করে। React-এ কোড স্প্লিটিং করতে React.lazy() এবং Suspense ব্যবহার করা হয়।
উদাহরণ:
import React, { Suspense } from 'react';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</div>
);
}
এখানে LazyComponent কেবল তখনই লোড হবে যখন এটি প্রয়োজন হবে, যার ফলে অ্যাপ্লিকেশন লোডিং সময় কমে যাবে।
3. Virtualization (React Window / React Virtualized)
বড় লিস্ট বা টেবিল রেন্ডার করার সময়, Virtualization ব্যবহার করলে পারফরম্যান্স অনেক ভালো হয়। এটি লিস্টের বা টেবিলের যে আইটেমগুলো স্ক্রিনে দেখা যায়, শুধুমাত্র সেগুলোকেই রেন্ডার করে, বাকি আইটেমগুলো লোড করা হয় না যতক্ষণ না সেগুলি স্ক্রিনে আসে।
React-এ React Window বা React Virtualized লাইব্রেরি ব্যবহার করা যেতে পারে।
React Window উদাহরণ:
import { FixedSizeList as List } from 'react-window';
function MyList() {
return (
<List
height={150}
itemCount={1000}
itemSize={35}
width={300}
>
{({ index, style }) => (
<div style={style}>Item {index}</div>
)}
</List>
);
}
4. Avoid Anonymous Functions in JSX
React-এ JSX এর মধ্যে অ্যানোনিমাস ফাংশন ব্যবহার করলে, প্রতিবার রেন্ডার হওয়ার সময় নতুন ফাংশন তৈরি হয়। এর ফলে অপটিমাইজেশন কম হয় এবং পুনরায় রেন্ডার হয়। অ্যানোনিমাস ফাংশনগুলি useCallback বা অন্য কোন স্থির ফাংশন ব্যবহার করে প্রতিরোধ করা যেতে পারে।
5. Optimize Context Usage
React Context হুকটি যখন বড় কম্পোনেন্ট ট্রীতে ব্যবহৃত হয়, তখন এটা সারা অ্যাপ্লিকেশনকে রেন্ডার করতে পারে, যা পারফরম্যান্সের সমস্যা সৃষ্টি করে। Context API ব্যবহার করার সময় কম্পোনেন্টগুলিকে যথাসম্ভব ছোট ও নির্দিষ্ট রাখুন এবং ভ্যালু আপডেটের পর শুধুমাত্র প্রয়োজনীয় কম্পোনেন্টগুলোই রেন্ডার হবে তা নিশ্চিত করুন।
6. Debouncing and Throttling for Expensive Operations
যদি কোনো ইভেন্ট (যেমন টাইপিং, স্ক্রলিং) অনেক বার ট্রিগার হয়, তবে debouncing বা throttling ব্যবহার করতে হবে যাতে একাধিক ইভেন্ট একসাথে প্রসেস না হয় এবং পারফরম্যান্স ঠিক থাকে।
Debouncing উদাহরণ (Input field):
import { useState } from 'react';
import { debounce } from 'lodash';
function SearchComponent() {
const [query, setQuery] = useState('');
const handleChange = debounce((event) => {
setQuery(event.target.value);
}, 500);
return <input type="text" onChange={handleChange} />;
}
সারাংশ
ReactJS অ্যাপ্লিকেশনের পারফরম্যান্স অপটিমাইজ করতে হলে, অ্যাপ্লিকেশনটির স্টেট ম্যানেজমেন্ট, রেন্ডারিং অপটিমাইজেশন, কোড স্প্লিটিং, ভার্চুয়ালাইজেশন এবং ডিবাউন্সিং ব্যবহার করা উচিত। উপরের টিপস এবং কৌশলগুলো ব্যবহার করলে আপনি React অ্যাপ্লিকেশনের পারফরম্যান্সে উল্লেখযোগ্য উন্নতি দেখতে পাবেন।
ReactJS-এ memoization একটি অপটিমাইজেশন কৌশল যা ফাংশনাল কম্পোনেন্টের অপ্রয়োজনীয় রেন্ডারিং রোধ করতে ব্যবহৃত হয়। এটি মূলত এমন একটি কৌশল, যেখানে কোনো কম্পোনেন্ট শুধুমাত্র যখন প্রপ্স বা স্টেট পরিবর্তিত হয় তখনই রেন্ডার হয়। এতে পারফরম্যান্স উন্নত হয়, বিশেষত বড় অ্যাপ্লিকেশনগুলোতে যেখানে একাধিক কম্পোনেন্ট রেন্ডার হতে থাকে।
ReactJS-এ React.memo একটি হাইঅর্ডার কম্পোনেন্ট (Higher Order Component, HOC) যা ফাংশনাল কম্পোনেন্টের মেমোাইজেশন (memoization) সহজতর করে। এটি শুধুমাত্র তখনই কম্পোনেন্ট রেন্ডার করে যখন তার প্রপ্স পরিবর্তিত হয়।
Memoization কী?
Memoization হল একটি কৌশল, যেখানে একটি ফাংশন শুধুমাত্র তখনই পুনরায় কল করা হয় যদি তার ইনপুট বা আর্গুমেন্ট পরিবর্তিত হয়। ReactJS-এ, এটি মূলত কম্পোনেন্টের পুনঃরেন্ডারিং রোধ করার জন্য ব্যবহৃত হয়। React.memo হুক ব্যবহারের মাধ্যমে, React এটি নির্ধারণ করে যে কোনো কম্পোনেন্ট যদি তার প্রপ্সের জন্য একই ভ্যালু পায়, তবে এটি পূর্বের রেন্ডার ফলাফলটি পুনরায় ব্যবহার করবে।
React.memo কী?
React.memo একটি হাইঅর্ডার কম্পোনেন্ট (HOC) যা একটি ফাংশনাল কম্পোনেন্টকে মেমোাইজ করে। এটি ফাংশনাল কম্পোনেন্টের অপ্রয়োজনীয় রেন্ডারিং বন্ধ করে, যদি কম্পোনেন্টের প্রপ্স আগের মতই থাকে। এটি শুধুমাত্র তখনই রেন্ডারিং ঘটাবে, যখন কম্পোনেন্টের প্রপ্স পরিবর্তিত হবে।
React.memo এর সিঁট্যাক্স:
const MyComponent = React.memo((props) => {
// কম্পোনেন্টের JSX রিটার্ন
return <div>{props.name}</div>;
});
এখানে, React.memo ফাংশনটি MyComponent কে রিটার্ন করবে এবং এটি শুধুমাত্র তখনই পুনরায় রেন্ডার করবে যখন props.name পরিবর্তিত হবে।
React.memo ব্যবহার করার সময়
১. প্রপ্সের অপ্রয়োজনীয় পরিবর্তন রোধ
ধরা যাক, আপনি একটি লিস্ট রেন্ডার করছেন এবং প্রতিটি লিস্ট আইটেম একটি আলাদা কম্পোনেন্ট। যদি কোনো পরিবর্তন না হয়, তবে পুরো লিস্টটি পুনরায় রেন্ডার হওয়ার প্রয়োজন নেই। এই ক্ষেত্রে React.memo ব্যবহার করে আপনি শুধুমাত্র সেই আইটেমগুলিকেই রেন্ডার করতে পারবেন যেগুলোর প্রপ্স পরিবর্তিত হয়েছে।
উদাহরণ:
import React from 'react';
const ListItem = React.memo(({ item }) => {
console.log('Rendering: ', item.name);
return <li>{item.name}</li>;
});
const List = ({ items }) => {
return (
<ul>
{items.map((item) => (
<ListItem key={item.id} item={item} />
))}
</ul>
);
};
এখানে, ListItem কম্পোনেন্টটি শুধুমাত্র তখনই রেন্ডার হবে যখন তার প্রপ্স পরিবর্তিত হবে, যা কম্পোনেন্টের পারফরম্যান্স উন্নত করবে। React.memo এখানে তালিকাভুক্ত আইটেমের মধ্যে অপ্রয়োজনীয় রেন্ডারিং কমাবে।
২. কাস্টম ইকুয়ালিটি চেক
ডিফল্টভাবে, React.memo শুধুমাত্র শ্যালো (shallow) কম্পেয়ারসন করে অর্থাৎ শুধুমাত্র প্রপ্সের উপরের স্তরের পরিবর্তন দেখবে। যদি আপনার প্রপ্সগুলি কোনো জটিল ডেটা স্ট্রাকচার যেমন অবজেক্ট বা অ্যারে হয়, তবে আপনাকে একটি কাস্টম ইকুয়ালিটি চেক (custom equality check) প্রদান করতে হতে পারে।
উদাহরণ:
const MyComponent = React.memo(
({ user }) => {
console.log("Rendering MyComponent");
return <div>{user.name}</div>;
},
(prevProps, nextProps) => prevProps.user.id === nextProps.user.id
);
এখানে, React.memo-এর দ্বিতীয় আর্গুমেন্ট হিসেবে একটি কাস্টম কম্পেয়ার ফাংশন দেওয়া হয়েছে। এই ফাংশনটি শুধুমাত্র তখনই true রিটার্ন করবে যখন user.id অপরিবর্তিত থাকবে, অর্থাৎ user অবজেক্টের অন্যান্য প্রপ্সে কোনো পরিবর্তন ঘটলেও কম্পোনেন্ট রেন্ডার হবে না।
৩. React.memo এবং স্টেট পরিবর্তন
React.memo শুধুমাত্র প্রপ্সের উপর ভিত্তি করে কাজ করে, স্টেট পরিবর্তন হলে এটি কম্পোনেন্ট পুনরায় রেন্ডার করবে। তবে, যদি আপনি এমন কোনো কেসে থাকেন যেখানে স্টেট পরিবর্তন হলে কিছু অপটিমাইজেশন করতে চান, তবে আপনাকে অন্য স্টেট ব্যবস্থাপনা টুল বা মেমোাইজেশন কৌশল (যেমন useMemo বা useCallback) ব্যবহার করতে হতে পারে।
সারাংশ
React.memoএকটি ফাংশনাল কম্পোনেন্টকে মেমোাইজ করে, যার মাধ্যমে আপনি অপ্রয়োজনীয় রেন্ডারিং কমাতে পারেন।- এটি কম্পোনেন্টের প্রপ্স পরিবর্তিত হলে পুনরায় রেন্ডার করে এবং আগের প্রপ্স একই থাকলে তা রেন্ডার বন্ধ করে দেয়।
- আপনি কাস্টম ইকুয়ালিটি চেকও প্রদান করতে পারেন যা কিছু নির্দিষ্ট শর্তে কম্পোনেন্টের রেন্ডারিং নিয়ন্ত্রণ করে।
- এটি বড় অ্যাপ্লিকেশনগুলিতে পারফরম্যান্স উন্নত করতে সাহায্য করে।
React.memo এবং memoization কম্পোনেন্টের অপ্রয়োজনীয় রেন্ডারিং কমিয়ে অ্যাপ্লিকেশনকে দ্রুত এবং কার্যকরী করতে সহায়তা করে।
ReactJS-এ Code Splitting একটি অত্যন্ত গুরুত্বপূর্ণ কৌশল, যা বড় অ্যাপ্লিকেশনগুলোর পারফরম্যান্স উন্নত করতে ব্যবহৃত হয়। এই কৌশলের মাধ্যমে অ্যাপ্লিকেশনের কোড একেবারে প্রথমে পুরোপুরি লোড না করে, প্রয়োজন অনুযায়ী ছোট ছোট ভাগে লোড করা হয়। React 16.6 থেকে React.lazy এবং Suspense হুক ব্যবহার করে Code Splitting সহজভাবে করা যায়।
Code Splitting কী?
Code Splitting হল একটি কৌশল যার মাধ্যমে অ্যাপ্লিকেশন বা ওয়েবপেজের কোডকে ছোট ছোট টুকরোতে ভাগ করা হয় এবং প্রয়োজনে সেই কোড লোড করা হয়। এর ফলে অ্যাপ্লিকেশনের প্রথম লোড সময় কমে যায় এবং ব্যবহারকারী দ্রুত অ্যাপ্লিকেশনটি ব্যবহার করতে পারে। ReactJS-এ React.lazy এবং Suspense এর সাহায্যে ডাইনামিকভাবে কম্পোনেন্ট লোড করা সম্ভব হয়, যা কোড স্প্লিটিং-এর জন্য অত্যন্ত উপকারী।
React.lazy এবং Suspense কী?
- React.lazy: এটি একটি React API, যা ডাইনামিকভাবে কম্পোনেন্ট লোড করতে ব্যবহৃত হয়। এটি কম্পোনেন্টের জন্য একটি পাদচরণ ফাংশন (dynamic import) ব্যবহার করে, যাতে শুধুমাত্র প্রয়োজনের সময় সেই কম্পোনেন্টটি লোড হয়।
- Suspense: এটি React-এর একটি বিল্ট-ইন কম্পোনেন্ট, যা লেজি লোডিং কম্পোনেন্টের জন্য "লোডিং" স্টেট পরিচালনা করে। যখন লেজি কম্পোনেন্ট লোড হয়ে না ওঠে, তখন Suspense কম্পোনেন্ট একটি ফলারব্যাক (fallback) UI দেখানোর সুযোগ দেয়।
React.lazy এবং Suspense দিয়ে Code Splitting উদাহরণ
ধরি, আমরা একটি React অ্যাপ্লিকেশন তৈরি করছি যেখানে কিছু কম্পোনেন্ট খুব বড় এবং শুধুমাত্র প্রয়োজনে তাদের লোড করতে চাই। আমরা React.lazy এবং Suspense ব্যবহার করে এই কম্পোনেন্টগুলোকে ডাইনামিকভাবে লোড করব।
১. React.lazy ব্যবহার করে কম্পোনেন্ট লোড করা
প্রথমে একটি কম্পোনেন্ট BigComponent তৈরি করি, যা বড় হতে পারে:
// BigComponent.js
import React from 'react';
const BigComponent = () => {
return (
<div>
<h2>This is a big component!</h2>
<p>It contains a lot of data and logic.</p>
</div>
);
};
export default BigComponent;
এখন, আমরা React.lazy ব্যবহার করে এই কম্পোনেন্টটি ডাইনামিকভাবে লোড করব:
// App.js
import React, { Suspense } from 'react';
// React.lazy দিয়ে BigComponent কে লেজি লোড করছি
const LazyBigComponent = React.lazy(() => import('./BigComponent'));
function App() {
return (
<div>
<h1>Welcome to my React App!</h1>
{/* Suspense দিয়ে লোডিং স্টেট হ্যান্ডেল করা */}
<Suspense fallback={<div>Loading...</div>}>
<LazyBigComponent />
</Suspense>
</div>
);
}
export default App;
এখানে, React.lazy() ব্যবহার করে BigComponent কে লেজি লোড করা হয়েছে। যখন কম্পোনেন্টটি লোড হবে না, তখন Suspense এর fallback প্রপস থেকে "Loading..." টেক্সট প্রদর্শিত হবে।
২. ফলারব্যাক UI (Fallback UI)
ফলারব্যাক UI হল সেই UI যেটি লোডিংয়ের সময় ব্যবহারকারীর জন্য দেখানো হয়। এটি সাধারণত "Loading..." বা স্পিনার ধরনের কিছু হতে পারে।
<Suspense fallback={<div>Loading component...</div>}>
<LazyBigComponent />
</Suspense>
এখানে, যখন BigComponent লোড হচ্ছে, তখন "Loading component..." টেক্সট ব্যবহারকারীকে দেখানো হবে। একবার কম্পোনেন্ট লোড হয়ে গেলে, এটি স্বাভাবিকভাবে রেন্ডার হবে।
Code Splitting এবং React.lazy এর সুবিধা
- পারফরম্যান্স উন্নয়ন: Code splitting দিয়ে, অ্যাপ্লিকেশন প্রথমে শুধু প্রয়োজনীয় কোড লোড করে, যার ফলে অ্যাপ্লিকেশনের লোড টাইম কমে যায়। এটি ব্যবহারকারীর অভিজ্ঞতা উন্নত করতে সহায়ক।
- ডাইনামিক লোডিং: React.lazy এবং Suspense ব্যবহারের মাধ্যমে আপনি আপনার অ্যাপ্লিকেশনের বিভিন্ন অংশ ডাইনামিকভাবে লোড করতে পারেন। এর ফলে কোডের আকার ছোট হয় এবং দ্রুত লোড হয়।
- মডুলার স্ট্রাকচার: Code splitting অ্যাপ্লিকেশনকে আরও মডুলার এবং স্কেলেবল করে তোলে, কারণ আপনি কোডের ছোট ছোট অংশে ভাগ করে তাদের আলাদাভাবে লোড করতে পারবেন।
আরো উন্নত Code Splitting
React.lazy এবং Suspense ব্যবহার করে আপনি কেবল কম্পোনেন্টগুলোই লোড করতে পারবেন না, পাশাপাশি আরো জটিল কনফিগারেশন যেমন API কল, ডাইনামিক রাউটিং ইত্যাদি ডাইনামিকভাবে লোড করতে পারেন। এছাড়া, React Router এবং lazy-loaded কম্পোনেন্টগুলোকে ব্যবহার করে পেজ লেভেল কোড স্প্লিটিংও করা যেতে পারে।
React.lazy এবং Suspense হুক ব্যবহার করে কোড স্প্লিটিং React অ্যাপ্লিকেশনগুলোর পারফরম্যান্স উন্নত করতে একটি শক্তিশালী উপায়। এগুলো ব্যবহারের মাধ্যমে আপনি অ্যাপ্লিকেশনের প্রথম লোড টাইম কমাতে পারেন এবং একটি স্মুথ, ফাস্ট, এবং মডুলার অ্যাপ্লিকেশন তৈরি করতে পারেন।
ReactJS-এ performance optimization একটি গুরুত্বপূর্ণ বিষয়, বিশেষ করে বড় এবং কমপ্লেক্স অ্যাপ্লিকেশনগুলোতে যেখানে স্টেট এবং রেন্ডারিং প্রক্রিয়া অনেক বেশি হতে পারে। useCallback এবং useMemo হুক দুটি পারফরম্যান্স অপটিমাইজেশনের জন্য ব্যবহৃত হয়, যাতে কম্পোনেন্টের অপ্রয়োজনীয় রেন্ডারিং এবং ফাংশন ক্রিয়েশন কমানো যায়। এই দুটি হুক আপনাকে পারফরম্যান্স বাড়ানোর জন্য React-এ কার্যকরভাবে ডেটা মেমোরাইজ করতে সাহায্য করে।
useMemo Hook কী?
useMemo হুকটি React-এ একটি মেমোরাইজেশন কৌশল হিসেবে কাজ করে, যেখানে একটি নির্দিষ্ট কম্পিউটেড ভ্যালু শুধুমাত্র তখনই রি-ক্যালকুলেট করা হয় যখন তার নির্ভরশীলতা পরিবর্তিত হয়। এটি প্রাথমিকভাবে গণনা (computation) ব্যয়বহুল কোনো অপারেশন থেকে পারফরম্যান্স অপটিমাইজেশন করতে ব্যবহৃত হয়।
Syntax:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
এখানে:
useMemoপ্রথম আর্গুমেন্ট হিসেবে একটি ফাংশন নেয়, যা গণনা করে একটি মেমোরাইজড মান রিটার্ন করে।- দ্বিতীয় আর্গুমেন্ট হিসেবে নির্ভরশীলতা (dependencies) অ্যারে দেওয়া হয়। যখন কোনো নির্ভরশীলতা পরিবর্তিত হয়, তখন
useMemoহুকটি পুনরায় গণনা করে।
উদাহরণ:
ধরা যাক, আপনার একটি লিস্ট এবং একটি অনুসন্ধান ফাংশন আছে, এবং এটি শুধুমাত্র তখনই রি-রেন্ডার হবে যখন অনুসন্ধানের শর্ত পরিবর্তিত হবে।
import React, { useState, useMemo } from 'react';
function SearchableList({ items, searchQuery }) {
const filteredItems = useMemo(() => {
return items.filter(item => item.includes(searchQuery));
}, [items, searchQuery]); // Only recompute when 'items' or 'searchQuery' changes
return (
<ul>
{filteredItems.map(item => (
<li key={item}>{item}</li>
))}
</ul>
);
}
এখানে, filteredItems শুধুমাত্র তখনই পুনরায় গণনা করা হবে যখন items অথবা searchQuery পরিবর্তিত হবে। যদি শুধুমাত্র অন্য কোনো স্টেট পরিবর্তিত হয়, তবে useMemo কম্পিউটেশনটি পুনরায় করা হবে না, ফলে পারফরম্যান্স ভালো থাকে।
useMemo এর সুবিধা:
- গণনা ব্যয়বহুল অপারেশন গুলোকে রি-ক্যালকুলেট করা কমিয়ে দেয়।
- ডিপেনডেন্সি চেকিংয়ের মাধ্যমে পারফরম্যান্স অপটিমাইজেশন করা হয়।
- কম্পোনেন্ট রেন্ডারিংয়ের সংখ্যা কমিয়ে দেয়।
useCallback Hook কী?
useCallback হুকটি বিশেষত যখন কোনো ফাংশনকে প্যারেন্ট কম্পোনেন্ট থেকে চাইল্ড কম্পোনেন্টে প্রপস হিসেবে পাঠানো হয়, তখন তা ব্যবহার করা হয়। এটি শুধুমাত্র তখনই একটি নতুন ফাংশন রিটার্ন করে যখন তার নির্ভরশীলতা পরিবর্তিত হয়। অন্যথায়, এটি একই ফাংশন রিটার্ন করে, যাতে অপ্রয়োজনীয় রি-রেন্ডারিং এড়ানো যায়।
Syntax:
const memoizedCallback = useCallback(() => { doSomething(a, b); }, [a, b]);
এখানে:
useCallbackপ্রথম আর্গুমেন্ট হিসেবে একটি ফাংশন নেয় এবং দ্বিতীয় আর্গুমেন্ট হিসেবে নির্ভরশীলতা অ্যারে নেয়।- এটি মেমোরাইজড ফাংশন রিটার্ন করে, যাতে একই ফাংশন বারবার তৈরি না হয়।
উদাহরণ:
ধরা যাক, আপনি একটি বাটন ক্লিক ফাংশন তৈরি করতে চান এবং এটি একটি চাইল্ড কম্পোনেন্টে পাস করবেন।
import React, { useState, useCallback } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []); // The function will not be recreated unless the dependencies change.
return <ChildComponent onIncrement={increment} />;
}
function ChildComponent({ onIncrement }) {
console.log('Child re-rendered');
return <button onClick={onIncrement}>Increment</button>;
}
এখানে:
incrementফাংশনটিuseCallbackদ্বারা মেমোরাইজড করা হয়েছে।- প্যারেন্ট কম্পোনেন্টে
incrementফাংশন বারবার রি-ক্রীএট না হয়ে, শুধুমাত্র একবার তৈরি হবে যদি তার নির্ভরশীলতা পরিবর্তিত না হয়।
useCallback এর সুবিধা:
- ফাংশনগুলি বারবার তৈরি হওয়া থেকে রক্ষা করে, যা বিশেষত বড় অ্যাপ্লিকেশনে পারফরম্যান্স অপটিমাইজেশনে সহায়ক।
- চাইল্ড কম্পোনেন্টে প্রপস হিসেবে ফাংশন পাস করার সময় অপ্রয়োজনীয় রি-রেন্ডারিং কমায়।
- React.memo এবং PureComponent এর সাথে ব্যবহৃত হলে আরও বেশি কার্যকর।
useMemo এবং useCallback এর মধ্যে পার্থক্য:
| Aspect | useMemo | useCallback |
|---|---|---|
| Purpose | Value মেমোরাইজ করতে ব্যবহার করা হয়। | Function মেমোরাইজ করতে ব্যবহার করা হয়। |
| Return Value | মেমোরাইজড মান রিটার্ন করে। | মেমোরাইজড ফাংশন রিটার্ন করে। |
| Use Case | যখন কোনো গণনা বা কম্পিউটেশন ব্যয়বহুল হয়। | যখন ফাংশন প্যারেন্ট থেকে চাইল্ড কম্পোনেন্টে পাস করা হয়। |
| Typical Usage | Performance অপটিমাইজেশনের জন্য, যেমন ফিল্টারিং বা গণনা। | Callback functions পাস করার ক্ষেত্রে, যেমন event handlers। |
সারাংশ
React-এ useMemo এবং useCallback হুকগুলি পারফরম্যান্স টিউনিংয়ের জন্য অপরিহার্য টুল। useMemo কস্টলি গণনাগুলোকে মেমোরাইজ করতে এবং useCallback পুনরায় ফাংশন ক্রিয়েশন কমাতে ব্যবহৃত হয়। এই হুকগুলো ব্যবহারের মাধ্যমে আপনি অ্যাপ্লিকেশনের অপ্রয়োজনীয় রেন্ডারিং কমাতে এবং পারফরম্যান্স অপটিমাইজ করতে সক্ষম হবেন।
Read more