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

Jahangir Alam
26 min readDec 26, 2020

Full react series is from udemy course Modern React with Redux by Stephen grider

Content

  • 14. Async Actions with Redux Thunk
  • 15. Redux store design
  • 16. Navigation with React router
  • 17. Handling Authentication with React
  • 18. Redux Dev tools

14. Async Actions with Redux Thunk

redux এর ভেতর যে সব middleware ব্যাবহার করা হয় , একেক middleware এর কাজ একেক রকম । এই প্রজেক্টে আমরা api দিয়ে ডাটা নিয়ে আসবো , এটা একটা asynchronous process.এই asynchronous process হেন্ডেল করবো আমরা redux-thunk দিয়ে।

আমরা এধরনের একটি ব্লগ পোস্ট প্রজেক্ট তৈরি করবো যেখানে blog post এবং author এর ডাটা গুলো আসবে rest based api থেকে । এজন্য আমরা jsonplaceholder নামের একটি সাইট থেকে ডাটা আনবো, এটি একটি fake api service site .

এই প্রজেক্টটি আমরা দুইটি কম্পোনেন্টে ভাগ করবো । একটি হচ্ছে PostList component আরেকটি হচ্ছে UserHeader component.

আমাদের প্রজেক্ট থেকে Axios এর মাধ্যমে নেটওয়ার্ক কল করবো JSONPlaceholder এ ফেক ডাটা আনার জন্য ।

এখন নিচের এই কমান্ডের মাধ্যমে blog প্রজেক্ট তৈরি করি ।

npx create-react-app blog

initial package setup :

এখন নিচের কমান্ডের সাহায্যে কিছু প্যাকেজ ইন্সটল করি ।

npm install --save redux react-redux axios redux-thunk

redux সাইট থেকে নেটওয়ার্ক রিকোয়েস্ট করার জন্য redux-thunk middleware লাগে ।

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

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

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

এখন npm start কমান্ড দিয়ে প্রজেক্ট রান করলে কোনও এরর দিবে না, ঠিক ভাবে রান করবে ।

redux based কোনও প্রজেক্ট initialize করার জন্য minimum কোড এটি ।

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

এখন এই কম্পোনেন্ট কে App.js ফাইলে ইন্টেগ্রেট করে দিবো ।

const App = () => {
return (
<div className="ui container"><PostList /></div>
);
};

এরপর public/index.html ফাইলের header সেকশনে semantic.min.css ফাইল CDN কে দিয়ে দিবো ।

<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" />

ইনিশিয়াল প্রজেক্ট সেটআপ মোটামুটি হয়ে গেছে ।

How to fetch data in a redux app :

এখন api থেকে ডাটা এনে আমরা কিভাবে আমাদের redux store এ জমা করবো সেটা দেখবো

api এর মাধ্যমে ডাটা আনার জন্য এই প্রসেস টা প্রায় প্রতি জায়গায় ব্যাবহার করা হয় ।

প্রথমে আমাদেরকে একটি কম্পোনেন্ট রেন্ডার করাইতে হবে । এখানে আমরা PostList কম্পোনেন্ট রেন্ডার করাবো ।

এরপর আমাদের componentDidMount রান করাতে হবে এজন্য আমরা Class based component ব্যাবহার করবো । class based component ব্যাবহার করলে আমরা সকল ধরনের life cycle method ব্যাবহার করতে পারবো ।

এই componentDidMount method এই আমরা action creator call করবো ।

যখনি এই কম্পোনেন্ট ইনিশিয়ালি রান হবে তখনি এই মেথডের ভেতর action creator রান হবে আর এই action creator এর ভেতর axios এর মাধ্যমে network request করবো । এই রিকোয়েস্ট করার মাধ্যমে কিছু ডাটা আসবে এখানে আমরা blog post ডাটা আনবো । এটা সব সময় ই একটা action রিটার্ন করবে । এই একশনের type এবং payload থাকবে ।

কিছু reducer এই action ধরার জন্য বসে থাকবে যখনি এই একশন পাবে তখনি এর payload রিটার্ন করবে । যখনি reducer রান হবে তখনি state আপডেট হবে ।

আর redux data আপডেট হলেই react component রি-রেন্ডার হবে।

অধিকাংশ সময়ই ডাটা fetch করা হয় componentDidMount মেথডের ভেতর ।

redux-thunk আমরা ব্যাবহার করবো action creator এ ।

Wiring up an action creator

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

এখন আমাদের PostList.js এ নিচের কোড গুলো লিখে action creator integrate করি ।

making a request from action creator

src এর আন্ডারে apis নামে একটি ডিরেক্টরি তৈরি করে সেখানে jsonPlaceholder.js নামে একটি ফাইল তৈরি করি । এখান থেকেই /post এ রিকোয়েস্ট করবো ।

এখন actions এ এই এন্ডপয়েন্টে নিচের মতো করে কল করে ডাটা নিয়ে এসে dispatch এ দিয়ে store এ সেভ করতে গেলে এরর দিবে কারণ ES6 syntax সেটাকে একটা অবজেক্ট রিটার্ন না করে একটা রিকোয়েস্ট রিটার্ন করবে ।

বেসিক্যালি এই প্রব্লেম শলভ করার জন্যই redux-thunk ব্যাবহার করা হয় ।

Middleware in Redux :

এর আগে যে redux ব্যাবহার করেছি সেটা হচ্ছে synchronous action creator . যখনি কোন ডাটার জন্য request করা হতো তখনি ডাটা দিয়ে দিতো । কিন্তু এখন আমরা asynchronous action creator ব্যাবহার করবো, মানে হচ্ছে রিকোয়েস্ট করার বেশ কিছু টাইম নিতে পারে ডাটা আপডেট হওয়ার জন্য, যখনি ডাটা আপডেট হবে কেবল তখনি ডাটা দিবে ।

redux এ asynchronous প্রসেস হেন্ডেল করার জন্য middleware ব্যাবহার করতে হয় । এখানে আমরা redux-thunk ব্যাবহার করবো ।

asynchronous action creator এ কোন action dispatch হয়ে reducer এ যাওয়ার আগে middleware হয়ে যেতে হয় । এই middlware বিভিন্ন ধরনের কাজ করতে পারে ।

middleware হচ্ছে একধরনের ফাংশন যেটা কিনা যখনি কোন action dispatch করা হয় তখনি কল হয় ।

এই middleware যেকোনো ধরনের action কে STOP, MODIFY অথবা যে কোনও ধরনের কাজ করতে পারে reducer এ যাওয়ার আগে ।

কোন action dispatch এ যাওয়ার আগে middleware এ কনসল লগ করলে বোঝা যাবে যে ঐ action টি reducer এ গিয়েছে কিনা ।

