Home » blog » Mastering React Redux: Core Concepts & State Management

Mastering React Redux: Core Concepts & State Management

React Redux দিয়ে অ্যাপ্লিকেশন ডেভেলপ করার সময় ডেভেলপাররা সবচেয়ে বেশি যে চ্যালেঞ্জের মুখে পড়েন, তা হলো State Management।

অ্যাপ্লিকেশন যখন ছোট থাকে, তখন useState বা Context API দিয়ে কাজ চালিয়ে নেওয়া যায়।

কিন্তু প্রজেক্ট যখন বড় হতে থাকে, ডাটা ফ্লো মেইনটেইন করা এবং “Props Drilling” এর ঝামেলা এড়ানো অনেক কঠিন হয়ে পড়ে। এখানেই সুপারহিরোর মতো এন্ট্রি নেয় React Redux!

react-redux-basics-foundation
React Redux Basic Foundation

আজকের এই ব্লগে আমরা React Redux-এর বেসিক এবং ফাউন্ডেশনাল কনসেপ্টগুলো খুব সহজ ভাষায় এক্সপ্লোর করব।

Mastering Redux: The Ultimate Foundation Guide

সহজ কথায়, Redux হলো জাভাস্ক্রিপ্ট অ্যাপ্লিকেশনের জন্য একটি Predictable State Container। আর React Redux হলো Redux-এর অফিশিয়াল UI Binding Library।

Redux একা যেকোনো ফ্রেমওয়ার্কের (যেমন Angular, Vue) সাথে কাজ করতে পারে।

কিন্তু React-এর কম্পোনেন্টগুলোর সাথে Redux-কে পারফেক্টলি কানেক্ট করতে এবং ডেটা সিঙ্ক রাখতে আমরা React Redux ব্যবহার করি।

এটি মূলত আপনার পুরো অ্যাপ্লিকেশনের সমস্ত ডেটা বা “State”-কে একটি গ্লোবাল জায়গায় স্টোর করে রাখে, যেখান থেকে যেকোনো কম্পোনেন্ট সহজেই ডেটা অ্যাক্সেস করতে পারে।

Core Concepts of Redux (The Foundation)

Redux-এর সম্পূর্ণ ইকোসিস্টেম মূলত ৩টি প্রধান পিলারের উপর দাঁড়িয়ে আছে। এই তিনটি কনসেপ্ট ক্লিয়ার থাকলে Redux আপনার কাছে একদম পানির মতো সহজ মনে হবে।

1. The Store (Single Source of Truth)

Store-কে আপনি আপনার অ্যাপ্লিকেশনের একটি গ্লোবাল ডেটাবেস বা “লকার” হিসেবে চিন্তা করতে পারেন। পুরো অ্যাপ্লিকেশনের সমস্ত state এই একটি মাত্র জায়গায় সেভ করা থাকে।

  • আপনার অ্যাপে একাধিক Store থাকতে পারবে না, একটাই গ্লোবাল Store থাকবে।
  • যেকোনো কম্পোনেন্ট সরাসরি এই Store থেকে তার প্রয়োজনীয় ডেটা টেনে নিতে পারে।

2. Actions (The Messengers)

Store-এ রাখা ডেটা আপনি চাইলেই সরাসরি পরিবর্তন করতে পারবেন না। ডেটা পরিবর্তন করার একমাত্র উপায় হলো একটি Action পাঠানো।

Action হলো মূলত একটি plain JavaScript object, যার মধ্যে দুটি জিনিস থাকে:

  • type: কী ধরনের ঘটনা ঘটছে তার একটি নাম (যেমন: "ADD_TO_CART")।
  • payload: যে নতুন ডেটাটি আপনি পাঠাতে চাচ্ছেন (অপশনাল)।

Action মূলত পোস্টম্যানের মতো কাজ করে, যে Store-কে গিয়ে খবর দেয়, “ভাই, এই নতুন ডেটা এসেছে, অ্যাপে কিছু একটা আপডেট করতে হবে!”

3. Reducers (The State Changers)

Action তো শুধু খবর নিয়ে যায়, কিন্তু ডেটা আপডেট করার আসল কাজটি করে Reducer।

Reducer হলো একটি Pure Function, যা দুটি আর্গুমেন্ট রিসিভ করে: বর্তমান State এবং পাঠানো Action।

এই Action-এর type চেক করে Reducer সিদ্ধান্ত নেয় যে সে কীভাবে বর্তমান State-কে মডিফাই করে একটি নতুন State রিটার্ন করবে।

মনে রাখবেন, Reducer কখনো সরাসরি আগের State-কে মিউটেট বা পরিবর্তন করে না, বরং আগেরটার উপর ভিত্তি করে সম্পূর্ণ নতুন একটি State তৈরি করে।

How React Redux Works Together (The Hooks)

আগে React-এর সাথে Redux কানেক্ট করতে connect() ফাংশন এবং HOC (Higher Order Components) ব্যবহার করা হতো, যা বেশ ঝামেলার ছিল। কিন্তু এখন React Redux Hooks-এর কারণে কাজগুলো অবিশ্বাস্য রকম সহজ হয়ে গেছে।

