রিঅ্যাক্ট তার v16.3.0 তে নতুন Context API অ্যাড করেছে। এই API অনেকটা রিডাক্সের মতোই কাজ করে। তবে ঠিক রিডাক্স না, বরং এটার কার্যপ্রণালী অন্যরকম।
আমরা রিঅ্যাক্ট এ সাধারণত একটা কম্পোনেন্ট থেকে আরেকটা কম্পোনেন্ট এ ডাটা সেন্ড করি। সেক্ষেত্রে একটা কম্পোনেন্ট এর ডাটা আরেকটা চাইল্ড কম্পোনেন্ট এ প্রপস হিসাবে পাঠাতে হয়। অনেকসময় এরকম সিচুয়েশন আসে যে আমাদের মেইন কম্পোনেন্ট যেখানে আপনার ডাটা রয়েছে সেখান থেকে চাইল্ড কম্পোনেন্ট অনেক লেভেল নিচে থাকে। মানে ঐ ডাটাওয়ালা কম্পোনেন্ট এর আরেকটা চাইল্ড কম্পোনেন্ট আছে, আবার সেই চাইল্ড কম্পোনেন্ট এর আবার আরেকটা চাইল্ড কম্পোনেন্ট আছে। এভাবে করতে করতে অনেকগুলা চাইল্ড থাকতে পারে। এখন আমরা মেইন কম্পোনেন্ট বা আমরা যেটাকে বলি টপ লেভেল কম্পোনেন্ট থেকে ডাটা অনেক লেভেল নিচের কোনো চাইল্ড কম্পোনেন্ট এ নিতে চাই, তাহলে আমাদের সেই চাইল্ড কম্পোনেন্ট এর প্যারেন্ট এবং সেই প্যারেন্ট এর প্যারেন্ট এভাবে করতে করতে ডাটাওয়ালা কম্পোনেন্ট এ বা টপ লেভেল কম্পোনেন্ট পর্যন্ত সবগুলার হেল্প নিতে হবে ডাটা পাস করার জন্যে। এটাকে খুড়তে খুড়তে ডাটা নেওয়ার মতো বলা যায়। এরকম সিচুয়েশনে আমরা রিডাক্স ইউজ করি সাধারণত। বা সিচুয়েশান এর চেয়েও জটিল হতে পারে। সেক্ষেত্রে আমরা এরকম গ্লোবাল স্ট্যাট রাখি যেটা পরে যেকোনো চাইল্ডই চাইলে অ্যাক্সেস করতে পারে, খুড়ে খুড়ে সব কম্পোনেন্ট এ প্রপস হিসাবে পাস করে ডাটা নিতে হয় না।
রিঅ্যাক্ট এর Context API সেইম এভাবেই কাজ করে। এটাও একদম টপ লেভেলে একটা স্ট্যাট তৈরী করে। এবং আপনি পরে চাইলে যেকোনো চাইল্ড কম্পোনেন্টই সেই ডাটা অ্যাক্সেস করতে পারবেন, পেরেন্ট কম্পোনেন্টকে কোনোরকম বিরক্ত না করেই। এবং এটা অনেক সিম্পল। রিডাক্সের মতো এতো ঝামেলাপূর্ণ না, তবে রিডাক্স কিছু কাজের জন্য স্পেশাল, তাই এই API রিডাক্স এর পরিপূরক নয়, মনে রাখবেন এটা রিডাক্সকে রিপ্লেস করতে পারবে না। তবে আমরা বেশীরভাগ ক্ষেত্রে রিডাক্স যে কাজে ইউজ করি সেগুলোর সমাধান দিতে পারবে হয়তো অনেকক্ষেত্রে।
আপনার যদি অলরেডি রিঅ্যাক্ট নিয়ে এক্সপেরিয়েন্স থাকে তাহলে আমার লেখা ইজিলিই বুঝতে পারবেন। নতুব হয়তো বুঝতে পারবেন না, কারণ এটা অনেকটা রাফ করে লিখা।
প্রথমে ধরে নিলাম আপনার প্রোজেক্ট সেটাপ করা আছে, বা অলরেডি করা কোনো প্রোজেক্টে নতুন এই API ইউজ করতে চাচ্ছেন। আগে শিউর হোন রিঅ্যাক্ট v16.3.0 বা তার উপরের ভার্শন নিয়ে কাজ করছেন, নতুবা এই নতুন API কাজ করবে না।
এবার একদম টপ লেভেল কম্পোনেন্ট এ গিয়ে একটা কন্টেক্সট তৈরী করতে হবে যেটা রিঅ্যাক্ট এর সাথেই আছে নতুন ভার্শনে।
const MyContext = React.createContext();
এখন আপনার টপ লেভেল কম্পোনেন্ট এই MyContext
এর ভিতরে যাবে। আপনি চাইলে যেকোনো নামই ইউজ করতে পারবেন। ধরি একদম টপে আপনার App
কম্পোনেন্ট আছে।
এখন জাস্ট আপনার সেই টপ লেভেল কম্পোনেন্টটাকে MyContext
দিয়ে বেঁধে দিতে হবে। এখন MyContext
এ আপনার দুইধরনের ইলিমেন্ট থাকতে পারে। একটা ইলিমেন্ট ডাটা দিবে যাকে এখানে Porvider
বলা হয়, আর আরেক ধরণের ইলিমেন্ট যে ডাটা নিবে MyContext
থেকে, তাদেরকে Consumer
বলা হয়। তো আপনি এখানে ডাটা দিবেন, মানে আপনার এই টপ লেভেল ইলিমেন্ট ডাটা প্রোভাইড করবে। তাই এটা হবে Provider
। তাই আপনাকে এখানে ইউজ করতে হবে MyContext.Provider
। …
এগুলো হচ্ছে আপনার এই টপ লেভেল কম্পোনেন্ট এর চাইল্ড কম্পোনেন্ট। এখন এই চাইল্ডগুলা এই কন্টেক্সট থেকে ডাটা নিতে পারবে।
class App extends React.Component {
render() {
return (
<MyContext.Provider>
<div className="App">
...
</div>
</MyContext.Provider>
);
}
}
এখানে কিছু মিসিং হচ্ছে। হ্যাঁ, আমরা ডাটাই দেইনি। তাই এখন ডাটা পাস করতে হবে MyContext.Provider
এ। প্রথমে খুবই সিম্পল উদাহরণ নিবো যাতে বুঝতে সুবিধা হয়। নিচে এভাবে value
এর ভিতরে একটা সিম্পল স্ট্যাটিক ডাটা পাস করলাম।
class App extends React.Component {
render() {
return (
<MyContext.Provider value="I am the hero">
<div className="App">
...
</div>
</MyContext.Provider>
);
}
}
এভাবে চাইল অবজেক্ট, লোকাল স্ট্যাট, ফাংশনও পাস করতে পারবেন। আশা করি ঐগুলাতে ঝামেলা হবে না, বুঝতে পারবেন। এগুলো নরমাল রিঅ্যাক্ট এর ফাংশানালিটির মতোই।
এখন ধরি এই কম্পোনেন্ট এর একটা চাইল্ড কম্পোনেন্ট আছে। আবার সেই চাইল্ড এরও আবার আরেকটা চাইল্ড আছে। এখন আমি সেই শেষের চাইল্ড থেকে ডাটা অ্যাক্সেস করতে চাচ্ছি, মাঝখানের চাইল্ডটাকে কোনোরকম বিরক্ত না করেই।
(দাদু) টপ লেভেলে কম্পোনেন্টঃ
class App extends React.Component {
render() {
return (
<MyContext.Provider value="I am the hero">
<div className="App">
<ChildOfApp />
</div>
</MyContext.Provider>
);
}
}
(বাবা) টপ লেভেলের চাইল্ডঃ
const ChildOfApp = () => {
return (
<div>
<AnotherCompo />
</div>
)
}
(আমি) চাইল্ডেরও চাইল্ডঃ
const AnotherCompo = () => {
return (
....
)
}
এখন এখানে আমার আছে ডাটা আনতে চাচ্ছি দাদু থেকে। কিন্তু বাবাকে কোনোরকম বিরক্ত না করে। নরমালি রিডাক্স আর এই নতুন Context API ছাড়া বাবাকে ডিস্টার্ব করা লাগতো। কিন্তু নতুন এই API তে আমরা জাস্ট MyContext
দিয়ে এটাকে বেঁধে দিয়ে এটা থেকেই ডাটা অ্যাক্সেস করতে পারবো। উপরে বলেছিলাম, যে ডাটা দেয় সে Provider
আর যে ডাটা নেয় সে Consumer
। তাহলে বুঝতে পারছেন আমি কনজিউমার এখানে। তাই আমাকে এখানে MyContext.Consumer
দিয়ে বাঁধতে হবে।
const AnotherCompo = () => {
return (
<MyContext.Consumer>
...
</MyContext.Consumer>
)
}
এখন ভিতরে আপনি একটা ফাংশন নিতে পারবেন যেটার আর্গুমেন্ট এ আপনার ডাটা থাকবে। মানে আপনি যে ডাটা দাদু থেকে পাঠিয়েছেন সেটা আপনার কাছে চলে আসবে এর ভিতরে নেওয়া ফাংশনের আর্গুমেন্ট হিসেবে। তাই ফাংশন নিলেই আপনি আর্গুমেন্ট এ ডাটা রিসিভ করতে পারছেন। এবং সেই ফাংশনে JSX
দিয়ে সেই ডাটা অ্যাক্সেস করতে পারবেন নরমালি।
const AnotherCompo = () => {
return (
<MyContext.Consumer>
{(context) => {
return (
<p>Value: {context}</p>
)
}}
</MyContext.Consumer>
)
}
ব্যাস এতোই সিম্পল রিঅ্যাক্ট এর নতুন Context API, আপনার কাজ শেষ। এবার চাইলে এগুলোতে আপনে সহজেই স্ট্যাট পাস করা থেকে, ফাংশনও পাস করতে পারবেন। ফাংশন মডিফাই করে দাদুর স্ট্যাট বা টপ লেভেল এর ডাটাও ও চ্যাঞ্জ করতে পারবেন।
সিম্পল এই উদাহরণটা আমার কোডপেন থেকে দেখতে পারবেন…
আজকে এই পর্যন্তই। আমি পরে আরো বিস্তারিত লিখবো। তবে আশা করি যারা অলরেডি রিঅ্যাক্ট নিয়ে কাজ করে তারা ইজিলিই ধরে ফেলতে পারবেন রিঅ্যাক্ট এর এই নতুন Context API