Redux একটি স্টেট ম্যানেজমেন্ট লাইব্রেরি যা মূলত JavaScript অ্যাপ্লিকেশনগুলির জন্য ব্যবহৃত হয়, বিশেষত React এর সাথে। এটি একটি নির্দিষ্ট প্যাটার্ন বা স্থিতি (state) পরিচালনা করার পদ্ধতি প্রদান করে। Redux-এর মূল উদ্দেশ্য হলো অ্যাপ্লিকেশনের স্টেট (যেমন ডেটা, UI স্টেট ইত্যাদি) পরিচালনা এবং শেয়ারিংকে সহজ করা। Redux-এর বেসিক কনসেপ্টগুলি একসাথে কাজ করে যাতে অ্যাপ্লিকেশনগুলি আরও স্ট্রাকচারড, স্কেলেবল এবং ডিবাগ করা সহজ হয়।
Redux-এর বেসিক কনসেপ্টগুলি মূলত তিনটি প্রধান উপাদানের উপর ভিত্তি করে গঠিত: স্টোর (Store), একশন (Action), এবং রিডিউসার (Reducer)। এছাড়া, এই ধারণাগুলির মাধ্যমে স্টেট পরিবর্তন এবং ডেটা ফ্লো নিয়ন্ত্রণ করা হয়। চলুন, Redux-এর বেসিক কনসেপ্টগুলির বিস্তারিত দেখি।
১. স্টোর (Store)
স্টোর হল Redux অ্যাপ্লিকেশনের কেন্দ্রীয় অংশ যেখানে সমস্ত স্টেট সংরক্ষিত থাকে। স্টোর অ্যাপ্লিকেশনের স্টেটের সমস্ত ডেটা ধারণ করে এবং এটি একমাত্র স্থান থেকে অ্যাক্সেস করা যায়।
- স্টোরের কাজ:
- অ্যাপ্লিকেশনের সমস্ত স্টেট স্টোরে রাখা হয়।
- স্টোর শুধুমাত্র পিউর ফাংশন (রিডিউসার) দ্বারা স্টেট পরিবর্তন করতে পারে।
- স্টোরের মাধ্যমে অ্যাপ্লিকেশনটি স্টেট পাঠাতে এবং তার উপর পরিবর্তন করতে পারে।
store.subscribe()ব্যবহার করে অ্যাপ্লিকেশনটি স্টোরের পরিবর্তন সম্পর্কে অবহিত হতে পারে।
২. একশন (Action)
একশন (Action) হল একটি সাধারণ জাভাস্ক্রিপ্ট অবজেক্ট, যা কোনো ঘটনা বা পরিবর্তন নির্দেশ করে। অ্যাপ্লিকেশনের স্টেট পরিবর্তন করতে হলে একটি অ্যাকশন পাঠাতে হয়। একশনটি সাধারণত দুটি অংশের সমন্বয়ে গঠিত: একটি type এবং প্রাসঙ্গিক তথ্য (payload)।
- একশনের কাজ:
- অ্যাকশন অ্যাপ্লিকেশনের স্টেট পরিবর্তন করার উদ্দেশ্যে রিডিউসারকে জানায়।
- একশনটি সাধারণত একটি অবজেক্ট আকারে থাকে, যার মধ্যে
typeএবং অতিরিক্ত ডেটা (যেমনpayload) থাকে।
উদাহরণ:
const addTodoAction = {
type: 'ADD_TODO',
payload: 'Learn Redux'
};
৩. রিডিউসার (Reducer)
রিডিউসার (Reducer) হল একটি ফাংশন যা স্টেট এবং অ্যাকশন গ্রহণ করে এবং একটি নতুন স্টেট রিটার্ন করে। রিডিউসার স্টেটের পুরানো কপি পরিবর্তন না করে একটি নতুন স্টেট কপি তৈরি করে। এটি একটি পিউর ফাংশন হিসেবে কাজ করে, যার মানে হল যে এটি পূর্বের স্টেট এবং অ্যাকশন দিয়ে নতুন স্টেট তৈরি করে, কিন্তু কখনোই সরাসরি স্টেট পরিবর্তন করে না।
- রিডিউসারের কাজ:
- এটি অ্যাকশন অনুযায়ী স্টেট পরিবর্তন করে।
- রিডিউসার স্টেটের পুরানো কপি বজায় রেখে নতুন স্টেট তৈরি করে।
উদাহরণ:
function todosReducer(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, action.payload];
default:
return state;
}
}
৪. ডিসপ্যাচ (Dispatch)
ডিসপ্যাচ (Dispatch) হল একশন পাঠানোর প্রক্রিয়া। অ্যাপ্লিকেশন যখন একটি একশন পাঠাতে চায়, তখন এটি dispatch() ফাংশন ব্যবহার করে। একবার ডিসপ্যাচ করার পর, সেই একশনটি রিডিউসারকে পৌঁছাবে এবং স্টেট পরিবর্তন করবে।
- ডিসপ্যাচের কাজ:
- এটি অ্যাকশনটি স্টোরে পাঠায়, যেখানে রিডিউসার তা গ্রহণ করে এবং স্টেট আপডেট করে।
উদাহরণ:
store.dispatch(addTodoAction);
Redux-এ ডেটা ফ্লো
Redux-এর ডেটা ফ্লো খুবই নির্দিষ্ট এবং একমুখী। এর মানে হল যে, স্টেট কেবল একমাত্র উপায়ে পরিবর্তিত হয়, তা হলো একশন দিয়ে। এবং স্টেট পরিবর্তন হওয়ার পর, নতুন স্টেট রিডিউসার মাধ্যমে স্টোরে সঞ্চিত হয়।
Redux-এর ডেটা ফ্লো নিম্নরূপ:
- অ্যাকশন: প্রথমে একটি অ্যাকশন ডিসপ্যাচ করা হয় (যেমন, ইউজার কোনো টুডু আইটেম যোগ করেছে)।
- রিডিউসার: একশনটি রিডিউসারকে পাঠানো হয়, যা পূর্ববর্তী স্টেট এবং অ্যাকশন দিয়ে নতুন স্টেট তৈরি করে।
- স্টোর: রিডিউসার স্টোরে নতুন স্টেট সংরক্ষণ করে।
- কম্পোনেন্ট: কম্পোনেন্টগুলোর মধ্যে নতুন স্টেট প্রতিফলিত হয়, এবং UI আপডেট হয়।
সারাংশ
Redux-এর বেসিক কনসেপ্টগুলি হল স্টোর (Store), একশন (Action), এবং রিডিউসার (Reducer)। এই তিনটি মৌলিক উপাদান একসাথে কাজ করে একটি অ্যাপ্লিকেশনের স্টেট ম্যানেজমেন্টকে সহজ এবং সুসংগঠিত করে। স্টোর সমস্ত স্টেট ধারণ করে, একশন স্টেট পরিবর্তনের উদ্দেশ্যে রিডিউসারকে জানায়, এবং রিডিউসার স্টেট পরিবর্তন করে নতুন স্টেট তৈরি করে। Redux-এর এই সুসংগঠিত কাঠামো অ্যাপ্লিকেশনটি স্কেলেবল, পূর্বানুমানযোগ্য এবং ডিবাগযোগ্য রাখে।
Redux Store হলো Redux এর কেন্দ্রীয় স্থান যেখানে অ্যাপ্লিকেশনের সমস্ত স্টেট (State) সংরক্ষিত থাকে। এটি Redux-এর একটি প্রধান উপাদান, যেহেতু স্টোরে থাকা স্টেটই অ্যাপ্লিকেশনটির বর্তমান অবস্থা নির্ধারণ করে। স্টোরের মাধ্যমে অ্যাপ্লিকেশনটি তার স্টেট অ্যাক্সেস করতে পারে এবং স্টেট পরিবর্তন করতে পারে। Redux স্টোরে অ্যাপ্লিকেশনের সমস্ত স্টেট একটি কেন্দ্রীভূত অবস্থানে রাখা হয়, যা ব্যবস্থাপনা এবং ডিবাগিংয়ের জন্য অত্যন্ত সুবিধাজনক।
Redux স্টোর কিভাবে কাজ করে, তা বোঝার জন্য এর বিভিন্ন ফিচার এবং প্রক্রিয়া নিয়ে আলোচনা করা প্রয়োজন।
Redux Store এর মৌলিক কাজ
- স্টেট ধারণ করা (State Management): স্টোর অ্যাপ্লিকেশনের সমস্ত স্টেট ধারণ করে। এটি একমাত্র স্থান যেখানে অ্যাপ্লিকেশনের স্টেট সঞ্চিত থাকে। স্টোরের মাধ্যমে স্টেট পরিবর্তন বা অ্যাক্সেস করা হয়।
- স্টেট রিডিং (Reading State): অ্যাপ্লিকেশনের যেকোনো কম্পোনেন্ট বা ফিচার স্টোর থেকে স্টেট পড়তে পারে। এইভাবে, স্টোরের স্টেটকে একাধিক কম্পোনেন্ট শেয়ার করতে পারে, ফলে স্টেটের সামঞ্জস্য বজায় থাকে।
- স্টেট আপডেট করা (Updating State): স্টোরের স্টেট সরাসরি পরিবর্তন করা যায় না। পরিবর্তনের জন্য, অ্যাপ্লিকেশনকে একটি অ্যাকশন (Action) ডিসপ্যাচ করতে হয়, যা রিডিউসার (Reducer) ব্যবহার করে স্টেটের একটি নতুন কপি তৈরি করে। স্টোর এই নতুন স্টেট রিটার্ন করে এবং সেই অনুযায়ী অ্যাপ্লিকেশনটি আপডেট হয়।
- স্টেট পরিবর্তনের সাবস্ক্রিপশন (Subscription): অ্যাপ্লিকেশন স্টোরের স্টেট পরিবর্তন সম্পর্কে অবহিত হতে পারে।
store.subscribe()ফাংশন ব্যবহার করে, কম্পোনেন্ট বা লজিক স্টোরের স্টেট পরিবর্তন হলে ট্রিগার হতে পারে।
Redux Store তৈরি এবং কিভাবে কাজ করে?
Redux স্টোর তৈরি করতে createStore ফাংশন ব্যবহার করা হয়। এই ফাংশনটি স্টোর তৈরি করার জন্য রিডিউসার এবং অন্যান্য প্রয়োজনীয় কনফিগারেশন নেয়। সাধারণত, একটি অ্যাপ্লিকেশন একাধিক রিডিউসার থাকতে পারে, সেক্ষেত্রে combineReducers ব্যবহার করা হয়।
স্টোর তৈরি করার উদাহরণ:
import { createStore } from 'redux';
// ১. রিডিউসার ফাংশন তৈরি
function rootReducer(state = { counter: 0 }, action) {
switch (action.type) {
case 'INCREMENT':
return { counter: state.counter + 1 };
case 'DECREMENT':
return { counter: state.counter - 1 };
default:
return state;
}
}
// ২. স্টোর তৈরি করা
const store = createStore(rootReducer);
// ৩. স্টোরে সাবস্ক্রাইব করা (স্টেট পরিবর্তন শোনার জন্য)
store.subscribe(() => {
console.log('State updated:', store.getState());
});
// ৪. স্টোরে একশন ডিসপ্যাচ করা
store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'DECREMENT' });
এখানে:
createStoreফাংশনটিrootReducerকে নেয় এবং একটি স্টোর তৈরি করে।store.subscribe()ব্যবহার করে, আমরা স্টোরের স্টেট পরিবর্তনের জন্য একটি হ্যান্ডলার সেট করেছি। যেকোনো পরিবর্তন হলে, এই হ্যান্ডলার ট্রিগার হবে।store.dispatch()ব্যবহার করে, আমরা স্টোরে একশন পাঠাচ্ছি, যার মাধ্যমে স্টেট পরিবর্তন হবে।
Redux Store-এর প্রধান ফিচার
- একক স্টোর (Single Store): Redux-এ শুধুমাত্র একটি স্টোর থাকে, যা অ্যাপ্লিকেশনের সমস্ত স্টেট ধারণ করে। এতে স্টেটের একাধিক কপি রাখার ঝামেলা কমে যায় এবং স্টেটের সঠিকতা বজায় থাকে।
- স্টেট অপরিবর্তনীয়তা (Immutable State): স্টোরের স্টেট কখনোই সরাসরি পরিবর্তিত হয় না। স্টেট পরিবর্তন করতে হলে, আপনাকে একটি নতুন কপি তৈরি করতে হবে। এটি স্টেটকে অপরিবর্তনীয় (immutable) রাখে।
- স্টেট সাবস্ক্রিপশন (State Subscription): যেকোনো কম্পোনেন্ট বা লজিক
store.subscribe()এর মাধ্যমে স্টোরের স্টেট পরিবর্তনের উপর নজর রাখতে পারে। যখনই স্টেট পরিবর্তিত হয়, তখন সাবস্ক্রাইব করা ফাংশনটি ট্রিগার হবে এবং সেই অনুযায়ী কম্পোনেন্ট বা লজিক আপডেট হবে। - স্টেট রিডিং (Reading State): অ্যাপ্লিকেশন স্টোর থেকে সরাসরি স্টেট পড়তে পারে। আপনি
store.getState()ব্যবহার করে স্টোরের বর্তমান স্টেট অ্যাক্সেস করতে পারেন। - একশন (Action) ডিসপ্যাচ (Dispatch): স্টোরে স্টেট পরিবর্তনের জন্য একশন ডিসপ্যাচ করতে হয়। একশনটি একটি অবজেক্ট, যা সাধারণত একটি
typeএবং প্রয়োজনীয় ডেটা ধারণ করে।
স্টোরের মাধ্যমে ডেটা ফ্লো
Redux-এ স্টোরের মাধ্যমে ডেটা ফ্লো একমুখী হয়। এটি নিশ্চিত করে যে, স্টেট কেবল একক জায়গা থেকে পরিবর্তিত হয় এবং প্রোগ্রামটির আচরণ সহজে পূর্বানুমানযোগ্য এবং ডিবাগযোগ্য হয়।
ডেটা ফ্লো:
- অ্যাকশন (Action): প্রথমে অ্যাপ্লিকেশন থেকে একটি একশন ডিসপ্যাচ করা হয় (যেমন,
INCREMENTবাADD_TODO)। - রিডিউসার (Reducer): রিডিউসার সেই একশনটি গ্রহণ করে এবং স্টেটের একটি নতুন কপি তৈরি করে।
- স্টোর (Store): নতুন স্টেট স্টোরে সঞ্চিত হয়।
- কম্পোনেন্ট: কম্পোনেন্ট বা অন্যান্য অংশ স্টোরের নতুন স্টেট রিটার্ন করে এবং UI আপডেট হয়।
সারাংশ
Redux স্টোর হলো অ্যাপ্লিকেশনের স্টেট ধারণ করার স্থান। এটি স্টেটের একক কপি রাখে এবং স্টেট পরিবর্তন করার জন্য একশন ডিসপ্যাচ করতে হয়। স্টোরে থাকা স্টেট কখনো সরাসরি পরিবর্তিত হয় না, বরং রিডিউসার ফাংশনের মাধ্যমে নতুন স্টেট তৈরি হয়। Redux স্টোর একমুখী ডেটা ফ্লো এবং অপরিবর্তনীয় স্টেট বজায় রাখে, যা অ্যাপ্লিকেশনের স্টেট ম্যানেজমেন্টকে সহজ, পূর্বানুমানযোগ্য এবং ডিবাগযোগ্য করে তোলে।
Actions Redux-এ এমন অবজেক্ট যা স্টেট পরিবর্তনের ইচ্ছা বা প্রয়োজনীয়তা জানাতে ব্যবহৃত হয়। একশনগুলি স্টেট পরিবর্তন করার উদ্দেশ্যে Reducers-কে সংকেত দেয়। Redux স্টেট ম্যানেজমেন্ট প্যাটার্নে, অ্যাকশন হল একমাত্র মাধ্যম যা স্টেট পরিবর্তন ঘটায়। তবে, একশনগুলি সরাসরি স্টেট পরিবর্তন করে না; বরং তারা রিডিউসার ফাংশনকে নির্দেশ দেয় কিভাবে স্টেট পরিবর্তন করতে হবে।
Action কী?
Action হল একটি সাধারণ JavaScript অবজেক্ট, যেটির মধ্যে কমপক্ষে একটি type ফিল্ড থাকে, যা সেই একশনের উদ্দেশ্য বা কার্যকলাপ নির্ধারণ করে। একশনটি কখনোই নিজে স্টেট পরিবর্তন করে না, বরং এটি রিডিউসারকে জানায় কিভাবে স্টেট পরিবর্তন হবে।
একটি একশন সাধারণত দুটি অংশে বিভক্ত থাকে:
- Type: একশনটির ধরন বা কার্যকলাপ। এটি একটি স্ট্রিং হিসেবে থাকে এবং রিডিউসারের মধ্যে একটি
switchস্টেটমেন্টে ব্যবহৃত হয়। - Payload (Optional): এটি ঐকিকভাবে কিছু ডেটা, যা একশনটি সম্পাদন করতে প্রয়োজন। উদাহরণস্বরূপ, যদি একশনটি কোনো নতুন টুডু আইটেম যোগ করার জন্য হয়, তবে সেই টুডু আইটেমের তথ্য
payloadহিসেবে থাকবে।
Action এর উদাহরণ
const addTodoAction = {
type: 'ADD_TODO',
payload: {
id: 1,
text: 'Learn Redux'
}
};
এখানে:
- type:
'ADD_TODO'- এটি একশনের ধরন, যা রিডিউসারকে জানায় যে, টুডু আইটেম যোগ করতে হবে। - payload:
{ id: 1, text: 'Learn Redux' }- এটি সেই তথ্য, যা টুডু আইটেমের জন্য প্রয়োজনীয়।
Action এর কাজ
Redux অ্যাপ্লিকেশনে স্টেট পরিবর্তন করতে হলে প্রথমে একটি একশন ডিসপ্যাচ করা হয়। একশনটি সাধারণত অ্যাপ্লিকেশনের যেকোনো জায়গা থেকে ডিসপ্যাচ করা হতে পারে, যেমন UI ইন্টারঅ্যাকশন, API কল বা কোনো অ্যাসিনক্রোনাস কাজের মাধ্যমে।
- একশন ডিসপ্যাচ করা: অ্যাপ্লিকেশনের যে কোনও অংশ থেকে
store.dispatch(action)ফাংশন ব্যবহার করে একশন পাঠানো হয়। একশন পাঠানোর মাধ্যমে, স্টোর রিডিউসারকে জানায় যে, স্টেট পরিবর্তন করতে হবে। - রিডিউসার: একশনটি রিডিউসার ফাংশনে পৌঁছায়। রিডিউসার বর্তমান স্টেট এবং অ্যাকশন গ্রহণ করে একটি নতুন স্টেট তৈরি করে।
- স্টোর: স্টোর নতুন স্টেট ধারণ করে এবং যেকোনো কম্পোনেন্ট বা অংশকে স্টেটের পরিবর্তন সম্পর্কে জানায়।
Action Creator কী?
Action Creator হল একটি ফাংশন যা একটি একশন অবজেক্ট তৈরি করে। এটি কোডের পুনঃব্যবহারযোগ্যতা এবং কোডের পরিষ্কারতা বাড়ায়। সাধারণত, একশনগুলি সরাসরি স্টোরে ডিসপ্যাচ করার পরিবর্তে, action creators দিয়ে ডিসপ্যাচ করা হয়।
Action Creator এর উদাহরণ:
// Action creator
function addTodo(text) {
return {
type: 'ADD_TODO',
payload: {
id: Date.now(),
text: text
}
};
}
// Dispatching action using action creator
store.dispatch(addTodo('Learn Redux'));
এখানে, addTodo একটি অ্যাকশন ক্রিয়েটর যা একটি নতুন টুডু আইটেমের জন্য একটি অ্যাকশন অবজেক্ট তৈরি করে। তারপর সেই অ্যাকশন store.dispatch() দিয়ে স্টোরে পাঠানো হয়।
অ্যাকশন (Action) এর Types
Redux অ্যাপ্লিকেশনগুলিতে বিভিন্ন ধরনের একশন ব্যবহৃত হতে পারে। সাধারণত, একশনগুলিকে একটি সেন্ট্রালাইজড স্থানে (যেমন, একটি actionTypes.js ফাইল) ডিফাইন করা হয়, যা কনস্ট্যান্ট হিসেবে ব্যবহৃত হয়। এর মাধ্যমে টেক্সট স্ট্রিংগুলির ভুল এড়ানো যায় এবং কোডকে আরও মেইনটেনেবল করা যায়।
উদাহরণ:
// actionTypes.js
export const ADD_TODO = 'ADD_TODO';
export const REMOVE_TODO = 'REMOVE_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO';
এবং তারপর, এই একশন টাইপগুলি অ্যাকশন অবজেক্টে ব্যবহার করা হয়:
import { ADD_TODO } from './actionTypes';
const addTodo = (text) => ({
type: ADD_TODO,
payload: { text }
});
এভাবে একশন টাইপগুলো একক স্থানে সংরক্ষণ করলে কোডের নিরাপত্তা এবং রিডেবিলিটি বাড়ে।
অ্যাকশন এবং রিডিউসার মধ্যে সম্পর্ক
Redux-এ একশন এবং রিডিউসারের মধ্যে সম্পর্ক অত্যন্ত গুরুত্বপূর্ণ। একশন শুধুমাত্র স্টেট পরিবর্তনের সংকেত দেয়, কিন্তু রিডিউসার সেই একশনের ভিত্তিতে স্টেট আপডেট করে।
একশন এবং রিডিউসারের উদাহরণ:
// Action
const addTodoAction = {
type: 'ADD_TODO',
payload: { id: 1, text: 'Learn Redux' }
};
// Reducer
function todosReducer(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, action.payload];
default:
return state;
}
}
// Dispatching action
store.dispatch(addTodoAction);
এখানে:
- একশন (Action) স্টোরকে জানায় যে একটি নতুন টুডু আইটেম যোগ করতে হবে।
- রিডিউসার (Reducer) সেই একশন গ্রহণ করে নতুন স্টেট তৈরি করে।
অ্যাসিনক্রোনাস অ্যাকশন (Asynchronous Actions)
Redux তে সাধারণত সিনক্রোনাস অ্যাকশন ব্যবহৃত হয়, কিন্তু কখনও কখনও অ্যাসিনক্রোনাস কাজ করতে হয় (যেমন API কল)। Redux এর সাধারণ অ্যাকশনগুলি সিনক্রোনাস হলেও, Redux Thunk বা Redux Saga এর মতো মiddleware ব্যবহার করে অ্যাসিনক্রোনাস একশন হ্যান্ডেল করা যায়।
Redux Thunk এর উদাহরণ:
function fetchData() {
return function(dispatch) {
dispatch({ type: 'FETCH_DATA_START' });
fetch('/api/data')
.then(response => response.json())
.then(data => {
dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
})
.catch(error => {
dispatch({ type: 'FETCH_DATA_FAILURE', payload: error });
});
};
}
এখানে, fetchData একটি অ্যাসিনক্রোনাস একশন ক্রিয়েটর, যা প্রথমে একটি START একশন ডিসপ্যাচ করে, তারপর API থেকে ডেটা ফেচ করে এবং সফল হলে একটি SUCCESS একশন ডিসপ্যাচ করে।
সারাংশ
Actions Redux-এর একটি গুরুত্বপূর্ণ অংশ, যা স্টেট পরিবর্তনের সংকেত প্রদান করে। এটি একটি সাধারণ জাভাস্ক্রিপ্ট অবজেক্ট, যেটির মধ্যে type এবং কখনো payload থাকে। Action Creator হল একটি ফাংশন যা এই অ্যাকশন অবজেক্ট তৈরি করে। অ্যাকশন কখনোই সরাসরি স্টেট পরিবর্তন করে না, বরং এটি রিডিউসারকে নির্দেশ দেয় কিভাবে স্টেট পরিবর্তন করতে হবে। Redux-এ অ্যাসিনক্রোনাস কাজের জন্য Redux Thunk বা Redux Saga এর মতো middleware ব্যবহৃত হতে পারে।
Reducers Redux-এর একটি অত্যন্ত গুরুত্বপূর্ণ অংশ, যা স্টেট পরিবর্তনের জন্য ব্যবহৃত হয়। এটি একটি পিউর ফাংশন যা অ্যাপ্লিকেশনের বর্তমান স্টেট এবং একটি অ্যাকশন অবজেক্ট গ্রহণ করে, এবং সেই অ্যাকশনটির উপর ভিত্তি করে একটি নতুন স্টেট রিটার্ন করে। রিডিউসার কখনোই সরাসরি স্টেট পরিবর্তন করে না, বরং এটি পুরানো স্টেট থেকে একটি নতুন স্টেট কপি তৈরি করে। এই বৈশিষ্ট্যটি স্টেটের অপরিবর্তনীয়তা (Immutability) নিশ্চিত করে।
Reducers-এর মূল উদ্দেশ্য হলো অ্যাপ্লিকেশনটির স্টেটকে পূর্বানুমানযোগ্য এবং স্কেলেবল রাখা, যাতে অ্যাপ্লিকেশনটি সহজে ডিবাগ করা যায় এবং বিভিন্ন অংশ একে অপরের সাথে সহজে ইন্টারঅ্যাক্ট করতে পারে।
Reducer কী?
Redux-এ Reducer হল একটি পিউর ফাংশন, যা বর্তমান স্টেট এবং অ্যাকশন অবজেক্ট নিয়ে একটি নতুন স্টেট রিটার্ন করে। এটি স্টেট পরিবর্তন করার একমাত্র উপায়। রিডিউসার কোন একশন ডেটা প্রক্রিয়া করে না, বরং একশনটি কি করতে চায় তার ভিত্তিতে নতুন স্টেট তৈরি করে।
Reducer এর কাঠামো:
একটি রিডিউসার সাধারণত তিনটি অংশ নিয়ে তৈরি হয়:
- প্রথম প্যারামিটার: বর্তমান স্টেট (State)। যদি কোনও স্টেট পূর্বে নেই, তবে একটি ডিফল্ট স্টেট প্রদান করা হয়।
- দ্বিতীয় প্যারামিটার: অ্যাকশন (Action) - যা স্টেট পরিবর্তন করতে নির্দেশনা দেয়।
- রিটার্ন স্টেট: একটি নতুন স্টেট, যা পুরোনো স্টেটের উপর ভিত্তি করে তৈরি হয়।
Reducer এর উদাহরণ
ধরা যাক, আমাদের একটি টুডু লিস্ট অ্যাপ্লিকেশন রয়েছে যেখানে টুডু আইটেম যোগ করা এবং মুছে ফেলার কার্যক্রম রয়েছে। এখানে রিডিউসারের একটি সাধারণ উদাহরণ দেওয়া হলো:
// ডিফল্ট স্টেট
const initialState = {
todos: []
};
// রিডিউসার ফাংশন
function todosReducer(state = initialState, action) {
switch (action.type) {
case 'ADD_TODO':
// নতুন টুডু আইটেম যোগ করা
return {
...state,
todos: [...state.todos, action.payload]
};
case 'REMOVE_TODO':
// টুডু আইটেম মুছে ফেলা
return {
...state,
todos: state.todos.filter(todo => todo.id !== action.payload.id)
};
default:
return state;
}
}
এখানে:
- initialState: এটি ডিফল্ট স্টেট, যা রিডিউসার প্রথমবার চালানোর সময় ব্যবহৃত হয়।
- action.type: এটি অ্যাকশনের ধরন নির্দেশ করে, যেমন
'ADD_TODO'বা'REMOVE_TODO'। - নতুন স্টেট: রিডিউসার পুরানো স্টেটের উপর ভিত্তি করে নতুন স্টেট তৈরি করে এবং সেটি রিটার্ন করে।
Reducer-এর ভূমিকা
- স্টেট পরিবর্তন: রিডিউসারের প্রধান কাজ হলো অ্যাপ্লিকেশনটির স্টেট পরিবর্তন করা। এটি শুধুমাত্র একটি ফাংশন, যা পুরানো স্টেট এবং অ্যাকশন এর মাধ্যমে নতুন স্টেট তৈরি করে।
- অপরিবর্তনীয়তা বজায় রাখা (Immutability): Redux-এ স্টেট কখনোই সরাসরি পরিবর্তন করা হয় না। রিডিউসার স্টেটের কপি তৈরি করে এবং সেই কপি পরিবর্তন করে নতুন স্টেট রিটার্ন করে। এটি স্টেটের অপরিবর্তনীয়তা বজায় রাখে।
- একটি নির্দিষ্ট স্টেটের জন্য দায়িত্বশীল: একটি রিডিউসার সাধারণত একটি নির্দিষ্ট স্টেট স্লাইস (slice) এর জন্য দায়ী থাকে। উদাহরণস্বরূপ, একটি টুডু অ্যাপ্লিকেশনে টুডু আইটেমের স্টেট পরিবর্তন করার জন্য একটি আলাদা রিডিউসার থাকতে পারে।
- স্টেটের পূর্বানুমানযোগ্যতা: যেহেতু রিডিউসার পিউর ফাংশন, এটি একটি নির্দিষ্ট ইনপুট (বর্তমান স্টেট + অ্যাকশন) দিয়ে একটি নির্দিষ্ট আউটপুট (নতুন স্টেট) রিটার্ন করে। এটি অ্যাপ্লিকেশনটির আচরণ পূর্বানুমানযোগ্য করে তোলে।
Reducer কীভাবে কাজ করে?
Redux অ্যাপ্লিকেশনে, রিডিউসারটি সাধারণত স্টোরের সাথে যুক্ত থাকে। যখন একটি অ্যাকশন ডিসপ্যাচ করা হয়, স্টোর সেই একশনটি রিডিউসারে পাঠায়, এবং রিডিউসার সেই অ্যাকশনটির উপর ভিত্তি করে নতুন স্টেট তৈরি করে। তারপর, স্টোর সেই নতুন স্টেট আপডেট করে এবং কম্পোনেন্টগুলোকে অবহিত করে, যাতে UI আপডেট করা যায়।
স্টোরের সাথে রিডিউসারের কাজ:
- একশন ডিসপ্যাচ করা (Dispatching Action): প্রথমে একটি অ্যাকশন তৈরি করা হয় এবং তা ডিসপ্যাচ করা হয় (যেমন, ইউজার একটি টুডু আইটেম যোগ করেছে)।
- রিডিউসারে পাঠানো: একশনটি রিডিউসারে পৌঁছায়, যেখানে এটি অ্যাকশন টাইপের উপর ভিত্তি করে স্টেট পরিবর্তন করে।
- নতুন স্টেট তৈরি: রিডিউসার একটি নতুন স্টেট কপি তৈরি করে এবং সেটি রিটার্ন করে।
- স্টোরে আপডেট: স্টোর নতুন স্টেট গ্রহণ করে এবং তার উপর ভিত্তি করে অ্যাপ্লিকেশনের UI আপডেট হয়।
Redux-এ একাধিক Reducer
অ্যাপ্লিকেশনগুলিতে সাধারণত একাধিক রিডিউসার থাকে, কারণ স্টেটের বিভিন্ন স্লাইস (যেমন, টুডু, ইউজার প্রোফাইল ইত্যাদি) আলাদা আলাদা রিডিউসার দ্বারা পরিচালিত হতে পারে। Redux এ একাধিক রিডিউসার ব্যবহারের জন্য combineReducers ফাংশন ব্যবহার করা হয়।
একাধিক রিডিউসার এবং combineReducers:
import { combineReducers } from 'redux';
// টুডু রিডিউসার
function todosReducer(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, action.payload];
default:
return state;
}
}
// ইউজার রিডিউসার
function userReducer(state = { name: '' }, action) {
switch (action.type) {
case 'SET_USER':
return { ...state, name: action.payload };
default:
return state;
}
}
// রিডিউসার গুলি কম্বাইন করা
const rootReducer = combineReducers({
todos: todosReducer,
user: userReducer
});
export default rootReducer;
এখানে:
combineReducersব্যবহার করে আমরাtodosReducerএবংuserReducerকে একত্রিত করেছি, যাতে একটি রুট রিডিউসার (rootReducer) তৈরি হয়।
Reducer এর কিছু গুরুত্বপূর্ণ বিষয়
- পিউর ফাংশন: রিডিউসার একটি পিউর ফাংশন হতে হবে, যা একই ইনপুটে সবসময় একই আউটপুট দেয় এবং কোন পাশের প্রভাব (side effect) সৃষ্টি করে না।
- অপরিবর্তনীয়তা: স্টেট পরিবর্তন করার সময়, রিডিউসারকে অবশ্যই নতুন স্টেট কপি তৈরি করতে হবে। সরাসরি স্টেট পরিবর্তন করা যাবে না।
- ডিফল্ট স্টেট: রিডিউসারে একটি ডিফল্ট স্টেট দেওয়া উচিত, যা প্রথমবার রিডিউসার কল হওয়ার সময় ব্যবহৃত হবে।
সারাংশ
Reducers হল Redux-এ স্টেট পরিবর্তনের জন্য ব্যবহৃত পিউর ফাংশন। রিডিউসার বর্তমান স্টেট এবং একশন গ্রহণ করে একটি নতুন স্টেট তৈরি করে এবং সেই নতুন স্টেট রিটার্ন করে। এটি অপরিবর্তনীয়তা বজায় রেখে স্টেট পরিবর্তন করে এবং স্টেট পরিবর্তনের পূর্বানুমানযোগ্যতা নিশ্চিত করে। একাধিক রিডিউসার ব্যবহারের জন্য combineReducers ফাংশন ব্যবহার করা হয়, যা স্টেটের বিভিন্ন স্লাইস পরিচালনায় সহায়ক।
Redux-এ ডেটা ফ্লো একটি একমুখী প্রক্রিয়া। এর মানে হল যে, ডেটা অ্যাপ্লিকেশনের মধ্যে কেবল এক ধরনের দিক দিয়ে প্রবাহিত হয় এবং কোনো অপ্রত্যাশিত পরিবর্তন বা ডেটা ম্যানিপুলেশন হয় না। এটি অ্যাপ্লিকেশনের স্টেট ম্যানেজমেন্টকে সহজ, পূর্বানুমানযোগ্য এবং ডিবাগযোগ্য করে তোলে। Redux-এ ডেটা ফ্লো তিনটি প্রধান উপাদান থেকে গঠিত: Actions, Reducers, এবং Store। এই উপাদানগুলি একসাথে কাজ করে, অ্যাপ্লিকেশনের স্টেট পরিবর্তন এবং প্রবাহ পরিচালনা করতে।
Redux Data Flow এর প্রধান ধাপ
Redux-এ ডেটা ফ্লো একটি নির্দিষ্ট সিকোয়েন্সে চলে, যা সুনির্দিষ্টভাবে ডেটা পরিবর্তন এবং স্টেট আপডেট করে। এর ধাপগুলো হলো:
১. Action (অ্যাকশন)
Redux-এ Action হল একটি প্লেইন অবজেক্ট যা একটি নির্দিষ্ট type ধারণ করে এবং প্রায়ই অতিরিক্ত ডেটা (payload) থাকে, যা স্টেট পরিবর্তন করার জন্য প্রয়োজনীয়। অ্যাকশন কেবল রিডিউসারকে জানায় যে কী পরিবর্তন করতে হবে, কিন্তু এটি নিজে স্টেট পরিবর্তন করে না।
Action Example:
const addTodoAction = {
type: 'ADD_TODO',
payload: {
id: 1,
text: 'Learn Redux'
}
};
এই অ্যাকশনটি ADD_TODO একশন টাইপ ধারণ করে এবং একটি নতুন টুডু আইটেম যোগ করার জন্য প্রয়োজনীয় তথ্য payload হিসাবে পাঠাচ্ছে।
২. Dispatch (ডিসপ্যাচ)
অ্যাকশনটি স্টোরে পাঠাতে dispatch ফাংশন ব্যবহার করা হয়। এটি অ্যাপ্লিকেশন থেকে অ্যাকশন স্টোরে পাঠানোর প্রক্রিয়া। একশন ডিসপ্যাচ করার মাধ্যমে, স্টোর রিডিউসারকে জানায় যে স্টেট পরিবর্তন করতে হবে।
Dispatch Example:
store.dispatch(addTodoAction);
এখানে dispatch() ফাংশন অ্যাকশনটি স্টোরে পাঠাচ্ছে, যা স্টোরে রিডিউসারকে ট্রিগার করবে।
৩. Reducer (রিডিউসার)
Reducer হল একটি ফাংশন যা একটি অ্যাকশন গ্রহণ করে এবং স্টেটের একটি নতুন কপি তৈরি করে। রিডিউসার কখনও সরাসরি স্টেট পরিবর্তন করে না, বরং এটি পূর্ববর্তী স্টেট এবং অ্যাকশন ব্যবহার করে একটি নতুন স্টেট রিটার্ন করে।
Reducer Example:
function todosReducer(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return [...state, action.payload];
default:
return state;
}
}
এখানে todosReducer স্টেটের একটি নতুন কপি তৈরি করে যখন একটি ADD_TODO অ্যাকশন আসে। স্টেটের পুরানো কপি অপরিবর্তিত থাকে, এবং একটি নতুন কপি তৈরি হয় যাতে নতুন টুডু আইটেম যুক্ত করা হয়।
৪. Store (স্টোর)
Store হল Redux-এ স্টেট ধারণ করার স্থান। এটি সমস্ত অ্যাপ্লিকেশনের স্টেট একক স্থানে সংরক্ষণ করে এবং রিডিউসার ব্যবহার করে সেই স্টেট আপডেট করে। স্টোর অ্যাকশন ও রিডিউসারের মাধ্যমে স্টেট পরিবর্তন করার জন্য একমাত্র জায়গা।
Store Example:
const store = createStore(todosReducer);
এখানে, createStore ফাংশনটি রিডিউসার todosReducer কে নিয়ে স্টোর তৈরি করে।
৫. View (ভিউ)
Redux-এ স্টোরের স্টেট পরিবর্তিত হলে, স্টেটের নতুন কপি থেকে UI (ভিউ) আপডেট করা হয়। UI রেন্ডার করার জন্য সাধারণত React বা অন্য কোনো লাইব্রেরি ব্যবহার করা হয়, যা স্টোরের স্টেট পরিবর্তনগুলোর প্রতি সাবস্ক্রাইব করে এবং সেই অনুযায়ী কম্পোনেন্ট রেন্ডার করে।
Redux Data Flow এর প্রক্রিয়া
Redux-এ ডেটা ফ্লো নিচের মতো একদম সোজা ও একমুখী:
- User Interaction / Event: ইউজার কোনো ইন্টারঅ্যাকশন বা ইভেন্ট ঘটায় (যেমন, টুডু আইটেম যোগ করা, বাটনে ক্লিক করা)।
- Action Dispatch: ইভেন্ট বা ইউজার ইন্টারঅ্যাকশনটি একটি অ্যাকশন তৈরি করে এবং সেই অ্যাকশনটি
store.dispatch()এর মাধ্যমে স্টোরে পাঠানো হয়। - Reducer: স্টোর অ্যাকশনটি গ্রহণ করে রিডিউসারে পাঠায়। রিডিউসার অ্যাকশন অনুযায়ী স্টেট পরিবর্তন করে একটি নতুন স্টেট রিটার্ন করে।
- State Update: নতুন স্টেটটি স্টোরে সঞ্চিত হয় এবং UI (ভিউ) রেন্ডার হয় নতুন স্টেটের সাথে।
- View Update: কম্পোনেন্টগুলি নতুন স্টেটের ভিত্তিতে UI আপডেট করে।
Redux Data Flow এর Diagram
User Event → Action → Dispatch → Reducer → Store → View Update
এটি Redux-এ ডেটা ফ্লোর সাধারণ প্রক্রিয়া, যা একমুখী ডেটা প্রবাহ নিশ্চিত করে এবং অ্যাপ্লিকেশনের স্টেট পরিবর্তনকে পূর্বানুমানযোগ্য এবং সহজে ডিবাগযোগ্য করে তোলে।
সারাংশ
Redux-এ ডেটা ফ্লো একটি একমুখী প্রক্রিয়া, যেখানে অ্যাকশন স্টোরে পাঠানো হয়, রিডিউসার সেই অ্যাকশন অনুযায়ী স্টেট পরিবর্তন করে, এবং নতুন স্টেটটি স্টোরে সঞ্চিত হয়। এটি UI (ভিউ) আপডেটের মাধ্যমে ব্যবহারকারীর কাছে পরিবর্তন প্রতিফলিত করে। Redux এর এই ডেটা ফ্লো অ্যাপ্লিকেশনটি সহজ, পূর্বানুমানযোগ্য, এবং ডিবাগযোগ্য রাখতে সাহায্য করে।
Read more