React+Redux (রিয়েক্ট+ রিডাক্স) Part-2

Jahangir Alam
20 min readDec 7, 2020

Full react series is from udemy course Modern React with Redux [2019 Update] by Stephen grider

Content

  • 11. Let’s Test your React Mastery!
  • 12. Redux
  • 13. Integrating React with Redux

11. Let’s Test your React Mastery!

youtube api key তৈরির জন্য আমাদের নিচের এই লিঙ্কে যেতে হবে ।

এই লিঙ্কে যেয়ে signup/signin করতে হবে এরপর একটি প্রজেক্ট তৈরি করতে হবে ।

project তৈরি করার জন্য উপরের দিকে Select a project ড্রপ ডাউনের মতো বাটন আছে সেখানে ক্লিক করলে পাশের চিত্রের মতো একটি মডাল ওপেন হবে সেখানে ডান পাশে New Project বাটনে ক্লিক করতে হবে ।

এরপর প্রজেক্টের একটি নাম দিয়ে CREATE বাটনে ক্লিক করতে হবে এরপর enable করতে হবে । এরজন্ন Video Browser এ ক্লিক করতে হবে ।

এরপর মডাল এ Video Browser এ ক্লিক করলে enable হয়ে যাবে । এরপর credentials এ ক্লিক করতে হবে ।

এখানে সার্চ বারে youtube টাইপ করলে ৪ ধরনের API আসবে সেখানে থেকে YouTube Data API v3 তে ক্লিক করতে হবে ।

ENABLE এ ক্লিক করে এরপর ডান পাশের চিত্রের মতো Credential এ ক্লিক করে key জেনারেট করতে হবে ।

1, 2, 3

1 no চিত্রে API key তে ক্লিক করে কী জেনারেট করতে হবে । এরপর সেই key টা কপি করে src এর আন্ডারে apis নামে একটি ডিরেক্টরি তৈরি করে সেখানে youtube.js নামে একটি ফাইল তৈরি করবো সেখানে একটি ভেরিয়েবলে এই key টা স্টোর করবো ।

const KEY = '<secret key>'

basically আমরা রিকোয়েস্ট করবো নেটওয়ার্ক রিকোয়েস্ট । এই ajax রিকোয়েস্ট টা আমরা axios এর

মাধ্যমে করবো । সেটা youtube থেকে Array of object নিয়ে আসবে এর অর্থ হচ্ছে একটি array এর মধ্যে কয়েকটা youtube video র অবজেক্ট থাকবে । অবজেক্ট এসে পরলে তারপর সেটাকে আমরা আমাদের প্রজেক্টে প্রয়োজনমত ব্যাবহার করতে পারবো ।

Searching for videos

এই লিঙ্কে থেকে আমরা কিভাবে রিকোয়েস্ট করবো সে বেপারে সকল ধরনের ইনফরমেশন দেওয়া আছে যেমন কিভাবে কোয়েরি লিখবো কোন লিঙ্কে রিকোয়েস্ট করবো সেধরনের ইনফরমেশন ।

এখন প্রথমে axios মডিউল ইন্সটল করি ।

npm i axios

অথবা নিচের এই কমান্ডের

npm install --save axios

এখানে part এ snippet দিয়েছে । এর পরিবর্তে যে কোনও নাম দিতে পারি । রিকোয়েস্ট করলে এই নামের আন্ডারেই বিভিন্ন ইনফরমেশন আসবে ।

আর baseURL এ শেষে search দিতে হয় কিন্তু আমরা এখানে দেই নাই কারণ যখন endpoint তৈরি করবো তখন এই /search দিয়েই endpoint তৈরি করবো ।

Putting it all together

App.js file

ইউজার ইনপুট দিয়ে ইন্টার দেওয়ার পর সেই ভেলুটা ধরার জন্য এখানে <searchBar> কম্পোনেন্টে onTermSubmit() মেথডের রেফারেন্স পাস করে দিবো কারণ যখন SearchBar.js ফাইলে এই মেথডটি props এর মাধ্যমে কল করবো তখন এটি কল হবে ।

SearchBar.js file

onFormSubmit = event => {
event.preventDefault();
this.props.onFormSubmit(this.state.term)
};

এখানে props এর মাধ্যমে onFormSubmit এ state এর ভেলু আপডেট করে দিয়েছি সাথে সাথে এই মেথড টি অটোম্যাটিক কল হবে ।

এখানে শুধু কনসল লগ করলে এই ইনপুটের আউটপুট দেখা যাবে ।

আর কোন ভেলু দিয়ে সাবমিট দিলে youtube থেকে ডাটা আসবে সেটা দেখা যাবে ctrl+shift+i প্রেস করলে inspector ওপেন হবে সেখানে network ট্যাবে ক্লিক করার পর XHR এ ক্লিক করলে সেখানে এই লিঙ্ক ওপেন করলে preview ট্যাবে দেখা যাবে ডাটাগুলো । এখানে থেকে প্রয়োজন মতো এই ডাটাগুলো ব্যাবহার করতে পারবো ।