action creator অবজেক্ট অথবা ফাংশন রিটার্ন করতে পারে । অবজেক্ট রিটার্ন করলে সেটার অবশ্যই একটি type থাকবে এবং অপশনালি payload থাকবে । আর ফাংশন রিটার্ন করলে redux thunk সেটাকে অটোম্যাটিক আমাদের জন্য রিটার্ন করবে ।

redux-thunk বোঝার জন্য এটা জাস্ট একটা ডায়াগ্রাম । এখানে action creator যদি অবজেক্ট রিটার্ন করে তাহলে reducer এ চলে যাবে । আর ফাংশন হলে dispatch এবং getState আর্গুমেন্ট নিয়ে dispatch এ ইনভক হয় । dispatch redux store এর ডাটা মেনিপুলেট করার মতো অনেক পাওয়ার আছে আর getState স্টোর থেকে ডাটা নিয়ে আসে ।

এখন jsonPlasceholder এ রিকোয়েস্ট করার পর ডাটা চলে আসলে আমরা ম্যানুয়ালি ডাটাকে payload এ দিয়ে dispatch করে দিতে পারি । তখন এটি একটি অবজেক্ট রিটার্ন করবে তখন সেটাকে reducer এ পাস করে দিয়ে redux এ ডাটা আপডেট করে দিবো ।

Shortened syntax with redux thunk

redux-thunk কে middleware হিশেবে ডিক্লেয়ার করে দিতে চাইলে প্রথমে আমাদের src এর আন্ডারে যে index.js ফাইল আছে সেখানে বলে দিতে হবে । সেজন্য প্রথমে আমাদের ২ টা জিনিস import করতে হবে ।

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk'

এরপর render এ কিছুটা পরিবর্তন আনতে হবে ।

const store = createStore(reducers, applyMiddleware(thunk))ReactDOM.render(
<Provider store={ store }>
<App />
</Provider>,
document.querySelector('#root')
);

এখানে applyMiddleware() মেথডের ভেতর thunk দিয়ে দিয়েছি এর মানে হচ্ছে redux-thunk কে middleware হিসেবে redux store এ হুক আপ করেছি ।

এখন actions এর index.js ফাইলে গিয়ে নিচের কোড টুকু লিখবো ।

action creator এ আমরা এখানে function রিটার্ন করেছি, রিকোয়েস্ট থেকে ডাটা আসলে আমরা dispatch এ payload সেট করে দিবো । নিচে এর short hand syntax দেওয়া হল ।

export const fetchPosts = () => async dispatch => {
const response = await jsonPlaceholder.get('/posts');
dispatch({ type: 'FETCH_POSTS', payload: response });
}

15. Redux store design

প্রথমে reducer এর কিছু রুলস নিয়ে আলোচনা করবো ।

reducer এর প্রথম রুল হলো undefined হওয়া যাবে না অর্থাৎ return স্টেটমেন্টে ভেলু ‘undefined’ দেওয়া যাবে না বা রিটার্ন স্টেটমেন্ট অবশ্যই দিতে হবে । return স্টেটমেন্টে null, string, number, খালি অবজেক্ট অথবা খালি অবজেক্ট দিয়ে ইনিসিয়ালাইজ দিতে হবে ।

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

export default () => {
return 123;
}

এখানে জাস্ট dummy কিছু ডাটা দিয়েছি । এখন reducer এর index.js ফাইলে এই reducer টি ইন্টেগ্রেট করে দিবো ।

import postReducer from './PostsReducer'
.................
export default combineReducers({
posts: postReducer
});

দ্বিতীয় নিয়ম হচ্ছে reducer প্রথমবার অটোম্যাটিক ভাবে কল হয় । তখন এটি ২ টি আর্গুমেন্ট নেয়, প্রথম আর্গুমেন্ট হচ্ছে undefined আর দ্বিতীয় আর্গুমেন্ট হচ্ছে action. প্রথম আর্গুমেন্টে undefined থাকলে সেটাকে অটোম্যাটিক null করে দেয়, নিচের চিত্রে এটা ভালভাবে বোঝা যাবে ।

এর পরবর্তীতে যখনি কল হবে তখন এটি আগের বার যখন কল হয়েছিল তখনকার ডাটা বা স্টেট সংরক্ষণ করে রাখে । পরবর্তীতে যখন আবার কল হবে তখন আগের স্টেটের ভেলু নিবে এবং একটি action নিবে ।

তৃতীয় নিয়ম হচ্ছে যে state এবং action আর্গুমেন্ট হিশেবে নেওয়ার পর আর কোনও নেটওয়ার্ক রিকোয়েস্ট, ইউজারের কাছ থেকে কোন ভেলু নেওয়া বা হার্ড ড্রাইভ থেকে ডাটা নেওয়া এধরনের কোনও কাজ করতে পারবে না । জাস্ট state এবং action এর ভেলু নিয়ে কোন কেল্কুলেসন বা ফিল্টারিং বা ফর লুপ চালানো এধরনের কাজ করতে পারবে । অন্য কাজও করতে পারবে কিন্তু ওগুল হচ্ছে bad approach .

চতুর্থ নিয়ম হচ্ছে state আর্গুমেন্টটি mutation করা যাবে না, অর্থাৎ state এর ভেলু চেঞ্জ করা যাবে না ।

এখানে জাভাস্ক্রিপ্টের array এবং object এর ব্যাবহার দেখান হয়েছে । array এবং object দুইটাই পরিবর্তনশীল । state এ এই দুই টাইপ ব্যাবহার করলে reducer এ এরর দেখা দিতে পারে পরবর্তীতে কিন্তু string এবং number অপরিবর্তনশীল আর তাই state এ এই দুই টাইপ ব্যাবহার করলে চতুর্থ এই রুল নিয়ে চিন্তা করতে হয় না । array এবং object ও ব্যাবহার করা যাবে কিন্তু reducer এ এই স্টেটের ভেলু পরিবর্তন করা যাবে না ।

equality of arrays and objects

কোন স্ট্রিং বা নাম্বার কম্পেয়ার করলে শুধু সেটার ভেলু চেক করবে কিন্তু array/object কম্পেয়ার অপারেটর দিয়ে চেক করলে সেগুলোর মেমরি লোকেশন চেক করবে । যদি মেমরি লোকেশন মিলে যায় তাহলে true রিটার্ন করবে আর না হয় false রিটার্ন করবে ।

A misleading rule

