fate: کلاینت داده مدرن برای React
خلاصهٔ کاملتر
fate یه کتابخانه دادهفچینگ برای React هست که الهامگرفته از Relay و GraphQL طراحی شده. ایده اصلیش اینه که همه مزایای Relay — مثل fragment composition، کش نرمالشده و data masking — رو بدون نیاز به GraphQL و زبان کوئری اختصاصیش در دسترس بذاره. اگه تیمتون از tRPC یا یه RPC type-safe دیگه استفاده میکنه و نمیخواد هزینه migration به GraphQL رو بپردازه، fate میتونه گزینه جالبی باشه.
مفهوم اصلی fate، view هست — معادل fragment در GraphQL. هر کامپوننت یه view تعریف میکنه که دقیقاً مشخص میکنه به چه فیلدهایی نیاز داره. fate این viewها رو از تمام درخت کامپوننتها جمع میکنه و همه رو در یه درخواست شبکه ارسال میکنه. این یعنی نه waterfall داریم، نه overfetch، نه دادههای اضافه.
برای استفاده، ابتدا یه view تعریف میکنیم و بعد با هوک useView داده رو در کامپوننت میخونیم:
export const PostView = view<Post>()({
content: true,
id: true,
title: true,
});
export const PostCard = ({ post: postRef }: { post: ViewRef<'Post'> }) => {
const post = useView(PostView, postRef);
return <Card><h2>{post.title}</h2><p>{post.content}</p></Card>;
};یکی از قابلیتهای کلیدی fate، ترکیبپذیری view هاست. میشه یه UserView جداگانه تعریف کرد و اون رو داخل PostView ترکیب کرد؛ دقیقاً مثل fragment spread در GraphQL. کامپوننت UserCard فقط به دادههایی که خودش انتخاب کرده دسترسی داره و داده بقیه viewها ازش پنهانه — این همون data masking هست که از coupling تصادفی بین کامپوننتها جلوگیری میکنه.
برای دریافت داده از سرور، هوک useRequest استفاده میشه. این هوک در ریشه اپ تعریف میشه و مشخص میکنه به چه دادههایی نیاز داریم. React Suspense مدیریت loading state رو به عهده میگیره و خطاها هم به error boundary بالادستی bubble up میکنن — دیگه نیازی به منطق دستی loading/error نیست.
امکانات دیگه fate شامل ایناست: optimistic updates برای mutation (اگه درخواست fail بشه، کش به حالت قبل برمیگرده)، pagination با cursor-based list، Live Views از طریق Server-Sent Events برای آپدیت real-time، و یه کش نرمالشده که از داده تکراری و stale جلوگیری میکنه. fate الان در مرحله آلفا هست و هنوز production-ready نیست.
نکات کلیدی:
- fate ایدههای Relay رو بدون GraphQL و با TypeScript معمولی پیاده میکنه
- هر کامپوننت داده موردنیازش رو با «view» اعلام میکنه؛ fate همه viewها رو در یه درخواست ادغام میکنه
- data masking اطمینان میده هر کامپوننت فقط به دادههای خودش دسترسی داره
- پشتیبانی از Suspense، optimistic updates، pagination و Live Views
- سازگار با tRPC و سایر RPC frameworkهای type-safe
- فعلاً در مرحله آلفاست و برای پروداکشن توصیه نمیشه




