SolidJS 2.0 একটি নেটিভ async-data মডেল নিয়ে এসেছে যা একটি কম্পোনেন্টকে একটি promise-কে অন্য যেকোনো reactive value-এর মতো ব্যবহার করতে দেয়, এবং এটি React ডেভেলপাররা Suspense এবং hooks-এর ক্ষেত্রে যে রেন্ডারিংয়ের ধারাবাহিকতা (cascade of re-renders) দেখেন, তা ছাড়াই সম্পন্ন করে। এই পরিবর্তনটি গুরুত্বপূর্ণ কারণ এটি ডেটা রিফ্রেশ হওয়ার সময় UI স্ক্রিনে বজায় রাখে, অপ্রয়োজনীয় কোড (boilerplate) কমায় এবং React টিমগুলোর জন্য তাদের ডেটা-ফেচিং কোড Solid-এ স্থানান্তরের একটি সুনির্দিষ্ট পথ তৈরি করে।
কেন Solid-এর async মডেলটি আলাদা মনে হয়
React-এ, যে কম্পোনেন্টের ডেটা প্রয়োজন সেটি সাধারণত একটি hook (প্রায়শই একটি কাস্টম hook) কল করে যা একটি promise-এর মতো অবজেক্ট রিটার্ন করে, তারপর promiseটি resolve হওয়ার সময় একটি fallback দেখানোর জন্য UI-কে <Suspense> দিয়ে মুড়িয়ে (wrap) দেয়। প্রতিবার যখন promiseটি settle হয়, React একটি re-render শিডিউল করে; যদি একই কম্পোনেন্ট পরে পুনরায় ডেটা ফেচ (refetch) করে, তবে ইতিমধ্যে দৃশ্যমান কন্টেন্টের ওপর fallback-টি হঠাৎ করে ভেসে উঠতে পারে।
Solid এই নিয়মটি বদলে দিয়েছে। একটি promise হলো কেবল একটি value যা reactive graph পর্যবেক্ষণ করে। যখন কোনো computation সেই value-টি পড়ে, graph-টি সেই রিড (read) প্রক্রিয়াটি ততক্ষণ স্থগিত রাখে যতক্ষণ না promiseটি resolve হয়, কিন্তু বাকি UI রেন্ডার অবস্থায় থাকে। প্রথমবার যখন একটি কম্পোনেন্ট mount হয়, তখন একটি <Loading> boundary একটি fallback দেখাতে পারে; এরপর, নতুন ডেটা না আসা পর্যন্ত একটি refetch বিদ্যমান DOM-কে অপরিবর্তিত রাখে। কম্পোনেন্টের ভেতরে কোনো স্পষ্ট “await” নেই, কোনো createResource নেই, এমনকি কোনো ম্যানুয়াল state toggle-ও নেই।
মূল primitives
<Loading>boundary – এটি React-এর<Suspense>-এর বিকল্প। এটি কেবল প্রাথমিক লোড হওয়ার সময় একটি fallback দেখায়। প্রথমবার paint হওয়ার পর, একটি pending read UI-কে প্রতিস্থাপন করে না; নতুন value resolve না হওয়া পর্যন্ত পুরনো কন্টেন্টটি থেকে যায়। নির্দিষ্ট কোনো refetch-এর সময় স্পিনার (spinner) দেখাতে একটিonprop ব্যবহার করুন।<Reveal>component – একাধিক<Loading>boundary একসাথে কীভাবে প্রদর্শিত হবে তা নিয়ন্ত্রণ করে। আপনি বেছে নিতে পারেন:- Sequential: DOM অর্ডার অনুযায়ী boundary-গুলো একে একে প্রদর্শিত হয়।
- Together: যখন সব ডেটা প্রস্তুত হয়, তখন সবগুলো একসাথে প্রদর্শিত হয়।
- Natural: প্রতিটি boundary তার নিজস্ব ডেটা পাওয়ার সাথে সাথেই প্রদর্শিত হয়।
isPendingsignal – একটি নির্দিষ্ট read চলাকালীন এটিtrueরিটার্ন করে। মূল কন্টেন্ট দৃশ্যমান থাকা অবস্থায় একটি পাতলা লোডিং বার বা সূক্ষ্ম অ্যানিমেশন দেখানোর জন্য এটি ব্যবহার করুন, যা আপনাকে বিনামূল্যে “stale-while-revalidate” সুবিধা প্রদান করে।actiongenerator – এটি React-এর mutable-state আপডেটগুলোর বিকল্প। একটিaction(function*…)আশাবাদীভাবে (optimistically) UI আপডেট করতে পারে, সার্ভার রেসপন্সের জন্যyieldকরতে পারে এবং promiseটি resolve হলে ফলাফলটি reconcile করতে পারে। এতে UI তাৎক্ষণিক মনে হয় এবং reconciliation ধাপটি primitives-এর মধ্যেই বিল্ট-ইন থাকে।
কীভাবে এই অংশগুলো React কনসেপ্টের সাথে মানানসই
| বৈশিষ্ট্য | React পদ্ধতি | Solid 2.0 পদ্ধতি |
|---|---|---|
| Data fetching | use() (experimental) অথবা third-party hooks; ফলাফল <Suspense> দিয়ে মোড়ানো থাকে |
createMemo (বা অনুরূপ) যা একটি promise রিটার্ন করে; সরাসরি JSX-এ পড়া হয় |
| Loading UI | প্রতিবার refetch-এর সময় <Suspense> পুনরায় fallback ট্রিগার করতে পারে |
কেবল প্রথম লোডের সময় <Loading>; refetch পুরনো UI বজায় রাখে |
| Refreshing | UI আপডেট বিলম্বিত করতে useTransition |
UI পরিবর্তন না করেই isPending দিয়ে pending read-এর সংকেত দেয় |
| Mutations | useState/useReducer + async calls, যা প্রায়শই কাস্টম action-এর মাধ্যমে মোড়ানো থাকে |
বিল্ট-ইন optimistic handling সহ action(function*…) |
এর ব্যবহারিক ফলাফল হলো, React যে বিষয়গুলোকে আলাদা hook হিসেবে বিবেচনা করে, Solid সেগুলোকে এর মূল reactivity engine-এর মধ্যেই বিল্ট-ইন করে রেখেছে।
ধাপে ধাপে মাইগ্রেশন গাইড
- ডেটা সোর্স শনাক্ত করুন – React-এ আপনার সম্ভবত
const data = useMyFetch(url)থাকে। Solid-এ এটি একটি memo দিয়ে প্রতিস্থাপন করুন যা promise রিটার্ন করে:const data = createMemo(() => fetch(url).then(r => r.json()))। - টপ-লেভেল কম্পোনেন্টটি র্যাপ (wrap) করুন – যদি promiseটি resolve হওয়ার আগে কম্পোনেন্টটি রেন্ডার হয়, তবে এটিকে
<Loading fallback={<Spinner/>}>…</Loading>দিয়ে ঘিরে রাখুন। fallback-টি শুধুমাত্র প্রথম মাউন্টের (mount) সময় দেখা যাবে। - প্রতিবার রি-ফেচ করার সময় স্পিনার ব্যবহারের পরিবর্তে পরিবর্তন করুন – যেখানে আপনি আগে একটি loading flag টগল করতেন, এখন সেখানে
isPending(data)পড়ুন। বিদ্যমান UI স্ক্রিনে থাকা অবস্থায় একটি সূক্ষ্ম ইন্ডিকেটর (indicator) রেন্ডার করতে সেই boolean ব্যবহার করুন। - optimistic updates কনভার্ট করুন – যদি আপনার কাছে একটি async কলের আগে
setState(prev => ({...prev, optimisticValue}))থাকতো, তবে সেটিকে এভাবে পুনরায় লিখুন:const update = action(function* (newValue) { state = newValue; const server = yield fetch(...); state = reconcile(server); });। জেনারেটরটি সার্ভার রেসপন্স না করা পর্যন্ত কন্ট্রোল ধরে রাখে, তারপর স্বয়ংক্রিয়ভাবে রিঅ্যাক্টিভ গ্রাফ আপডেট করে। - একাধিক async অংশ হ্যান্ডেল করুন – প্রয়োজন অনুযায়ী
<Loading>বাউন্ডারিগুলো নেস্ট (nest) করুন, তারপর তারা একসাথে নাকি একে একে আসবে তা নির্ধারণ করতে একটি<Reveal>র্যাপার যোগ করুন। এটি সেই প্যাটার্নগুলোকে প্রতিস্থাপন করে যেখানে React ডেভেলপাররা জটিল state চেক ব্যবহার করে একাধিক<Suspense>কম্পোনেন্ট পর্যায়ক্রমে দেখাতেন। - ফ্লো (flow) পরীক্ষা করুন – যেহেতু Solid promise resolution-এর সময় পুনরায় রেন্ডার (re-render) হয় না, তাই UI আপডেটগুলো আপনার প্রত্যাশা অনুযায়ী হচ্ছে কি না তা যাচাই করে নিন। রিঅ্যাক্টিভ গ্রাফ স্বয়ংক্রিয়ভাবে পরিবর্তনগুলো ছড়িয়ে দেয়; অতিরিক্ত
useEffectকলের প্রয়োজন নেই।
যা এখনও পরিবর্তনশীল
Solid 2.0-এর async API বর্তমানে বিটা (beta) পর্যায়ে আছে। স্ট্যাবল রিলিজের আগে <Loading> এবং action-এর মতো নামগুলো পরিবর্তিত হতে পারে এবং ডকুমেন্টেশন এখনও বিবর্তিত হচ্ছে। মূল ধারণাটি—promise-কে রিঅ্যাক্টিভ ভ্যালু হিসেবে বিবেচনা করা—অপরিবর্তিত রয়েছে, তবে লাইব্রেরিটি স্থিতিশীল হওয়ার সাথে সাথে শুরুর দিকের ব্যবহারকারীদের সামান্য ব্রেকিং চেঞ্জ (breaking changes) আশা করা উচিত।
কারা উপকৃত হবেন
- প্রচুর ডেটা ফেচিং করা React টিম – এক্সটার্নাল স্টেট লাইব্রেরির প্রয়োজনীয়তা হ্রাস এবং বিল্ট-ইন stale-while-revalidate প্যাটার্ন বান্ডেল সাইজ কমাতে পারে এবং কোডবেস সহজ করতে পারে।
- পারফরম্যান্স-কেন্দ্রিক অ্যাপ – প্রতিবার ফেচ করার সময় সম্পূর্ণ কম্পোনেন্ট রেন্ডার হওয়া এড়িয়ে Solid আরও মসৃণ ভিজ্যুয়াল আপডেট প্রদান করে, বিশেষ করে লো-এন্ড ডিভাইসে।
- যারা “flash of spinner” নিয়ে বিরক্ত –
<Loading>বাউন্ডারির “first-load-only” আচরণটি ইতিমধ্যে দৃশ্যমান কন্টেন্টের ওপর স্পিনার ফ্ল্যাশ করার সাধারণ বিরক্তি দূর করে।
সম্ভাব্য অসুবিধাগুলো
- বিটা স্ট্যাটাস – API স্থিতিশীল না হওয়া পর্যন্ত, দীর্ঘমেয়াদী প্রজেক্টগুলোর পরবর্তীতে মাইগ্রেশন প্রচেষ্টার জন্য বাজেট রাখা প্রয়োজন হতে পারে।
পরবর্তীতে যা খেয়াল রাখতে হবে
<Loading> বা action-এর যেকোনো রিনেমের (renaming) জন্য অফিসিয়াল চেঞ্জলগের (changelog) দিকে নজর রাখুন।
মূল কথা: SolidJS 2.0 আপনাকে promise-কে ফার্স্ট-ক্লাস রিঅ্যাক্টিভ ভ্যালু হিসেবে ব্যবহার করতে দেয়, যা ডেটা রিফ্রেশ হওয়ার সময় UI-কে স্থির রাখে এবং React-স্টাইল হুক-এর একটি সম্পূর্ণ সেটের প্রয়োজনীয়তা দূর করে। যারা রেন্ডার-কেন্দ্রিক মডেল থেকে বেরিয়ে আসতে প্রস্তুত, তাদের জন্য মাইগ্রেশন পথটি স্পষ্ট, পারফরম্যান্সের সুবিধাটি দৃশ্যমান এবং একমাত্র প্রকৃত ঝুঁকি হলো বিটা-পর্যায়ের সাধারণ অনিশ্চয়তা।