৪ নাম্বার রুলে array/object দিয়েও কাজ করা যাবে কিন্তু এর একটি কর্নার কেস আছে । সেটি হচ্ছে আর্গুমেন্টে যে অবজেক্ট/ এরে নেওয়া হয় সেটিই যদি রিটার্ন করি তাহলে রিডাক্স মেমরি লোকেশন যখন মিলিয়ে দেখবে যে একি, তখন ঐ অবজেক্ট অথবা এরেতে যে মডিফাই করা হয়েছে সেটা আর re-render করে আপডেট করবে না, অর্থাৎ আশানরুপ ফল পাওয়া যাবে না । আর তাই অনেকে অবজেক্ট অথবা এরে ব্যাবহারের প্রতি অনুসাহিত করে ।

Safe state updates in reducer

array অথবা object কিভাবে সেফলি ব্যাবহার করা যায় সেটা আমরা এখন দেখবো । state এ যে এরে অথবা অবজেক্ট আসবে সেটাকে mutate না করে সেটাতে কিছু অপারেশন চালিয়ে নতুন obejct অথবা array প্রডিউস করবো ।

array/object কিভাবে সেফলি ব্যাবহার করা যায় সেটা এখানে দেখিয়েছি । এক্সিস্টিং array/objce কে সরাসরি পরিবর্তন না করে সেটাতে কিছু অপারেশন চালিয়ে নতুন array/object প্রডিউস করবো ।

এখানে array তে কিভাবে push এবং pop অপারেশন চালানো যায় সেটা দেখিয়েছি ।

এখন উপরে আমরা দেখলাম কিভাবে object কে মডিফাই করা যায় । অবজেক্ট থেকে এলিমেন্ট ডিলিটের জন্য আমরা এখানে lodash package ব্যাবহার করেছি । lodash প্যাকেজের omit() ফাংশন ব্যাবহার করেছি ।

switch statements in reducers :

এখানে একটি ওয়ার্নিং দিবে যে ফাংশনটাকে একটি ভেরিয়েবলে রাখতে হবে । সেজন্য আমরা এখানে ফাংশন টাকে একটি ভেরিয়েবলে রাখার জন্য ফাংশনের আগে const postReducer = () => {} এভাবে লিখে সেটাকে শেষে export default postReducer; এভাবে এক্সপোর্ট করে দিলে ওয়ার্নিং থাকবে না । এটা না করলেও সমস্যা নাই ।

switch এর জায়গায় if-else স্টেটমেন্ট ও ব্যাবহার করা যায় কিন্তু কমন একটি ব্যাবহার হচ্ছে swtich statement ব্যাবহার করা ।

এপিয়াই এর মাধ্যমে ডাটা আসলে সেটাকে redux এ সেভ করার জন্য এই কোড টুকু লিখতে হয় ।

dispatching the correct value :

API এর মাধ্যমে ডাটা এসে store এ সেভ হলে অর্থাৎ state আপডেট হলে অটোম্যাটিক কম্পোনেন্ট re-render হবে, তাই এই state এর ভেলুকে আমাদের PostList component এ ইন্টিগ্রেট করে দিতে হবে । এজন্য mapStateToProps এর ভেতর কিছু কোড লিখতে হবে যাতে store থেকে ডাটা এসে এখানে available থাকে এবং সেই mapStateToProps কে connect এর ভেতর পাস করে দিতে হবে ।

postlist কম্পোনেন্টে mapStateToProps এর ভেতর প্রথমে reducer এর সকল ডাটা নিলাম state আর্গুমেন্টে, এরপর সেটাকে posts এর ভেতর assign করলাম, এরপর সেটাকে connect এর ভেতর পাস করে দিয়ে render এর ভেতর কনসল লগ করবো ।

console.log(this.props.posts)

এখানে অনেক ধরনের ডাটা আসবে কিন্তু আমরা সব ডাটা নিবো না , শুধু data অবজেক্টের ভেতর যা আছে সেটাই লাগবে সেজন্য actions/index.js ফাইলে সব ডাটা পাস না করে দিয়ে শুধু data পাস করবো ।

dispatch({ type: 'FETCH_POSTS', payload: response.data });

অর্থাৎ request অবজেক্টে সব ডাটাই থাকবে, এখান থেকে শুধু response.data অবজেক্ট কে এক্সট্রাক্ট করে নিয়ে store এ পাস করে দিবো ।

List building :

এখন আমরা এই ডাটা গুলো নিয়ে JSX list তৈরি করবো । ডাটাগুলোকে একটি লিস্টে দেখাব । সেজন্য conponent/PostList.js ফাইলে নিচের কোড গুলো লিখবো ।

এখানে প্রত্যেকটা ইলিমেন্টকে map করে লিস্ট তৈরি করেছি এরপর সেটাকে render এ রেন্ডার করিয়েছি ।

Displaying users :

jsonplaceholder এ বিভিন্ন এন্ড পয়েন্টে রিকোয়েস্ট করার অপশন আছে, বিভিন্ন এন্ড পয়েন্টে বিভিন্ন ধরনের ডাটা দেয় ।

এখন আমরা /posts এন্ড পয়েন্টে রিকোয়েস্ট করলে শুধু পোস্টের ডাটাই দিবে আর /users এন্ড পয়েন্টে রিকোয়েস্ট করলে user এর ডাটা দিবে ।

আমরা আলাদা আলাদা ভাবে এই মাত্র দুইটা রিকোয়েস্ট করে সব ডাটা নিয়ে আসবো না । লিস্ট তৈরি করার সময় একটা পোস্ট এর ডাটা আসলে সেটার সাথে user এর id চলে আসবে যখন user এর id পাবো তখন ঐ id র এন্ড পয়েন্টে রিকোয়েস্ট করবো । যেমন /users/4 এই রকম user এর আইডি দিয়ে রিকোয়েস্ট করলে synchronization টা ঠিক হবে, কোনও ঝামেলা হবে না ।

এই রকম UserHeader নামে আরেকটি কম্পোনেন্ট তৈরি করে এর সাথে আরেকটি action creator তৈরি করবো ।

উপরে যে কথা গুলো বললাম সেগুলোই এখানে স্টেপ বাই স্টেপ দেখানো হয়েছে । নেক্সটে এ কাজ গুলোই করবো ।

Fetching singular records

এখন আমরা ইউজারের জন্য একটি action creator তৈরি করবো এরপর এটার জন্য reducer ও তৈরি করবো ।

Displaying user header

এখন UserHeader.js নামে একটি কম্পোনেন্ট তৈরি করবো । component নামের প্রথম অক্ষর বড় হাতের দিতে হয়, এটা হচ্ছে কনভেনশন ।

action creator এবং component তৈরি হয়ে গেলে এখন reducer তৈরি করবো । reducer ডিরেক্টরির আন্ডারে userReducer.js নামে একটি ফাইল তৈরি করি । এরপর সেখানে নিচের কোড গুলো লিখি ।

