আজকে আমরা আলোচনা করব কিভাবে রিয়াক্ট এর Context API, useReducer, Custom Hooks দ্বারা Redux এর মতো state ম্যানেজ করতে পারি।
এগুলো নিয়ে যারা অলরেডি জানেন বা গবেষণা করেছেন তারা এই পোস্টটি এড়িয়ে যেতে পারেন ।
কিভাবে Redux ছাড়াই Redux এর মত করে reducer, dispatch, actions ব্যবহার করতে পারি সেটা দেখব.
আমরা নিশ্চয় জানি রিয়েক্ট এর কোন ডাটা যদি চাইল্ড কম্পোনেন্ট কে পাস করতে চাই তাইলে আমরা ডাইরেক্ট নেস্টেট n তম চাইল কে আমরা সেই ডাটাটা পাঠাতে পারিনা, তার জন্য আমাদের সবগুলো ইন্টারমিডিয়েট চাইল্ডের ভেতর দিয়ে আমাদের সব ডাটা গুলো পাস করতে হয় এবং একসময় Last child component এ ডাটা এক্সেস করতে পারি Props আকারে।
মানে প্রতিটি চিল্ড্রেন কে প্রপস আকারে ডাটা পাঠাতে হবেই ।
প্যারেন্ট থেকে ডাইরেক্ট কোনো চাইল্ড কে কোনো state পাঠাতে পারব না । আর এই প্রবলেম থেকেই গ্লোবাল স্টেট বাবহার শুরু ।
সো. গ্লোবাল স্টেট কি?
গ্লোবাল স্টেট হচ্ছে আমাদের এপ্লিকেশন এর স্টেট যেটা গ্লোবালি অ্যাকেসিবল হয়ে থাকে এবং যেটা
এপ্লিকেশন এর ভিতরে যেকোনো কম্পোনেন্ট এক্সেস করতে পারে । যেমন Redux এর state।
আমরা কনটেক্স এপিআই দ্বারা আমাদের স্টেটকে যে কোন কম্পনেন্টে থেকে এক্সেস করতে পারি।
লেটেস্ট ভার্সন রিয়াক্ট ইউজ রিডিউসার নামে হোক তৈরি করেছে ইউজ রেডিওস ব্যবহার করে আমাদের লোকাল স্টেট কে আরো কমপ্লেক্স ভাবে ইউজ করতে পারি।
রিয়েক্ট ডিসপ্যাচ দ্বারা স্টেট কে পরিবর্তন করতে পারি
আর কন্টাক্সে এপিআই দ্বারা আমাদের অ্যাপ স্টেট কে যেকোন কম্পোনেন্ট বা নেস্টেড চাইল্ড কম্পোনেন্ট থেকেও accees করতে করতে পারি।
আচ্ছা প্রথমে আমরা React.createContext দ্বারা আমরা একটা কনটেক্স তৈরি করবো।
কোড অর্গানাইজেশন করার জন্য আলাদা ফাইল বানাবো।
AppContext.js
ইনিশিয়াল ভ্যালু হিসাবে আমরা নাল প্রোভাইড করি। আপনিই যেকোন ভ্যালু প্রোভাইড করতে পারেন।
// AppContext.js
import {createContext} from "react";
export const AppContext = createContext(null)
এখন আমরা একটা কম্পনেন্ট তৈরি করব AppProvider.jsx
.jsx কেনো ? কারন context provider React component return করে। আর jsx রিটার্ন করে। তবে আপনি create রিয়েক্ট দিয়ে প্রোজেক্ট ইনিশিয়ালাইজ করলে extention js ইউজ করলেই হবে। আমি যেহেতু vite Js use korci তাই jsx ইউজ করছি ।
এর ভিতরে আমাদের এপ্লিকেশনের state রাখবো। যেটা গ্লোবালী Accessible হবে। স্টেট create করার জন্য useState hook ব্যবহার না করে আমরা useReducer hook ইউজ করব। কারন useReducer স্টেট কে আরো অনেক ভাবে মডিফাই করতে পারব লাইক dispatch করতে পারবো যে কোন অ্যাকশন টাইপ দ্বারা।
এই কম্পনেন্ট দ্বারা আমাদের রুট এপ্লিকেশন কে wrap করে দেব ।
কারন আমরা এই কম্পনেন্ট এর ভেতরে আমরা context এর ডাটা Provide করব।
যেভাবে আমরা context প্রোভাইডার দ্বারা আমাদের এপ্লিকেশন রুট কম্পনেন্ট কে wrap করে দেই।
Example code:
// AppProvider.jsx
export let dispatch;
const initialState = {
auth: null,
posts: []
}
function AppProvider(props) {
const [state, dispatch: dis] = useReducer(reducer, initialState)
dispatch = dis;
return (
<AppContext.Provider value={state}>
{props.children}
</AppContext.Provider>
)
}
এখন আমরা reducer তৈরি করব।
যেটা useReducer ফার্স্ট প্যারামেটার আকারে গ্রহণ করে।
reducer হচ্ছে জাস্ট একটা ফাংশন যেটা রিটার্ন করে আমাদের আপডেট state কে।
reducer ফাংশন দুইটা প্যারামিটার গ্রহণ করে প্রথমটা state পরেরটা action অবজেক্ট । এই অবজেক্টটা পাব যখন dispatch মেথড কল করব তখন যে অবজেক্ট পাঠাবো।
অ্যাকশন অবজেক্ট ভিতরে type নামে আর একটা প্রোপার্টি থাকবে যেটার উপর বেস করে আমরা গ্লোবাল state কে পরিবর্তন করবো।
আমরা switch কেস ইউজ করব । আপনি ইচ্ছা করলে if else ব্লক ও ইউজ করতে পারেন।
তবে শর্ত একটাই আপডেটেড state রিটার্ন করতে হবে।
Example code:
// reducer.js
function reducer(state, action) {
switch (action.type) {
case "LOGIN":
return {
...state,
auth: action.payload,
}
case "FETCH_POSTS":
return {
...state,
posts: action.payload,
}
default:
return state
}
}
AppProvider দ্বারা আমাদের রুট অ্যাপ কে আমরা wrap করে দেবো ।
// index.js
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<AppProvider>
<App />
</AppProvider>
</React.StrictMode>
)
ব্যাস আমাদের কাজ শেষ।
এখন আমরা আমাদের custom hook তৈরি করব l যার সাহায্যে আমরা আমাদের গ্লোবাল কন্টেক্স state কে এক্সেস করতে পারব এবং Dispatch করতে পারব। যেভাবে Redux এর অ্যাকশন create করে।
যখন আমরা আমাদের এই useStore custom hook ফাংশন কল করবো, তখন Array রিটার্ন পাব । যার প্রথম ইনডেক্সে এ থাকবে আমাদের কনটেক্স স্টেট এবং সেকেন্ড ইনডেক্সে এ থাকবে useReducer এর dispatch method.
Example code:
import React, {useContext} from "react";
import AppContext, {dispatch} from "./AppContext";
function useStore(){
const state = useContext(AppContext)
return [state, dispatch]
}
export default useStore
এবার আমরা ইউজ করব আমাদের কাস্টম useStore Hook ।
App.jsx
// App.jsx
function App() {
// useStore hook
const [state, dispatch] = useStore()
function handleLogin() {
// after successfully api call
dispatch({
type: 'LOGIN',
payload: user,
})
}
console.log(state.auth) // it will update when context state change
return (
<div>
<h1>App Component</h1>
<button onClick={handleLogin}>Login</button>
</div>
)
}
export default App
এখানে হ্যান্ডেল লগইন যখন ফাংশন কল করলে dispatch method যেটা useStore রিটার্ন করছে এবং Dispatch method কল করার সময় প্যারামিটার হিসেবে action অবজেক্ট পাঠাব। যার একটা প্রোপার্টি type যেটার উপর বেস করে গ্লোবাল state কে পরিবর্তন করবে। এবং payload দিয়ে ডাটা পাশ করব।
পোস্ট পেজ কম্পোনেন্ট
// Posts.jsx
function Posts() {
// useStore hook
const [{posts}, dispatch] = useStore()
useEffect(()=>{
fetch("/api/posts")
.then(response=>response.json())
.then((data)=>{
dispatch({
type: "FETCH_POSTS",
payload: data
})
})
}, [])
return (
<div>
<h1>Posts</h1>
{posts?.map(post=>(
<li>{post.title}</li>
))}
</div>
)
}
export default Posts
কত সুন্দরভাবে আমরা useReducer ইউজ করতে পারি Context API এর সাথে। কোনো context manually ইম্পোর্ট না করেই।
লিখায় অনিচ্ছাকৃত ভূল ত্রুটি ক্ষমা সুন্দর দৃষ্টিতে দেখবেন। 🙏🏻 🙏🏻 🙏🏻
Top comments (0)