Updating state with fetched data

youtube এ api রিকোয়েস্ট করার পর যে response আসে সেখানে সকল ডাটাই আমাদের কাজে লাগে না শুধু response.data.items এর আন্ডারে ভিডিওর ইনফরমেশন গুলো আসে । এটাই আমরা জাস্ট কনসল লগ করেছি ।

app এর আন্ডারে ৩ টা কম্পোনেন্ট থাকবে ।

SearchBar থেকে সার্চ keyword টি নিয়ে আসবো App কম্পোনেন্টে এরপর app কম্পোনেন্ট থেকে network রিকোয়েস্ট করবো youtube api এ । এখান থেকে যে ডাটা আসবে সেই ডাটাকে আবার পাস করে দিবো VideoList কম্পোনেন্টে ।

Passing state as props

এখন <VideoList এর ভেতর videos গুলো props আকারে পাস করে দিবো child component এ ।

app.js

render(){
return (
<div className="ui container" >
<SearchBar onFormSubmit={ this.onTermSubmit } />
<VideoList videos={this.state.videos} />
</div>
);
}

এখন components ডিরেক্টরির আন্ডারে VideoList.js নামে একটি ফাইল তৈরি করি । এই ফাইলে নিচের কোডগুলো লিখি ।

এরপর একি ডিরেক্টরিতে VideoItem.js নামে আরেকটি ফাইল তৈরি করি । এটার কারণ হচ্ছে মূলত আমরা youtube api থেকে অনেক গুলো ভিডিওর লিস্ট পাবো । সেগুলো একটা একটা করে নিবো আর সেটাকে ডিজাইন করবো এরকম ভাবে সব গুলো কমপ্লিট হয়ে গেলে নেক্সটে সব গুলো রেন্ডার করবো ।

<VideoItem এর ভেতর single video পাস করে করে দিবো child component এ ।

Rendering List of video

এখানে আমরা VideoList এ map() মেথডের ভেতর একটা একটা করে ভিডিও পাঠিয়েছিলাম সেগুলোর একটা নিয়ে সেটার title দেখাইছি । এখানে props না ব্যাবহার করে destructuring করে সেখান থেকে শুধু video বের করে নিয়ে আসছি ।

Rendering video thumbnails

return (
<div>
<img src={ video.snippet.thumbnails.medium.url } alt='video images' />
{ video.snippet.title }
</div>
);

video র কভার ইমেজ নিয়ে আসার জন্য উপরের কোড গুলো লিখতে হয় img ট্যাগের মধ্যে এখন কিছু CSS styling করবো ।

Styling a list

semantic ui এর লিস্ট সেকশনে গেলে আমরা বিভিন্ন ধরনের লিস্ট দেখতে পারবো এখান থেকে আমরা আমাদের ডিজাইন করবো বিভিন্ন ধরনের class ব্যাবহার করে ।

উপরের এই লিঙ্ক থেকে লিস্ট কিভাবে তৈরি করবো তার বিভিন্ন রকম class দেওয়া আছে ।

এরপর সিএসএস টা এপ্লাই করবো ।

VideoItem.js

import './VideoItem.css';<div className="video-item item">

videoitem.js ফাইলে এই দুটো লাইন এড করে দেই তাহলেই এই css ইমপ্লিমেন্ট হয়ে যাবে ।

Communicating from Child to Parent

video সার্চ করার পর যখন youtube api থেকে ভিডিও আশে তখন সব গুলো item ই ক্লিকেবল কারণ css এ styling করার সময় console এ cursor দিয়েছি । এখন এই আইটেম গুলো ক্লিক করার পর VideoDetail পেজে যাবে সেজন্য আমাদের কিছু কাজ করতে হবে ।

parent এর state এ একটি কলব্যাক মেথড ডিক্লেয়ার করবো । যখন কোনও video ক্লিক করা হবে তখন এই video অবজেক্টটি ধরে এই কলব্যাকের মাধ্যমে পাঠিয়ে setState আপডেট করে দিবো এই অবজেক্ট টি দিয়ে ।

parent থেকে যখন কোনও কিছু পাঠাই তখন prop system এ পাঠাতে পারবো কিন্তু যখন child থেকে parent এ পাঠাবো তখন সেটা callback এর মাধ্যমে পাঠাতে হবে । এখানে আমরা এই কলব্যাকের নাম দিবো selectedVideo

প্রথমে আমরা App কম্পোনেন্টে selectedVideo initialize করে দিবো ।

App.js file

state = { videos: [], selectedVideo: null }
..............................
onVideoSelect = video => {
console.log('From the App!', video)
}
.............................
<VideoList onVideoSelect={this.onVideoSelect} videos={this.state.videos} />

এখান প্রথমে app component এ state এ selectVideo ইনিসিয়ালাইজ করে দিয়েছি এরপর onVideoSelect() কলব্যাক মেথড ডিক্লেয়ার করেছি এরপর return এ VideoList কম্পোনেন্টে সেটা prop system এর মাধ্যমে pass করে দিয়েছি ।