এরপর reducer এর আন্ডারে index.js ফাইলে import করে combinereducer এর ভেতর key-value হিশেবে সেট করে দিবো যাতে সেটা পরবর্তীতে ঐ key দিয়ে এক্সেস করতে পারি ।

import userReducer from './userReducer';
...................
export default combineReducers({
posts: postReducer,
users: userReducer
});

এখন এই ভেলু কে এক্সেস করার জন্য UserHeader কম্পোনেন্টে mapStateToProps এর মাধ্যমে এক্সেস করতে পারবো ।

এখানে user এর যত নাম্বার id তত নাম্বার id তে রিকোয়েস্ট করে ঐ ইউজারের সকল ডাটা নিয়ে আসলাম । এরপর আমরা find() মেথড দিয়ে ইউজারের id খুঁজলাম যে আমরা যে id দিয়ে রিকোয়েস্ট করেছি সেটার ডাটা এসেছে কিনা এরপর আসলে ঐ ইউজারের user name দেখিয়েছি । তবে এখানে একটি সমস্যা হচ্ছে প্রত্যেকটা ইউজার id র জন্য প্রত্যেকবার request করেছি । এখানে ১০ টা ইউজার কিন্তু পোস্ট ১০০ টা , তাই আমরা এখানে ১০০ বার রিকোয়েস্ট করেছি ইউজার আনার জন্য এটা একটা কর্নার কেস ।

এখানে উপরের চিত্রে কোনও নিদ্রিস্ট ইউজারের ডাটা এবং ব্রাউজারে রিকোয়েস্ট করার পর ওয়েব পেজে কি দেখাবে সেটার আউটপুট দেখিয়েছি ।

Extracting logic to MapStateToProps

store থেকে কোন ডাটা নিয়ে এসে সেটাতে কোন অপারেশন চালালে সেটা mapStateToProps এ করা বেস্ট প্র্যাকটিস কারণ অহেতুক বাড়তি ডাটা লোড করে ফিলটার আউট করার চেয়ে store থেকে ফিল্টার করে যেটুকু ডাটা প্রয়োজন সেটুকুই আনা ভালো, এতে app এ বাড়তি প্রেশার পরে না ।

Over fetching problem

100 টা পোস্টের জন্য ১০০ বার রিকোয়েস্ট করে ইউজার খুঁজে আনে, কিন্তু ইউজার আছে মাত্র ১০ টা ।অর্থাৎ একি আর্গুমেন্টে বার বার রিকোয়েস্ট করছে । ctrl+shift+iপ্রেস করে inspect ওপেন করে এর network ট্যাবে ক্লিক করে এরপর পেজ রিফ্রেশ করলে দেখা যাবে যে প্রত্যেকবার রিকোয়েস্ট করছে । এটা একটা বড় প্রব্লেম এটা শলভ করার জন্য কিছু প্রসেস আছে ।

Memoizing function

lodash নামে একটি javascript এর npm লাইব্রেরি আছে সেখানে memoize() নামে একটি মেথড আছে, এই মেথডের কাজ হচ্ছে কোন একটি আর্গুমেন্ট দিয়ে ফাংশন কল করলে সেই আর্গুমেন্টে আর দ্বিতীয়বার কল করবে না । প্রথম বার যেটা দিয়ে কল করা হয়েছিল সেটার যে return ভেলু আছে সেটা সেভ করে রেখে, সেটা আবার রিটার্ন করবে ।

lodash এর সাইটে গিয়ে কোড গুলো লিখেছি তাই lodash প্যাকেজ import করতে হয়নি, কনসলে available ছিল তাই memoize() মেথড ব্যাবহার করতে পেরেছি । এখানে দেখা যাচ্ছে যে প্রথমে আমরা নরমাল যে ফাংশন তৈরি করেছিলাম সেটা যতবার ই একি আর্গুমেন্ট দিয়ে কল করিনা কেনও প্রতিবার ই network রিকোয়েস্ট করে কিন্তু এই ফাংশনটি যখন memoized ভার্সন করেছি তখন এক আর্গুমেন্টে একবারই রিকোয়েস্ট করে ।

এখন আমাদের প্রজেক্টে আমরা এই প্যাকেজ ইন্সটল করে এই method ইমপ্লিমেন্ট করবো ।

npm i --save lodash

এখন lodash import করে কোড রিফেক্টর করি ।

এখানে ফাংশনটাকে আলাদা করে নিয়ে memoize করেছি এরপর সেটাকে কল করেছি ।

এখন পেজ রিফ্রেশ করলে দেখা যাবে যে একি আর্গুমেন্টের রিকোয়েস্ট একবার ই রিকোয়েস্ট করবে ।

Alternate over fetching problem :

memoization এখানকার জন্য ঠিক আছে কারণ আমরা কোনও particular id র জন্য শুধু ইউজারের ডাটা আনবো কিন্তু অনেক সময় দেখা যায় যে আমরা অন্য কিছু আনতে চাচ্ছি ঐ আইডির জন্য তখন এটা একটা flow back. আর তাই আমরা alternate approach দেখবো ।

এখানে আমরা এই লজিক গুলো ইমপ্লিমেন্ট করবো । আমরা এখানে একটাই action creator তৈরি করবো সেটা হচ্ছে fetchPostsAndUsers().

প্রথমে fetchPosts থেকে পোস্টগুলো আনবো এরপর সকল unique id খুঁজে বের করবো পোস্ট লিস্ট থেকে , এরপর unique id এর উপর লুপ চালাবো দেন fetchUser কল করবো প্রত্যেক user id র জন্য ।

এখন কোডিং সেকশনে memoize ভার্সন থেকে নরমাল ফাংশনে চলে যাবো । আর আগের memoize কোড টুকু কপি করে নিচে comment out করে রেখে দিবো, পরবর্তীতে memoize ব্যাবহারের জন্য ।

export const fetchUser = id => async dispatch => {
const response = await jsonPlaceholder.get(`/users/${id}`)
dispatch({ type: 'FETCH_USER', payload: response.data })
};

Finding unique user ids

এখানে প্রথমে getState আর্গুমেন্ট নিয়েছি, এটার কাজ হচ্ছে redux store থেকে সব state নিয়ে আসা । এরপর fetchPosts() একশন ক্রিয়েটর কল করে সকল post নিয়ে এসেছি । এরপর _.uniq() মেথডের কাজ হচ্ছে ইউনিক ভেলুু নিয়ে আসা, _.map() এর কাজ হচ্ছে প্রথম আর্গুমেন্ট হচ্ছে কোনটার সাথে map করবে আর দ্বিতীয় আর্গুমেন্টে যে ভেলু দিবে সেটার সাথে ম্যাপ করে array রিটার্ন করবে । ইউজারের unique id পেয়ে গেলাম । এখন fetchUser() একশন ক্রিয়েটরে কল করে user এর নাম নিয়ে আসবো ।

