داخل ریاکتیویتی TanStack Table V9
خلاصهٔ کاملتر
نویسنده با یه وضعیت آشنا شروع میکنه: یه دیتاگرید که کمکم خودش تبدیل به یه اپلیکیشن کوچیک میشه؛ یه ستون ویجت انتخاب ردیف داره، یکی ادیتور inline و بالای جدول هم شمارندهٔ ردیفهای انتخابشده. وقتی انتخاب عوض میشه فقط همون ویجت و شمارنده باید آپدیت بشن، نه بقیهٔ سلولها و کنترلهای صفحهبندی. با اضافهشدن جستوجو و مخصوصاً ریسایز ستون، کارایی رندر واقعاً مهم میشه.
تو Table V8 هسته یه نمونهٔ پایدار از جدول میساخت و آداپتر هر فریمورک با setOptions و setState اون نمونه رو با استیت فریمورک هماهنگ نگه میداشت. این قرارداد هسته رو قابلحمل نگه داشت، ولی فریمورک نمیدید یه فراخوانی مثل table.getRowModel() دقیقاً چه استیت، آپشن، ردیف یا سلولی رو خونده؛ پس هر ارتباطی بین اون خوندنها و چرخهٔ رندر باید از بیرون و توسط آداپتر ساخته میشد.
به گفتهٔ نویسنده، اولین تجربهاش تو آداپتر انگولار یه Proxy دور نمونهٔ جدول بود که متدهای get* رو داخل computed میپیچید تا انگولار وابستگیای برای ردیابی داشته باشه. جواب داد ولی مرزش پهن بود، و بعدتر React Compiler هم همین مشکل رو لو داد: کامپوننت یه row پایدار میگرفت در حالی که row.getIsSelected() زیرش عوض میشد و کامپایلر JSX کششده رو دوباره استفاده میکرد.
قدم بعدی رپکردن خود متدهای table و row و cell بود، ولی حجم کار تقریباً با R×C×N رشد میکرد، در حالی که همهٔ اون متدها فقط یه مجموعهٔ کوچیک از استیت و آپشن رو میخوندن. برای همین مرز ریاکتیو رفت پایینتر: اول TanStack Store وارد هسته شد، بعد نسخهٔ سیگنالمحورش با createStore و createAtom، و بعد آپشنها هم با optionsStore وارد گراف شدن تا تغییر چیزی مثل enableRowSelection باعث بشه row.getCanSelect() مقدار تازه رو ببینه.
در نهایت اسنپشات استیت به اتم جدا برای هر فیچر شکسته شد و هستهٔ Table فقط به یه قرارداد کوچیک اتم وابسته موند:
interface TableReactivityBindings {
createWritableAtom: <T>(value: T) => Atom<T>
createReadonlyAtom: <T>(fn: () => T) => ReadonlyAtom<T>
batch: (fn: () => void) => void
schedule: (fn: () => void) => void
untrack: <T>(fn: () => T) => T
}ریاکت این قرارداد رو با اتمهای TanStack Store پیاده میکنه و انگولار، سالید و ویو با پریمیتیوهای بومی خودشون؛ امبر هم با @tracked و @cached همین کارو کرده. برای کاربر، کد اپلیکیشن تقریباً دستنخورده میمونه: تو آداپترهای سیگنالمحور کافیه متد رو داخل یه کامپوننت یا computed صدا بزنی تا وابستگیهاش ثبت بشه، ولی تو ریاکت چون خوندن سیگنال موقع رندر جمع نمیشه، رندر دانهریز با selectorها و Subscribe انتخابیه. نسخهٔ ۹ با ۹ آداپتر فریمورک میآد.
نکات کلیدی:
- هر فیچر (صفحهبندی، انتخاب ردیف، سایز ستون، فیلتر) اتم ریاکتیو خودشو داره.
- آپشنها هم از طریق optionsStore وارد گراف ریاکتیو شدن.
- هسته فقط به قرارداد Atom/ReadonlyAtom وابستهست، نه به یه رانتایم خاص.
- تو ریاکت رندر دانهریز اختیاریه؛ با selector و Subscribe فعال میشه.
- Table V9 با ۹ آداپتر رسمی، از جمله امبر، پریکت و آلپاین میآد.