VideoList.js file

const VideoList = ({ videos, onVideoSelect }) => {
..................................
return <VideoItem onVideoSelect={onVideoSelect} video={ video } />;

এখন VideoList.js ফাইলে ঐ props টা destrucuring করেছি এরপর এর child component VideoItem এ পাস করে দিয়েছি ।

VideoItem.js file

const VideoItem = ({ video, onVideoSelect }) => {
...................................
<div onClick={() => onVideoSelect(video)} className="video-item item">

VideoItem কম্পোনেন্টে প্রথমে destructuring করে নিয়েছি onVideoSelect কলব্যাক মেথডটি এরপর onClick এ এই কলব্যাক মেথডটি কল করেছি সাথে video টি পাস করে দিয়েছি । যখনি আমরা কোন আইটেমে ক্লিক করবো তখনি ঐ আইটেমের ইনফরমেশন কনসলে লগ আউট হবে । অর্থাৎ এখানে আমরা মূলত click করা আইটেমের ইনফরমেশন parent কম্পোনেন্টে পাস করেছি এখন আমাদের যেখানে প্রয়োজন সেখানে ব্যাবহার করবো ।

যে আইটেমে ক্লিক করবো সে আইটেমের ইনফরমেশন কনসলে দেখাবে ।

Conditional rendering

conditional rendering এ আমরা এখানে দেখবো যে আমরা state এ selectVideo র ভেলু null করে দিয়েছি এর জন্য এরর দিবে কারণ যখন প্রজেক্ট ইনিসিয়ালাইজ হবে তখন এর ভেলু null দেখাবে কিন্তু এই নালের জন্য এরর দিবে তাই আমরা এখানে কন্ডিসন চেক করবো যে নাল থাকলে loading দেখানে না হয় ভেলু রিটার্ন করবে ।

প্রথমে আমরা setState দিয়ে selectVideo এর ভেলু আপডেট করে দিবো ।

এরপর component এর আন্ডারে VideoDetail.js নামে একটি ফাইল তৈরি করে নিচের কোড গুলো লিখবো ।

এরপর App কম্পোনেন্টে এই ফাইলটি import করে রেন্ডারে search কম্পোনেন্টের পরে এই detail কম্পোনেন্ট দেখাব, সেজন্য selectVideo র ভেলু এর ভেতর props হিশেবে পাঠিয়ে দিবো ।

import VideoDetail from './VideoDetail';
...............................
<VideoDetail video={ this.state.selectedVideo } />

Styling Video detail

Displaying a video player

iframe tag অটোম্যাটিক নেটওয়ার্ক কল করে ভিডিও প্লেয়ার নিয়ে আসে, youtube থেকে আসা ভিডিও লিঙ্কে । এটি একটি html ট্যাগ । youtube এর কোনও ভিডিও তে গেলে সেখানে embade এ গেলে এধরনের ট্যাগ দেখতে পারবো যে কিভাবে কল করা হয় ।

styling with semantic Grid system

detail এবং player একি রো তে রাখবো আলাদা আলাদ কলামে । এজন্য semantic grid সিস্টেম ব্যাবহার করবো । grid সিস্টেম সাধারণত 16 টি কলামে বিভক্ত থাকে । নিচের এই লিঙ্কে grid system সম্পর্কে সকল কিছু আছে ।

এখন App.js ফাইলে কিছু styling করি ।

আর ImageList.js ফাইলে নিচের এই লাইন টিতে key দিয়ে দেই কারণ এই key দিলে রেন্ডারিং অনেক efficient হবে ।

return <VideoItem key={video.id.videoId} onVideoSelect={onVideoSelect}  video={ video } />;

Defaulting video selecting

normally default ভাবে selectVideo তে কোন ভেলু থাকে না তাই iframe এ কোনও কিছু থাকে না, জাস্ট ফাকা থাকে তাই default value দিয়ে দিতে হয়। যাতে লোড হওয়ার সাথে সাথেই কিছু ডাটা দেখা যায় । যখন কোন কিছু সার্চ দেওয়া হবে তখন নতুন video list render হবে । এজন্য componentDidMount() এর onTermSubmit এ buildings দিয়ে selectedVideo র ভেলু আপডেট করে দেয়া হয়েছে ।

12. Redux

redux হচ্ছে state ম্যানেজমেন্ট লাইব্রেরি, অর্থাৎ react এ আমরা ডাটা স্টোর করতাম ক্লাসের/কম্পোনেন্টের ভেতর তাই অন্য কোথাও থাকে এই ডাটা এক্সেস করার জন্য অনেক ঝামেলা পোহাতে হয় । কলব্যাক, প্রপ ইত্যাদির মাধ্যমে এক্সেস করতে হয় ।

রিডাক্সে আমরা state এর এই ডাটাগুলো অন্য জায়গায় স্টোর করবো এরপর প্রয়োজন মতো রিডাক্স থেকে state এর ডাটা নিয়ে ব্যাবহার করবো । রিডাক্স অনেকটা front-end এর ডাটাবেজের মতো । এটা অনেক কমপ্লেক্স প্রজেক্ট সহজ করে দেয়, কিন্তু ছোট খাটো প্রজেক্টের এটা না হলেও অতোটা সমস্যা হয় না । এটা শুধু react এর সাথেই ব্যাবহার করা যায় না অন্যান্য ফ্রেমওয়ার্ক যেমন vue, angular এর সাথেও ব্যাবহার করা যায় ।

Redux analogy

redux বোঝার জন্য কিছু analogy বোঝার দরকার হয় , এগুলো নিচে আলোচনা করা হল ।

এখন আমরা সিম্পলি একটি ইনস্যুরেন্স কোম্পানির কথা চিন্তা করি, পরে এটার সাথে redux কে মিলাব ।

ধরা যাক, একটি ইনস্যুরেন্স কোম্পানির কিছু policy আছে যেমন কারো যদি গাড়ি এক্সিডেন্ট করে আর সেই গাড়ির ইনস্যুরেন্স করা থাকলে কিছু টাকা সে পাবে । আবার claim হচ্ছে ধরেন আমার কাছে কিছু কাগজ পত্র আছে যেটা ঐ ইনস্যুরেন্স কোম্পানিকে দিলে তারা ভেরিফাই করে ক্ষতিপূরণ দিবে ।

form ২ ধরনের হতে পারে একটি হচ্ছে policy form আরেকটি হচ্ছে claim form . এখানে একজন কাস্টমার একটি claim ফর্ম নিয়ে ইনস্যুরেন্স কোম্পানির কাছে গেলো । ফর্ম রিসিভার সেই ফর্মকে নিয়ে কয়েকটা কপি করে বিভিন্ন department এ পৌঁছে দিবে । এখানে ৩ ধরনের department আছে claims history, policies, accounting । বিভিন্ন ধরনের department এর কাজ বিভিন্ন ধরনের ।

এখন ধরা যাক একটি management team আছে যারা কিনা সব ধরনের ইনফরমেশন আপডেট করে রাখে । এখন form receiver কোন claim policy department এর কাছে নিয়ে গেলো তখন তারা সেটিকে management team এর কাছে পাঠালে তারা সেটিকে central database এ আপডেট করে দিবে, প্রত্যেক ডিপার্টমেন্টের জন্য আলাদা আলাদা কিছু স্টোরেজ থাকে এরপর সেটাকে policy department এর কাছে পাঠাবে ।

ধরা যাক ৩ ধরনের কাস্তমার ৩ ধরনের ফর্ম নিয়ে গেলো কোম্পানির কাছে ।

এখন ফর্মের ২ ধরনের ইনফরমেশন থাকতে পারে কোনও ফর্মের । একটি হচ্ছে কি type এর আরেকধরনের ইনফরমেশন হচ্ছে তার ডাটা অর্থাৎ payload. payload নাও থাকতে পারে, এটা আবশ্যিক না ।

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

এখানে ধরা যাক কেউ একটি ফর্ম accounting department এ দিল , সে চেক করে দেখল যে এটি কি claim যদি claim হয় তাহলে চেক করে দেখল যে সে ২০ ডলার ফেরত চায় তাহলে সে ২০ ডলার টাকে দিয়ে ডাটাবেজে 80 ডলার আপডেট ক্রে রাখল ।

আর না হয় policy হলে অন্য কাজ গুলো করবে ।

এভাবে policies এও একি ভাবে চেক করে ডাটাবেজে আপডেট, ডিলিট করবে ।

Mapping the analogy to Redux

Action creator হচ্ছে একধরনের ফাংশন যেটা কিনা create/return জাভাস্ক্রিপ্ট অবজেক্ট রিটার্ন করে । এই জাভাস্ক্রিপ্ট অবজেক্ট টিই হচ্ছে Action.

Action এর ২ ধরনের প্রপার্টি আছে একটি হচ্ছে type প্রপার্টি আরেকটি হচ্ছে payload প্রপার্টি । action এর কাজ হচ্ছে Application এর ডাটাতে কি পরিবর্তন করতে চাচ্ছি ।

এখানে form receiver এর কাজ হচ্ছে যে কোন ফর্ম রিসিভ করে সেটাকে কোন নিদ্রিস্ট ডিপার্টমেন্টে পাঠিয়ে দেওয়া । dispatch এর কাজ ও একি । dispatch এর কাজ হচ্ছে ঐ জাভাস্ক্রিপ্ট অবজেক্টকে কপি করে নিয়ে এসে সেটাকে আমাদের application এর বিভিন্ন জায়গায় পাঠিয়ে দেওয়া ।

আমরা আগেই দেখেছি যে department এর জন্য নিদ্রিস্ট কিছু জায়গা থাকে যেটা কিনা সেন্ট্রাল ডাটাবেজে সেভ থাকে। একিভাবে reducer এর কাজ হচ্ছে action creator থেকে ডাটা নিয়ে এসে সেটাকে প্রসেস করে আপডেট করে রিটার্ন করে যাতে সেটা সেন্ট্রাল ডাটাবেজে সেভ করা যায় ।

state হচ্ছে সেই সেন্ট্রাল ডাটাবেজ । এখানেই সকল কিছু আপডেট থাকে । তাই ইউজারকে সবার কাছে যেয়ে যেয়ে জিজ্ঞাস করতে হয় না ডাটার জন্য, জাস্ট state এর কাছে গেলেই সব আপডেট ইনফরমেশন পেয়ে যাবে ।

Creating Action Creator

action creator এর বেসিক স্ত্রাকচার মোটামুটি একি । কিন্তু সমস্যা হচ্ছে dispatch, reducer কোথায় কিভাবে এপ্লাই করবো ।

Creating reducer

dispatch সেকশনটা পুরোপুরি redux নির্ভর তাই এটা পরে করবো এখন আগে reducer তৈরি করে নেই ।

store এর কাজ হচ্ছে বিভিন্ন ধরনের reducer এর সাথে action creator এর এসেম্বলি করে । এজন্য আমরা Redux থেকে createStore এবং combineReducers ইম্পরট করে নিবো ।

const { createStore, combineReducers } = Redux;const ourDepartments = combineReducers({
accounting: accounting,
claimsHistory: claimsHistory,
policies: policies
});
const store = createStore(ourDepartments);

এই লাইনগুলোতে আমরা reducer এবং action creator গুলো কম্বাইন করে নিয়েছি এরপর createStore এ একটি store তৈরি করে নিয়েছি এখন এই store object থেকে আমরা সকল state কে এক্সেস করতে পারবো । এই store অবজেক্টের বিভিন্ন ধরনের ফাংশন ব্যাবহার করতে পারবো ।

এখন store.dispatch() মেথডের ভেতরে action পাস করে দিলে সেটার action এর কপি reducer এ পাঠিয়ে দিবে ।

এখানে createPolicy() হচ্ছে একটি action . এই action দিয়ে দিলে স্টোরে ডাটা initialize হয়ে যাবে । এখন স্টোর থেকে ডাটা এক্সেস করার জন্য getState() মেথড ব্যাবহার করতে হয় ।

তাই console.log() এ এই মেথড কল করলে আমাদের স্টোরের ডাটা দেখা যাবে । এটা এখন নিজেদের প্রয়োজন মতো যেকোনো জায়গার ব্যাবহার করা যাবে ।

redux cycle এর এনালজি বুঝতে হলে আমাদের এই ডায়াগ্রাম টি বুঝতে হবে ।

ধরাযাক, আমরা state এর কোনও ডাটা মডিফাই করতে চাই সেজন্য প্রথমে action creator কে কল করতে হবে । এই action creator একটি action object তৈরি করবে । এই একশন কে এরপর dispatch এর ভেতর দিয়ে কল করতে হবে । dispatch মেথড সেটার একটি কপি reducer এ পাঠিয়ে দিবে ।

reducer সেটাকে state এ আপডেট করে দিবে ।

combine reducer এ আমরা key value হিশেবে reducer pass করে দিয়েছি এই নাম দিয়েই store এ ডাটা স্টোর হয়ে থাকবে । এখানে আমরা যেকোনো নাম ই দিতে পারি তাহলে সেই নামেই ডাটা স্টোর হয়ে থাকবে । কিন্তু কনভেনশন হচ্ছে একি নামে key value দেওয়া ।

সকল redux store design এই একি ফরম্যাটে হবে । redux store এ কোন ডাটা মডিফাই বা ক্রিয়েট করার জন্য আমাদেরকে অবশ্যই এই action creator, reducer এর মাধ্যমে করতে হবে, অন্য কোনও ভাবে এটা মডিফাই অথবা তৈরি করতে পারবো না । যেমন store.state.accounting-100 এভাবে করা যাবে না ।

13. Integrating React with Redux

project link :

react এবং redux একসাথে integrate করার জন্য আমরা সিম্পলই একটি প্রজেক্ট তৈরি করবো ।

এই প্রজেক্টে song list থাকবে এর এরপাশে একটি select বাটন থাকবে, যখন select বাটন ক্লিক করা হবে তখনি এর details দেখাবে ।

এখন আমরা আমাদের workspace ডিরেক্টরিতে গিয়ে নিচের কমান্ড টি দিয়ে songs নামে একটি react প্রজেক্ট তৈরি করবো ।

npx create-react-app songs

আগে থেকে npm গ্লোবালি ইন্সটল থাকলে সেটাকে uninstall করে দিয়ে এরপর উপরের এই কমান্ড দিলে প্রজেক্ট তৈরি হয়ে যাবে । আগে নরমালি create-react-app app_name কমান্ড দিলে প্রজেক্ট তৈরি হতো কিন্তু এখন নতুন ভার্সনে এটা দিয়ে করা যায় না, তাই উপরের এই কমান্ড দিলে প্রজেক্ট তৈরি হবে আগের কোনও কনফিগারেশন না থাকলেও ।

এখন এই প্রজেক্ট ডিজাইন করার জন্য এটিকে আলাদা আলাদা কম্পোনেন্টে ভাগ করে নিবো SongList এবং SongDetail.

প্রত্যেক SongList অবজেক্টের লিস্ট বা এরেতে রাখবো ।

react এর সাথে redux ইন্টিগ্রেট করতে গেলে আমাদেরকে ২ টা লাইব্রেরি অবশ্যই ইন্সটল করতে হবে একটি হচ্ছে redux আরেকটি হচ্ছে react-redux

react-redux লাইব্রেরি টি লাগবে react এর সাথে redux এর কমিউনিকেশনের জন্য আর redux তো অবশ্যই লাগবে । আর react লাইব্রেরি যখন আমরা প্রজেক্ট ইনিসিয়ালাইজ করি তখনি ইন্সটল হয় । এখন আমরা এই দুটো লাইব্রেরি ইন্সটল করবো নিচের এই কমান্ডের সাহায্যে ।

redux একটি ইন্ডিপেন্ডেন্ট লাইব্রেরি । এটা vue/angular অথবা যেকোনো frontend এর সাথেই ব্যাবহার করা যায় ।

npm i --save redux react-redux.........or........npm i redux react-redux

install হয়ে গেলে src এর আন্ডারে সকল ফাইল ডিলিট করে দিয়ে সেখানে index.js নামে একটি ফাইল তৈরি করি । এরপর সেখানে নিচের কোড গুলো লিখি ।

এরপর src/components/App.js নামে একটি ফাইল তৈরি করে সেখানে নিচের কোড টুকু লিখে দেই ।

এরপর semantic ui এর cdn লিঙ্ক আমাদের প্রজেক্টে ইন্টিগ্রেট করবো। google এ যেয়ে semantic ui cdn লিখে সার্চ দিলে সেখান থেকে semantic ui cdn এর সাইটে গিয়ে semantic.min.css লিখে সার্চ দিলে ঐ লিঙ্ক দেখানে সেখান থেকে এই লিঙ্ক কপি করে নিয়ে এসে আমাদের প্রজেক্টের public ডিরেক্টরির আন্ডারে index.html ফাইলের head সেকশনে লিঙ্কটি দিয়ে দিবো ।

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" integrity="sha512-8bHTC73gkZ7rZ7vpqUQThUDhqcNFyYi2xgDgPDHc+GXVGHXq+xPjynxIopALmOPqzo9JZj0k6OqqewdGO3EsrQ==" crossorigin="anonymous" />

design of redux app

আমরা আগের অ্যাপ এ component label এ state ডিজাইন করেছিলাম । সেখানে state এর প্রপার্টি এক্সেস করতে গেলে parent-child এর মাধ্যমে এক্সেস করতে হতো কিন্তু আমরা এখানে react এর বাহিরে আলাদা ভাবে redux এ ডাটাবেজ ডিজাইন করবো। বলা যেতে পারে এটা হচ্ছে front-end এর ডাটাবেজ ।

বাম পাশের চিত্র টা হচ্ছে এই প্রজেক্ট যদি শুধু react এ করা হতো তাহলে এটার স্টোর ডিজাইন কেমন হতো আর ডান পাশের চিত্র হচ্ছে যদি এই প্রজেক্টটি redux এ ডিজাইন করা হয় তখন এটার স্টোর ডিজাইন কেমন হবে ।

How react-redux work

পাশের এই ডায়াগ্রাম অনুযায়ী এই react-redux সিস্টেম কাজ করে । provider এবং connect এই দুটো আলাদা কম্পোনেন্ট বা ট্যাগ । এই দুটো ট্যাগ সরাসরি যোগাযোগ করতে পারে যদিও এদের মাঝে অন্য কোনও প্যারেন্ট কম্পোনেন্ট থাকে । provider সব সময় একদম প্রথমে ইনিসিয়ালাইজ হয়ে থাকে । এই কম্পোনেন্ট গুলো যোগাযোগ করে থাকে context সিস্টেমের মাধ্যমে ।

connect function provider এর কাছে list of songs চাইবে । provider এর পর store থেকে dispatch এর মাধ্যমে list of songs নিয়ে এসে props এর মাধ্যমে SongList কম্পোনেন্টে পাঠাবে । action creator এর কাজ হচ্ছে এখানে কোন song select করলে ঐ action creator তৈরি করে connect এর মাধ্যমে props হিশেবে Select song action creator পাঠিয়ে দিবে ।

Project structure :

src এর আন্ডারে action এবং reducers নামে ডিরেক্টরি তৈরি করবো। এরপর action ডিরেক্টরিতে index.js নামে একটি ফাইল তৈরি করবো । এই ফাইলের নাম অন্য যেকোনো কিছুই দেওয়া যাবে কিন্তু এটা হচ্ছে conventional . এই নাম দিলে আলাদা করে ফাইলের নাম ধরে App.js কম্পোনেন্ট ক্লাসে import করতে হবে না শুধু /action এই ডিরেক্টরির নাম দিলেই import হয়ে যাবে ।

import actions from '../actions';

এখানে আমরা export default ব্যাবহার করিনি কারণ এটা দিয়ে একটা ক্লাসে শুধু মাত্র একটা ফাংশনের ক্ষেত্রেই ব্যাবহার করা যাবে কিন্তু যদি আমরা named export ব্যাবহার করি তখন আমরা একাধিক ফাংশন export করতে পারবো । আর তাই এখানে named export ব্যাবহার করেছি ।

এখন অন্য ফাইলে এই ফাংশন গুলো ব্যাবহার করার জন্য আলাদা আলাদা ভাবে করতে হয় কারণ name export এ একভাবে করে আর default export আলাদা ভাবে import করে ।

// default export
import selectSong from '../actions'
// named export
import { selectSong } from '../actions'

named export এ দুইটা second bracket দিতে হয় এখানে কমা কমা দিয়ে একাধিক ফাংশন import করা যায় ।

Building reducer

আমরা অ্যাপ এর ডিজাইন অনুযায়ী ২ টা reducer তৈরি করবো । আর action creator তো তৈরি করেছি ই ।

এখানে আমরা কিছু static সং দিয়ে দিয়েছি কিন্তু পরবর্তীতে এটা প্রয়োজনমতো dynamic করা যাবে । আর selectedSongReducer এ action creator থেকে ডাটা আসলে সেই ডাটাকেই আমরা বেক করবো অন্যথায় null দিয়ে দিবো । এরপর combineReducer এ key value দিয়ে দিয়েছি reducer ম্যাপ করে । এই key টাই state এ স্টোর হবে ।

এখন Provider এ reducer এর রেফারেন্স দিয়ে দিবো । এরপর store তৈরি করার জন্য createStore ফাংশনের ভেতর reducer দিয়ে দিবো । এর জন্য নিচের কোড গুলো লিখবো । এগুলো করবো আমরা src এর আন্ডারে index.js ফাইলে ।

index

এখানে root হায়ারারকিতে Provider এ redux এর লিঙ্ক করে দিলে পরবর্তীতে যেকোনো child component এ connect ফাংশনের মাধ্যমে এই provider এর কাছে ডাটা চাইলে অথবা state মডিফাই করতে চাইলে provider অটোম্যাটিক ভাবে store এর data manipulate করবে ।

implement connect function

এখন components ডিরেক্টরির আন্ডারে SongList.js নামে একটি ফাইল তৈরি করে সেখানে নিচের কোড গুলো লিখবো এরপর App.js ফাইলে এই কম্পোনেন্টটি integrate করে দিবো ।

const App = () => {
return (
<div>
<SongList />
</div>
);
};

উপরের এই লাইনগুলো App.js ফাইলে দিয়ে দিবো ।

এখন প্রজেক্ট রান করলে SongList স্ট্রিং টি দেখা যাবে। এখন আমরা এই লেখার পরিবর্তে আমাদের redux store এর সং লিস্ট দেখাব ।

এখন connect function কানেক্ট করার জন্য SongList.js ফাইলে নিচের লাইনটি দিয়ে প্রথমে import করে নিবো ।

import { connect } from 'react-redux'

এরপর export default এ নিচের লাইন দিয়ে কানেক্ট করে দিবো ।

export default connect()(SongList);

এটা হচ্ছে IIFE function .

যেমন উপরের এই উদাহারনটিতে দেখিয়েছি IIFE function(Immediately Invoked Function Expression) কিভাবে কাজ করে । দুইবার কল করার মানে হচ্ছে ফাংশনটি দুইবার রিটার্ন করে । অর্থাৎ দুইটা return statement আছে । connect function টা আসলে একটি component .

Configuring Connect with MapStateToProps

redux store থেকে ডাটা এক্সেস করার জন্য সব সময় এই একি ফরমেট ব্যাবহার করতে হয় । mapStateToProps এর জায়গায় অন্য যেকোনো নাম ও দেওয়া যায় কিন্তু এটা হচ্ছে convention । এই মেথডের মাধ্যমে কোন ডাটা এক্সেস করবো সেটা ঠিক করে দিবো এরপর আমরা কম্পোনেন্টের যেকোনো জায়গায় ব্যাবহার করতে পারবো এই ডাটা । উপরে আমরা render() এর ভেতর console.log() এ ডাটা কনসলে দেখিয়েছি ।

এরপর সেটা connect() এর ভেতর পাস করে দিয়েছি ।

এখানে পাশের চিত্রে কনসলে ডাটাগুলো দেখা যাবে ।

Building a List with Redux data

renderList() মেথডের কাজ হচ্ছে song list এর একটা একটা করে song নিবে এরপর সেটাকে JSX list এ রূপান্তরিত করবে , এভাবে সব গুলো লিস্ট এর song দিয়ে jsx list তৈরি করে রিটার্ন করবে । এখন parent কম্পোনেন্টেও কিছু semantic ui এর class এপ্লাই করবো ।

Calling action creator from components

এই ডায়াগ্রাম থেকে আমরা জানি যে connect এর ভেতর action creator ও পাস করা যায় । এই action creator পরে reducer থেকে ম্যাচ করে ডাটা নিয়ে এসে component এ ডাটা props এর মাধ্যমে পাস করে দিয়ে এক্সেস করতে দেয় । এখন আমরা connect এর দ্বিতীয় আর্গুমেন্টে আমরা actions/index এ যে action creator তৈরি করেছিলাম সেটা import করে pass করে দিবো ।

// SongList.js 
import
{ selectSong } from "../actions";
....................export default connect(mapStateToProps, { selectSong })(SongList);

component ক্লাসের নামের প্রথম Letter ক্যাপিটাল লেটারে দিতে হয়, এটা হচ্ছে কনভেনশনাল ।

এখন আমরা যে selectSong একশন ক্রিয়েটর তৈরি করেছিলাম সেটা কল করার সময় একটি argument দিয়ে দিতে হয় । যখন এই বাটনে ক্লিক করবো তখন ঐ লিস্টের song কে আর্গুমেন্ট হিশেবে পাঠিয়ে দিবো ।

<button
className="ui button primary"
onClick={() => this.props.selectSong(song)}
>
Select
</button>

যখন এই selectSong একশন ক্রিয়েটর কল হবে তখন এই মেথডের type ‘SONG_SELECTED’ dispatch এ যেয়ে মিলিয়ে দেখবে তখন এটা পেলে সেটার payload return করবে ।

যখনি state পরিবর্তন হবে অর্থাৎ আপডেট হবে তখনি mapStateToProps পুনরায় রান হয়ে state update হবে । এই মেথডে যদি আমরা state কে কনসল লগ করি তখন আপডেট state properties গুলো দেখা যাবে ।

const mapStateToProps = state => {
console.log(state)
return { songs: state.songs }
}

mapStateToProps এ কনসল লগ করার পর এখন প্রজেক্ট রান করে লিস্ট গুলোর বাটনে ক্লিক করার পর আমাদের যে অবজেক্ট রিটার্ন করে সেখানে maximize করার পর আপডেট ডাটা দেখতে পারবো ।

selectSong() আসলে নরমাল একটি ফাংশন, এটাকে Action creator এ রূপান্তর করার জন্যই মূলত connect() ফাংশনের ভেতর pass করতে হয় । connect() ফাংশন সেটাকে dispatch() এর ভেতর অটোম্যাটিক pass করে সেটাকে redux store এ manipulate করে । যদি আমরা selectSong() মেথডকে connect() মেথডের ভেতর না দিয়ে দেই তখন আমরা যেকোনো জায়গায় ব্যাবহার করতে পারি নরমাল একটি ফাংশনের মতো করে ।

Functional components with connect

এখানে আমরা দেখবো যে কিভাবে আমরা redux store থেকে ডাটা এক্সেস করতে পারি অন্য কোন কম্পোনেন্ট থেকে ।

SongDetail এ state এর ডাটা access করার জন্য প্রথমে component এর আন্ডারে SongDetail.js নামে একটি ফাইল তৈরি করি এরপর উপরের কোডগুলো লিখি ।

SongList এর Select বাটনে ক্লিক করার পর state এ ডাটা যে আপডেট হবে সেটা এক্সেস করার জন্য reducer এ আমরা যে key-value দিয়েছি সেখান থেকে এক্সেস করতে পারবো ।

export default combineReducers({
songs: songsReducer,
selectedSong: selectedSongReducer
})

এখানকার selectedSong থেকে ডাটা পেতে পারি আর তাই SongDetail.js ফাইলের mapStateToProps মেথডে এই ভেলুটাকে জাস্ট song key এর ভেতরে জাস্ট assign করে দিয়েছি ।

এখন এই ডাটাটা আমরা আমাদের এই SongDetails কম্পোনেন্টে ব্যাবহার করতে পারবো । এভাবে আমরা ঐ redux store থেকে ডাটা এক্সেস করতে পারি ।

এই component টাকে আমরা এখন আমাদের App.js ফাইলের যেখানে প্রয়োজন সেখানে সেট করে দিবো ।

কনসল লগ করার পর আমরা এখন কোনও বাটনে ক্লিক করার পর দেখতে পারবো যে redux store এ ডাটা আপডেট হয়ে গেছে ।

Conditional rendering

নরমালি যখন আমরা song.title / song.duration এক্সেস করতে যাবো তখন error দিবে কারণ প্রজেক্ট যখন initially run হয় তখন state এ selectedSong এর ভেলু null থাকে । এই null ভেলু যখনি আমরা এক্সেস করতে যাবো তখনি error দিলে তাই এখানে আমরা চেক করেছি যে যখন null থাকবে তখন নরমাল একটি টেক্সট return করবে আর যখন কোনও button ক্লিক করা হবে তখন সেটার ভেলু দেখাবে ।

--

--