এখানে আরেকটা বিষয় হচ্ছে user এর একশন ক্রিয়েটর এখান থেকেই কল করে ফেলেছি আলাদাকরে user এর কম্পোনেন্টের componentDidMount() থেকে কল করার দরকার নাই তাই components/UserHeader.js থেকে componentDidMount() এর কোড ডিলিট করে দিবো সাথে সাথে এটার action creator এর import স্টেটমেন্ট কেটে দিয়ে connect থেকে ঐ action creator fetchUser ডিলিট করে দিবো ।

export default connect(mapStateToProps)(UserHeader);

16. Navigation with React router

এখানে আমরা twitch.tv সাইট টাকে ক্লোন করবো । এটা বেসিক্যালি video streaming সাইট ।

https://www.twitch.tv/

এই সাইটে অনেকে কোন ভিডিও রেকর্ড করে এখানে লাইভ করে । অনেকে এখান থেকে লাইভ ভিডিও দেখে ।

video stream করার জন্য একটি সফটওয়ার ব্যাবহার করবো এটা হচ্ছে OBS software . এটা একচুয়ালি একটি প্রোগ্রাম । এটা খালি ভিডিও streaming এর জন্যই না আমাদের desktop এ রেকর্ডিং এর জন্যও কাজে লাগান যায় । ডেক্সটপ stream করে সেটাকে একটা সার্ভারে রাখতে হবে সেটার নাম হচ্ছে RTMP server — Real Time Messaging Protocol server. এটা যেকোনো streaming video feed করে এরপর অন্যান্য দের কাছে পাঠিয়ে দেয় লাইভ দেখার জন্য । অন্যান্য ইউজার তাঁদের ব্রাউজারে গিয়ে OBS এর মাধ্যমে দেখতে পারে ।

কে কে এখন ভিডিও stream করতেছে সেটা দেখতে পারবে ইউজার । সেখান থেকে কোন একটা সিলেক্ট করলে সেটাকে ইউজার ব্রাউজার থেকে RTMP server এর মাধ্যমে OBS এ পাঠিয়ে দিলে লাইভ দেখতে পারবে ।

এটা করতে backend এ ছোট একটি API সার্ভার লাগবে ,streaming video র ইনফরমেশনের জন্য, viewer browser এ react-redux লাগবে আর RTMP server লাগবে ।

Mockups in details :

প্রথমে একটি ল্যান্ডিং পেজ থাকবে index page . এখানে বিভিন্ন ধরনের streaming video র লিস্ট থাকবে । কোনও একটা ভিডিও লিস্টের উপর ক্লিক করলে show stream page এ নিয়ে যেয়ে video দেখাবে ।

Authentication সেকশনে আমরা google এর মাধ্যমে লগইন করাবো ইউজারকে । এরপর লগইন করলে delete, edit বাটন ও থাকবে নিজের রেকর্ড এ । edit kওরতে চাইলে এডিট পেজে যাবে, create করতে চাইলে new page এ যাবে আর ডিলিট করতে চাইলে মডাল ওপেন হবে ।

Project initialization

প্রথমে workspace এ একটি ডিরেক্টরি তৈরি করবো । সেখানে front-end এর কাজ এক ডিরেক্টরিতে করবো, back-end এর কাজ অন্য ডিরেক্টরিতে করবো । এজন্য প্রথমে streams নামে একটি ডিরেক্টরি তৈরি করবো এরপর create-react-app দিয়ে react project তৈরি করবো ।

mkdir streams
cd streams
npx create-react-app client

প্রথমে আমরা ন্যাভিগেশনের জন্য react-router ব্যাবহার করবো , এরপর authentication এর জন্য google auth ব্যাবহার করবো, ফর্ম ডাটা হেন্ডেলের জন্য redux ব্যাবহার করবো । react-redux দিয়ে CRUD operation চালাবো ।

initial setup

src এর আন্ডারে সকল বয়লার প্লেট ডিলিট করে দিবো । এরপর src/index.js এবং src/components/App.js ফাইল তৈরি করবো ।

এখন প্রজেক্ট রান করলে App লেখাটি দেখা যাবে , তাহলে বোঝা যাবে যে প্রজেক্ট ঠিক ঠাক ভাবে সেটআপ হয়েছে । এখন react-router ইন্সটল করি ।

Introducing react router

npm i --save react-router-dom

react-router ফ্যামিলির এই কয় ধরনের ভেরিয়েন্ট আছে। react-router এর কাজ হচ্ছে low lable এর কিছু কাজ করা, সাধারণত এটা ব্যাবহারের দরকার হয় না । react-router-dom এটা react based এপ্লিকেশন এর জন্য লাগে । react-router-native এটা react-native মোবাইল বেজেড এপ্লিকেশনের জন্য লাগে আর react-router-redux সাধারণত react-redux এর জন্য ব্যাবহার করা যায় কিন্তু অধিকাংশ সময় এটি ব্যাবহার করা হয় না । অধিকাংশ সময় react-router-dom ই ব্যাবহার করা হয় এটাই ডকুমেন্টেশনে রিকমান্ড করা ।

এখন ছোট একটি এক্সাম্পল দেখবো কিভাবে রাউটার কাজ করে ।

এখানে রুট ডিরেক্টরিতে PageOne ওপেন হবে আর /pagetwo রাউটারে PageTwo ওপেন হবে ।

react-router সাধারণত domain name অথবা port টাকে কেয়ার করে না localhost:3000 এই পার্ট টাকে কেয়ার করে না । এরপরের অংশটাকে নেয় ।

BrowserRouter কম্পোনেন্ট ইন্টারনালি history অবজেক্ট তৈরি করে । এই history অবজেক্ট address bar এর ট্র্যাক রাখে এরপর BrowserRouter এর path এর সাথে কমিউনিকেট করে ।

path কিভাবে কাজ করে ?

<Route  path="/" exact component={ PageTwo } />
<Route path="/" exact component={ PageOne } />
<Route path="/pagetwo" component={ PageTwo } />

এভাবে দিলে একি পেজে দুইটা কম্পোনেন্ট রেন্ডার হবে ।

<Route  path="/" component={ PageOne } />
<Route path="/pagetwo" component={ PageTwo } />

আবার এখান থেকে exec key-word বাদ দিয়ে দিলেও একি কাজ হবে । এটা react এর অটো ডিজাইন করা । / এর পর যত গুলো route থাকবে সব গুলোই নিবে রেন্ডার করবে ।