প্রধানত ৩টি জিনিস আমাদের সবচেয়ে বেশি কাজে লাগে:

Provider Component

পুরো অ্যাপ্লিকেশন যেন Store-এর ডেটা অ্যাক্সেস করতে পারে, সেজন্য অ্যাপের একদম রুটে (Root) বা শুরুতে <Provider> কম্পোনেন্ট দিয়ে পুরো অ্যাপটিকে র‍্যাপ (wrap) করে দিতে হয় এবং props হিসেবে Store-কে পাস করতে হয়।

useSelector (Reading State)

এটি হলো ডেটা রিড করার হুক।

Store-এ থাকা বিশাল ডেটাবেস থেকে আপনার নির্দিষ্ট কম্পোনেন্টে ঠিক যেটুকু ডেটা দরকার, useSelector দিয়ে আপনি ঠিক ততটুকুই সিলেক্ট করে নিয়ে আসতে পারবেন। Store-এ ওই ডেটা আপডেট হলে, আপনার কম্পোনেন্টও স্বয়ংক্রিয়ভাবে রি-রেন্ডার হবে।

useDispatch (Updating State)

কোনো বাটনে ক্লিক করলে বা ইউজারের কোনো ইন্টার‍্যাকশনের পর যদি আপনি Store-এর ডেটা আপডেট করতে চান, তখন useDispatch ব্যবহার করতে হয়। এই হুকটি মূলত Action-কে ট্রিগার করে Reducer-এর কাছে পাঠিয়ে দেয়।

Why Should You Use React Redux?

নতুন ডেভেলপারদের মনে প্রশ্ন আসতেই পারে, “Context API থাকতে খামোখা এতো কষ্ট করে Redux কেন শিখব?” এর সলিড কিছু কারণ আছে:

  1. Predictability: State কখন, কোথায় এবং কীভাবে পরিবর্তন হচ্ছে, তা Redux-এ খুব স্পেসিফিকভাবে ট্র্যাক করা যায়।
  2. Debugging is a Breeze: Redux DevTools এক্সটেনশনটি এক কথায় অসাধারণ! এর “Time Travel Debugging” ফিচারের মাধ্যমে আপনি আপনার অ্যাপের আগের যেকোনো State-এ ফিরে যেতে পারবেন এবং ঠিক কোন Action-এর কারণে বাগ (bug) তৈরি হয়েছে তা বের করতে পারবেন।
  3. Performance Optimization: React Redux ইন্টারনালি অনেক অপটিমাইজেশন করে রাখে। স্টোরের কোনো ডেটা চেঞ্জ হলে পুরো অ্যাপ রি-রেন্ডার হয় না, শুধুমাত্র যে কম্পোনেন্ট ওই ডেটার উপর নির্ভরশীল, সেটাই রি-রেন্ডার হয়।
  4. Scalability: বড় স্কেলের এন্টারপ্রাইজ লেভেল অ্যাপ্লিকেশনের জন্য Redux-এর কোনো বিকল্প নেই।

Step-by-Step Implementation of React Redux (with Code Examples)

থিওরি তো অনেক হলো, এবার চলুন দেখি প্র্যাকটিক্যালি কোডে React Redux কীভাবে কাজ করে।

বর্তমানে Redux-এর জটিলতা এবং বয়লারপ্লেট কোড (boilerplate code) কমানোর জন্য অফিশিয়ালি Redux Toolkit (RTK) ব্যবহার করার পরামর্শ দেওয়া হয়।

আমরা একটি সিম্পল Counter App-এর উদাহরণ দিয়ে পুরো ফ্লো-টি বুঝব, যেখানে একটি সংখ্যা বাড়ানো এবং কমানো যাবে।

Step 1: Installing Dependencies

শুরুতেই আমাদের প্রজেক্টে Redux Toolkit এবং React Redux ইনস্টল করে নিতে হবে। টার্মিনালে নিচের কমান্ডটি রান করুন:

Bash

npm install @reduxjs/toolkit react-redux

Step 2: Creating a Slice (Actions & Reducers combined)

Redux Toolkit-এ Action এবং Reducer-কে আলাদা আলাদা ফাইলে না লিখে, একসাথে একটি ফাইলে লেখা হয়, যাকে বলা হয় “Slice”। চলুন counterSlice.js নামে একটি ফাইল তৈরি করি।

JavaScript//
import { createSlice } from '@reduxjs/toolkit';

// 1. Initial State ডিক্লেয়ার করা
const initialState = {
  value: 0,
};

// 2. Slice তৈরি করা
export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment: (state) => {
      // Redux Toolkit ইন্টারনালি Immer.js ব্যবহার করে, 
      // তাই এখানে আমরা সরাসরি state মিউটেট করার মতো কোড লিখতে পারি
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      // Payload রিসিভ করে state আপডেট করা
      state.value += action.payload;
    },
  },
});

// আমাদের Action গুলোকে এক্সপোর্ট করে দিচ্ছি
export const { increment, decrement, incrementByAmount } = counterSlice.actions;