anchor tag

react-redux এ আমরা কখনই anchor tag ব্যাবহার করবো না কারণ <a> ট্যাগে ক্লিক করলে সকল javascript veriable data, api data মুছে যাবে, নতুন করে পেজ রিলোড হবে । inspect এ গিয়ে <a> ট্যাগে ক্লিক করলে দেখা যাবে যে পেজ রিলোড হচ্ছে অর্থাৎ নতুন করে সার্ভারে রিকোয়েস্ট হচ্ছে ।

Navigating with react router

react router এ আমরা Link কম্পোনেন্ট ব্যাবহার করবো, এটা react-router-dom থেকে import করবো ।

এখন এই Link কম্পোনেন্ট ব্যাবহার করলে দেখা যাবে যে পেজ রিলোড হচ্ছে না, এখানেই single page application এর ধারনা আসছে অর্থাৎ পেজ রিলোড হবে না । কিন্তু ইন্সপেক্ট এ গেলে দেখা যাবে যে <Link> ট্যাগের জায়গায় <a> ট্যাগ দেখাচ্ছে ।

different router types

সাধারণত react এপ্লিকেশনে BrowserRouter ব্যাবহার করা হয় ।

HashRouter ব্যাবহার করলে domain বা পোর্ট এর পর # চিহ্ন বসিয়ে দেয় অটোম্যাটিক ।

MemoryRouter এ url এর কোন পরিবর্তন হয় না ।

Component scaffolding :

বাম পাশের গুলো হচ্ছে path আর ডান পাশের গুলো হচ্ছে component. path এর জন্য component গুলো রেন্ডার করবো ।

এখন আমরা components এর আন্ডারে streams নামে একটি ডিরেক্টরি তৈরি করবো এরপর সেখানে StreamCreate.js, StreamDelete.js, StreamEdit.js, StreamList.js, StreamShow.js নামে ফাইল তৈরি করবো ।

এখন একি ভাবে বাকিগুলোও করবো । এরপর শুধু নাম পরিবর্তন করে দিবো । যেখানে StreamList সেখানে StreamCreate, StreamDelete এভাবে বাকিগুলো করবো ।

এরপর App.js ফাইলে ঐ ফাইলগুলো import করে নিচের কোডগুলো দিয়ে দিবো ।

এখন এই route গুলোতে গেলে দেখা যাবে যে component গুলো রেন্ডার হচ্ছে ।

এটার মানে হচ্ছে যে BrowserRouter এর বাহিরে

কোন কিছু দেওয়া হলে সব গুলতেই ঐগুলো দেখাবে । যেমনঃ

<div>
<h1>Header</h1>
<BrowserRouter>
<div>
<Route path="/" exact component={StreamList} />
</div>
</BrowserRouter>
</div>

এখানে অন্য route গুলোও আছে । এখন সকল রাউটারেই এই header টা দেখাবে ।

Connecting the header:

এখন semantic ui এর cdn লিঙ্ক google করে নিয়ে এসে আমাদের index.html ফাইলের header সেকশনে দিয়ে দেই । এরপর src ডিরেক্টরির আন্ডারে Header.js নামে একটি কম্পোনেন্ট তৈরি করি এরপর সেখানে নিচের কোডগুলো লিখি ।

এরপর Header.js ফাইলটা App.js ফাইলে import করে <Route> ট্যাগের উপরে দিয়ে দেই । এখন প্রজেক্ট রান করলে ঠিক ভাবে Header integrate হয়ে যাবে ।

<Header> কম্পোনেন্ট টা <BrowserRouter> এর বাহিরে দেওয়া যাবে না কারণ Header এ আমরা react-router-dom এর কম্পোনেন্ট <Link> ব্যাবহার করেছি তাই এটা <BrowserRouter> এর বাহিরে দিলে এরর দিবে ।

17. Handling Authentication with React

normal authentication এ আমরা কোন ইউজারের email, password নিয়ে ডাটাবেজে সেভ করে রাখি এরপর লগইন করতে চাইলে সেই email, password চেক করে মিলিয়ে দেখি ঠিক আছে কিনা । আর OAuth authentication এ আমরা google, linkedin, facebook থেকে api এর মাধ্যমে ডাটা নিয়ে email অথবা যেকোনো কিছু নিয়ে identity check করি

email, password এগুলো হচ্ছে streamy , ইউজারের কাছ থেকে আমাদের access নেওয়ার জন্য permission এর দরকার হয় ।

google oauth scope list দিয়ে google এ সার্চ দিলে একটা লিঙ্ক দিবে সেখান থেকে আমরা আমাদের যত রকম streamy বা list of scopes এর পারমিশনের দরকার হবে সব কিছুর documentation পাবো ।

এটা হচ্ছে email এর জন্য , যদি আমরা google sign in এর মাধ্যমে scope এর এক্সেস পেতে চাই সেটার documentation. এভাবে আমরা gamil এর অপশন গুলোও পেতে পারি ।

How OAuth works:

OAuth সার্ভারের জন্য ব্যাবহার করবো না, simplicity র জন্য Google এর OAuth সার্ভিস ব্যাবহার করবো আমাদের apps এর জন্য ।

এখানের diagram এ আমরা দেখিয়েছি যে কিভাবে google servers এর api service ব্যাবহার করবো । ইউজার google button এ ক্লিক করলে আমরা জাভাস্ক্রিপ্টে কিছু কোডের মাধ্যমে google সার্ভারে রিকোয়েস্ট করবো । এরপর ওখান থেকে authentication হয়ে আসলে আমরা একটা callback invoke করবো আমাদের react-redux এপে । call back আমাদের authorization token এবং user info দিবে ।

Creating OAuth credentials

OAuth setup করার জন্য পাশের এই ফ্ল অনুযায়ী কাজ করতে হবে । প্রথমে console.developers.google.com এই সাইটে গিয়ে একটি প্রজেক্ট তৈরি করতে হবে যেভাবে আমরা করেছিলাম youtube প্রজেক্ট তৈরি করার সময় ।

এই সাইটে গিয়ে উপরের দিকে ড্রপ ডাউন এ Select project এ ক্লিক করে সেখানে Create project এ ক্লিক করে একটি নতুন প্রজেক্ট তৈরি করবো । প্রজেক্টের নাম দিবো Streamy.

এরপর প্রজেক্ট তৈরি হয়ে গেলে আবার উপরের Select project এ ক্লিক করে সেখান থেকে Streamy তে ক্লিক করলে আমাদের প্রজেক্টে চলে যাবো ।

Creating OAuth Credentials:

Streamy project এ যেয়ে সাইড বারে Credentials এ ক্লিক করে Create Credentials এ ক্লিক করলে কয়েকটা ড্রপ ডাউন আসবে সেখান থেকে OAuth Client Id তে ক্লিক করবো । এরপর Configure Consent screen এ ক্লিক করবো । সেখানে এপের নাম দিবো stream . এরপর এটা কনফিগার করে আবার Credentials এ ক্লিক করবো ।

এরপর আবার Create Credentials এ ক্লিক করে OAuth Client Id তে ক্লিক করে এরপর Application type এ web application এ ক্লিক করবো । এরপর একটি নাম দিবো Streamy

এরপর authorized javascript origin এ একটি url add করবো ।

http://localhost:3000

কারণ এখনকার জন্য আমরা শুধু localhost এর জন্য ব্যাবহার করতে চাচ্ছি । এরপর create এ প্রেস করবো ।

create হয়ে গেলে একটি client id দিবে । প্রথমটা আমাদের লাগবে তাই এই key টা কপি করে আমাদের প্রজেক্টে বা যেকোনো জায়গায় সেটাকে সংরক্ষণ করবো । কারণ রিকোয়েস্ট করার সময় এই id টা লাগবে ।

Wiring up the google api library:

এখন আমাদের প্রজেক্টে google api library ইন্টিগ্রেট করবো । এটা করার জন্য index.html এর header সেকশনের যেকোনো জায়গায় নিচের কোড টুকু দিয়ে দিবো ।

<script src="https://apis.google.com/js/api.js"></script>

এরপর প্রজেক্ট রান করে ব্রাউজারের console এ গিয়ে gapi

লিখে ইন্টার দিলে যদি অবজেক্ট রিটার্ন করে তাহলে বুঝতে হবে যে ঠিক মতো ইন্টিগ্রেট হয়েছে ।

OAuth flow react এবং redux এ ভিন্নভাবে কাজ করে কিন্তু এখানে আমরা প্রথমে react এর ফ্ল দেখবো এরপর react থেকে ডাটা redux store এ আপডেট করবো ।

এখন প্রথমে src/components এর আন্ডারে GoogleAuth.js নামে একটি ফাইল তৈরি করবো । সেখানে নিচের কোড গুলো লিখবো ।

এরপর Header.js ফাইলে গিয়ে এই কম্পোনেন্ট কে ইন্টিগ্রেট করে দেই ।

<div className="right menu">
<Link to="/" className="item">
All Streams
</Link>
<GoogleAuth />
</div>

এখন নিচের এই লিঙ্কে যাই ।

এত গুগল এ gapi documentation লিখে সার্চ দিলেও পাওয়া যাবে , এরপর সেখানের সাইড বারে Authentication সেকশনে যাবো । এখানে gapi.auth2.getAuthinstance() নামে একটি মেথড আছে এটা একটি google auth অবজেক্ট রিটার্ন করবে । এখানে signin, signout, currentuser এর মতো বিভিন্ন ধরনের মেথড আছে ।

auth.signIn() মেথড দিয়ে কনসলে ইন্টার দিলে google এ সাইন ইন করার একটি pop-up মেথড ওপেন হবে , এখানে যেকোনো একটি আইডি দিয়ে sign in করলেই হবে । এরপর auth.isSignedIn.get() মেথড দিয়ে রান করলে true or false রিটার্ন করবে । এটা দিয়ে বোঝা যাবে যে ইউজার সাইন ইন হয়েছে কিনা ।

এখানে getAuthInstance() দিয়ে gapi এর ইন্সটেন্স নিলাম এরপর চেক করলাম যে ইউজার sign in কিনা । এরপর কন্ডিশন অনুযায়ী ইউজারের স্ট্যাটাস সেট করে দিলাম । এখন আমরা প্রজেক্টের inspect এ কনসলে যেয়ে লগইন অথবা লগআউট করে দিয়ে পেজ রিফ্রেশ করলে কারেন্ট স্ট্যাটাস দেখাবে ।

যদি sign in থাকে তাহলে gapi.auth2.getAuthInstance().signOut() মেথড দিয়ে

সাইন আউট করতে পারবো । আবার gapi.auth2.getAuthInstance().signIn() করতে পারবো ।

Updating auth state :

এখন ব্রাউজারে গিয়ে gapi.auth2.getAuthInstance().isSignedIn দিয়ে ইন্টার দিলে কিছু মেথড দেখাবে যেগুলো আমরা ব্যাবহার করতে পারবো। এরমধ্যে একটি হচ্ছে listen() , এটার কাজ হচ্ছে ইউজার signin আছে কি নাই । এটা ব্যাবহারে করে আমরা লেখা অটোম্যাটিক পরিবর্তন করতে পারবো অর্থাৎ state আপডেট করতে পারবো । তখন ম্যানুয়ালি sign in অথবা sign out করার পর রিফ্রেশ করতে হবে না । স্টেট আপডেট হলে component অটোম্যাটিক রি রেন্ডার হয়ে লেখা আপডেট হবে ।

এখানে componentDidMount এ then এর ভেতরে তৃতীয় লাইনে listen() এর ভেতর onAuthChange মেথডের রেফারেন্স পাস করেছি, আর এই মেথডের ভেতর state এর ভেলু আপডেট করে দিয়েছি । অর্থাৎ যখনি sign in হবে তখন এর ভেলু true আপডেট হবে আর যখন sign out হবে তখন এর ভেলু false হবে ।

gapi.auth2.getAuthInstance().signOut() এই মেথড দিয়ে কনসল থেকে sign out করতে পারি আর gapi.auth2.getAuthInstance().signIn() মেথড দিয়ে sign in করতে পারি ।

On-Demand sign in and sign out :

এর আগে আমরা ম্যানুয়ালি sign in এবং sign out করেছে কিন্তু এখন আমরা সেখানে একটি বাটন এড করবো যেখানে ক্লিক করে sign in এবং sign out করা যাবে । sign in with google বাটনে ক্লিক করলে আমরা সেখানে onClick এ onSignIn মেথডের রেফারেন্স পাস করে দিয়েছি যখনি এটা ক্লিক করা হবে তখনি এই মেথড টি ফায়ার হবে তখন this.auth.signIn() মেথড কল হয়ে সাইন ইন হবে আবার সাইন হওয়ার পর sign out বাটনে ক্লিক করে সাইন আউট করা যাবে ।

onSignIn এর জায়গায় onSignInClick এবং onSignOut এর জায়গায় onSignOutClick দিয়ে রিনেম করি ।