// Store-এর জন্য Reducer-কে এক্সপোর্ট করছি
export default counterSlice.reducer;

এখানে খেয়াল করুন, increment এবং decrement হলো আমাদের Reducer ফাংশন, এবং RTK স্বয়ংক্রিয়ভাবে এদের জন্য Action তৈরি করে দেয়।

Step 3: Configuring the Store

এবার আমাদের গ্লোবাল ডাটাবেস বা Store তৈরি করতে হবে। store.js নামে একটি ফাইল বানিয়ে নিচের কোডটি লিখুন:

JavaScript//
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';

export const store = configureStore({
  reducer: {
    // এখানে আমাদের সব Slice এর Reducer গুলো যুক্ত করতে হবে
    counter: counterReducer,
  },
});

Step 4: Wrapping the App with Provider

Store তো তৈরি হলো, কিন্তু আমাদের React অ্যাপ্লিকেশনকে তো জানাতে হবে যে এই Store-টি কোথায় আছে! এর জন্য main.jsx বা index.js ফাইলে গিয়ে পুরো অ্যাপটিকে <Provider> দিয়ে র‍্যাপ করে দিতে হবে।

JavaScript//
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import { store } from './store'; // আমাদের তৈরি করা store ইমপোর্ট করলাম

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

Step 5: Reading State and Dispatching Actions in Components

ফাউন্ডেশন রেডি! এবার আমাদের যেকোনো কম্পোনেন্ট থেকে Store-এর ডেটা পড়তে useSelector এবং ডেটা আপডেট করতে useDispatch হুক ব্যবহার করব। চলুন Counter.jsx কম্পোনেন্টটি দেখি:

JavaScript///
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './counterSlice';

const Counter = () => {
  // Store থেকে current count ভ্যালু টেনে আনছি (Reading State)
  const count = useSelector((state) => state.counter.value);
  
  // Action ট্রিগার করার জন্য dispatch ফাংশন কল করছি
  const dispatch = useDispatch();

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>Counter Value: {count}</h2>
      
      <button onClick={() => dispatch(increment())}>
        Increase (+)
      </button>
      
      <button onClick={() => dispatch(decrement())}>
        Decrease (-)
      </button>
      
      <button onClick={() => dispatch(incrementByAmount(5))}>
        Increase by 5
      </button>
    </div>
  );
};

export default Counter;

Summary of the Data Flow

উপরের কোডগুলো কীভাবে একসাথে কাজ করছে, তার একটি কুইক সামারি নিচে দেওয়া হলো:

  1. ইউজার যখন “Increase (+)” বাটনে ক্লিক করে, তখন dispatch(increment()) একটি Action ফায়ার করে।
  2. এই Action-টি সোজা চলে যায় Store-এর কাছে।
  3. Store তার ভেতরের Reducer-কে চেক করে দেখে যে, increment নামের অ্যাকশনের কাজ কী।
  4. Reducer তখন state.value-এর মান ১ বাড়িয়ে নতুন State তৈরি করে।
  5. সবশেষে, যে কম্পোনেন্ট useSelector দিয়ে ওই ডেটা রিড করছিল (যেমন আমাদের Counter কম্পোনেন্ট), সেটি স্বয়ংক্রিয়ভাবে আপডেট হওয়া ডেটা নিয়ে Re-render হয়ে যায়।

কোডসহ এই কনসেপ্টগুলো প্র্যাকটিস করলে React Redux আপনার কাছে একদম ম্যাজিকের মতো কাজ করবে!

Redux One-Way Data Flow Overview
Redux One-Way Data Flow Overview

Final Thoughts on State Management

প্রথম প্রথম Redux-এর ফ্লো (Action -> Reducer -> Store) বুঝতে একটু কঠিন মনে হতে পারে।

তবে এর বেসিক ফাউন্ডেশন একবার ধরতে পারলে, এটি আপনার ওয়েব ডেভেলপমেন্ট ক্যারিয়ারের অন্যতম সেরা স্কিল হয়ে উঠবে।

আর বর্তমানে Redux Toolkit (RTK) আসার পর থেকে Redux-এর বয়লারপ্লেট কোড (boilerplate code) অনেক কমে গেছে, যা ডেভেলপার এক্সপেরিয়েন্সকে আরও স্মুথ করেছে।

Redux প্র্যাকটিস শুরু করার জন্য ছোট একটি প্রজেক্ট (যেমন: To-Do App বা Shopping Cart) বানিয়ে ফেলুন। কনসেপ্টগুলো হাতে-কলমে ইমপ্লিমেন্ট করলেই পুরো বিষয়টা আপনার কাছে একদম ক্লিয়ার হয়ে যাবে!

হ্যাপি কোডিং! React এবং Redux রিলেটেড আরও কোনো টপিক নিয়ে বিস্তারিত জানতে চাইলে কমেন্টে জানাতে পারেন।

All Tech Update

Technology এর সকল আপডেট সবার আগে বিস্তারিত পড়ুন –

Scroll to Top