আগের বার আমরা এভাবে redux স্টোর ডিজাইন করেছিলাম, ওখানে component থেকে ডাটা নিয়ে action creator এর মাধ্যমে dispatch করেছিলাম redux store এ । আবার যখন ডাটা লাগতো তখন mapStateToProps এর মাধ্যমে সেই ডাটা এক্সেস করতাম কিন্তু এখন সামান্য একটি পরিবর্তন করবো কারণ ইউজার sign in অথবা sign out বাটনে ক্লিক করলে সেখান থেকে একশন gapi এ যাবে সেখানে থেকে sign in অথবা sign out করে এরপর listen থেকে আপডেট ডাটা নিয়ে আসবে true or false .

এখন আমরা এটাকে এভাবে ডিজাইন করবো । বাটন এ ক্লিক করলে সেখান থেকে trySignIn() একশন ক্রিয়েটরে যাবে এরপর gapi থেকে ডাটা নিয়ে এসে changeAuth() একশন ক্রিয়েটর থেকে dispatch হয়ে redux store চলে যেয়ে স্টেট আপডেট হবে ।

Redux setup :

redux এবং react-redux প্যাকেজ দুটো ইন্সটল করি ।

npm install --save redux react-redux

এখন src এর আন্ডারে actions নামে ডিরেক্টরি তৈরি করে সেখানে index.js নামে ফাইল তৈরি করবো, এ ফাইলটি খালি রাখবো পরবর্তীতে কিছু action creator তৈরি করবো, এরপর src এর আন্ডারে reducers নামে একটি ডিরেক্টরি তৈরি করে সেখানে index.js নামে ফাইল তৈরি করে dummy একটি ফাংশন তৈরি করবো যাতে প্রজেক্টটা আপাতত রান হয় ।

import { combineReducers } from 'redux'export default combineReducers({
replaceMe: () => 'alsdf'
});

এরপর src এর আন্ডারে যে index.js ফাইল আছে সেখানে reducer ইন্টিগ্রেট কর দিবো ।

Connecting auth with action creator :

এরপর components এর আন্ডারে GoogleAuth.js ফাইলে উপরের এই action creator import করে নিচের কোড গুলো লিখবো ।

এখানকার onAuthChange এর ভেতর আগে যখন করেছিলাম তখন state এ isSignedIn এর ভেলু আপডেট করে দিয়েছিলাম কিন্তু এখন আমরা তা না করে action creator কল করেছি । এই action creator সেই ভেলুটাকে নিয়ে যেয়ে redux store এ আপডেট করে দিবে ।

এখন reducer তৈরি করি । প্রথমে reducers ডিরেক্টরির আন্ডারে authReducer.js নামে ফাইল তৈরি করে সেখানে নিচের কোড গুলো লিখি ।

এখানে INTIAL_STATE ভেরিয়েবলের নাম capitalize করেছি কারণ আমরা এটাকে constant হিশেবে ডিক্লেয়ার করেছি অর্থাৎ এটার ভেলু পরিবর্তন করবো না । redux এর একটি রুল হচ্ছে যে এই state এর ভেলু পরিবর্তন করা যাবে না । পরবর্তীতে এটা ব্যাবহার করে নতুন অবজেক্ট তৈরি করে রিটার্ন করেছি, মুল অবজেক্ট এর কোনও পরিবর্তন করিনি ।

এখন reducer এর index.js ফাইলে এটা ইন্টিগ্রেট করে দিবো ।

import { combineReducers } from 'redux'
import authReducer from './authReducer'
export default combineReducers({
auth: authReducer
});

এখন state এ auth নামের অবজেক্টে ডাটা সেভ হয়ে থাকবে, পরবর্তীতে যেকোনো জায়গা থেকে mapStateToProps মেথডের মাধ্যমে এক্সেস করতে পারবো এই ভেলু ।

এখন এই ভেলু আমরা GoogleAuth.js কম্পোনেন্ট থেকে এক্সেস করবো ।

এখন আরও কিছু বিষয় পরিবর্তন করবো ।

 state = { isSignedIn: null }

প্রথমে এই লাইনটি কেটে দিবো ।

this.setState({ isSignedIn: this.auth.isSignedIn.get() })

এরপর এই লাইনটি কেটে দিয়ে এর জায়গায় নিচের লাইনটি লিখবো ।

this.onAuthChange(this.auth.isSignedIn.get());

এই লাইনটি লিখে এর মাধ্যমে signIn(), signOut() একশন ক্রিয়েটর কল করবো । এরপর connect() মেথডের ভেতর {} ব্রাকেটের মাধ্যমে পাস করে দিবো ।

এখন এই redux এ state এর ভেলু স্টোর করার জন্য আমরা প্রজেক্টের যেকোনো কম্পোনেন্টের মাধ্যমে ইউজার signin আছে কিনা সেটা authenticate করতে পারবো জাস্ট connect এবং mapStateToProps মেথডের মাধ্যমে ।

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

export const SIGN_IN = 'SIGN_IN'
export const SIGN_OUT = 'SIGN_OUT'

এখানে জাস্ট ভেরিয়েবলের ভেতর স্ট্রিং গুলো রাখছি , এরপর এগুলো যেখানে যেখানে দরকার সেখানে সেখানে এগুলো ইম্পরট করে ব্যাবহার করতে পারবো । এতে করে টাইপিং এ মিস্প্লে হলে এরর ভালভাবে দেখাবে যে কোথায় এরর হয়েছে ।

import { SIGN_IN, SIGN_OUT } from './types'

Recording the User’s Id :

this.auth.currentUser.get().getId() এই মেথড কল করলে user id দেয়, এই ইউজার আইডি হচ্ছে google এ কেউ সাইন ইন করলে অটোম্যাটিক একটা ইউজার আইডি দেয়, এটাই হচ্ছে সেটা। এখন এই ইউজার আইডি আমরা আমাদের রিডাক্স এ সেভ করবো ।

এজন্য GoogleAuth.js কম্পোনেন্টের onAuthChange() মেথডের signIn() মেথডের ভেতর this.auth.currentUser.get().getId() এটা পাস করে দিবো ।

if (isSignedIn) {
this.props.signIn(this.auth.currentUser.get().getId());
}

এরপর action creator এর signIn এ আর্গুমেন্টই হিশেবে userId দিবো, সাথে একটা payload ও দিবো ।

export const signIn = userId => {
return {
type: SIGN_IN,
payload: userId
}
}

এখন reducer এ এই payload এর ডাটা স্টোর করে রাখবো , আবার যখন signOut করবে তখন এটার ভেলু null করে দিবো ।

18. Redux Dev tools

এখন প্রথমে আমরা redux-devtool-extension ইন্সটল করবো আমাদের ক্রম ব্রাউজারে ।

এরপর কোডে এটা ইন্টিগ্রেট করে দিবো ।

এখানে সবুজ লেখাটি কোডে ইন্টিগ্রেট করে দিবো ।

--

--