الترحيل من React

يقارب Carats React عن قصد، لذا تنتقل معظم شيفرة المكونات مباشرة. والفروق أدناه هي التي تكسر الترحيل فعلًا.

المفهومReactCarats
بيئة التشغيل‏React وReact DOM وDOM افتراضي‏JJSX فقط؛ المكونات دوال تُعيد HTML
الحالة‏useState يُعيد تصيير المكوّن‏use يخزّن قيمة؛ وDOM يُحدَّث يدويًا
الآثار‏useEffect مع مصفوفة اعتماديات‏afterMount (بعد التحميل) أو beforeMount (فورًا)، بلا اعتماديات
معالجات الأحداث<button onClick={fn}>‏addEventListener داخل استدعاء خطاف
التوجيهموجّه نظام ملفات بتخطيطات ومسارات متداخلةخريطة ‏defineFacets‎، تُركَّب باستيراد تخطيط
بيانات الخادم‏getServerSideProps على الصفحةدالة خادمية لكل مسار مع غلاف ‏Burnish
ترويسة المستند‏next/head أو تصدير البيانات الوصفية في الإطار‏this.head داخل مكوّن دالة
بيانات المكوّن الوصفية‏Component.displayName وmemo وcontext‏defaultProps على المكوّن؛ بلا context ولا memo
التنسيق‏CSS-in-JS أو أصناف مساعدة‏SASS محدود النطاق يستورد رموز تصميم مشتركة
الأنواعواجهات مُستوردة لكل ملفواجهات DTO عامة من ‎src/dto‎

معالجات الأحداث

نموذج الأحداث هو التغيير الذي يكسر الترحيل أكثر من غيره، لذا يجدر بالدقة في وصفه.

// React
<button onClick={() => setOpen(!open)}>Toggle</button>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
// Carats
import { use, afterMount } from '@carats/hooks';

export default function Toggle() {
    const open = use(false);

    afterMount(() => {
        const button = document.getElementById('toggle');

        const stop = open.subscribe((value) => {
            button?.setAttribute('aria-expanded', String(value));
        });

        const onClick = () => open.set(!open.get());
        button?.addEventListener('click', onClick);

        return () => {
            stop();
            button?.removeEventListener('click', onClick);
        };
    });

    return <button id="toggle" aria-expanded="false">Toggle</button>;
}

الحالة

يصبح ‏`useState`‎ هو ‏`use`‎، وكل تصيير كان React سيتولاه يصبح كتابة DOM صريحة. أما الحالة التي كانت محلية لمكوّن فتبقى كما هي في الجوهر: استدعِ ‏`use`‎ في المستوى الأعلى من المكوّن، واقرأها بـ ‏`get`‎، واكتب بـ ‏`set`‎.

التوجيه

ينهار موجّه نظام الملفات إلى كائن واحد. يصبح كل مسار مُدخلًا في ‏`defineFacets`‎، وتصبح التخطيطات المتداخلة استيرادًا صريحًا. ولأن كائن الأوجه مشترك، فالمسار الغائب عنه غائب عن العميل وعن الخادم معًا، وهذا يُزيل فئة كاملة من الأخطاء.

بيانات الخادم

يصبح ‏`getServerSideProps`‎ دالةً خادمية، وتصبح الصفحة مُبرَزة. وتبقى صيغة الدالة بالشكل نفسه: الطلب دخلًا والبيانات خروجًا.

// React / Next.js
export async function getServerSideProps({ params }) {
    return { props: { symbol: params.symbol } };
}
// Carats
export default culet<TradeData>('/trade/:symbol', async (req) => {
    return { symbol: req.params.symbol.toUpperCase() };
});
// Carats page
export default Burnish<TradeData>(function (data) {
    return <h1>{data.symbol}</h1>;
});

ترويسة المستند

يصبح تصدير البيانات الوصفية ‏`this.head`‎، ويجب أن يكون المكوّن تصريح ‏`function`‎ كي يوجد ‏`this`‎. ويمكن لمكوّن يكون أصلًا دالة سهم أن يبقى كذلك، على حساب أنه لا يساهم بوسوم head.

التنسيق

لا يوجد نظير لـ CSS-in-JS. يستورد كل مكوّن ملف SASS، ويستورد ذلك الملف ‎`base.sass`‎ من أجل رموز التصميم، وتعيش الرموز في المستوى الأعلى من ورقة الأنماط العامة تلك.

قائمة تدقيق الترحيل

  1. احذف react وreact-dom وكل اعتمادية تخص React وحدها.
  2. استبدل سمات الأحداث بـ addEventListener داخل استدعاء afterMount أو beforeMount.
  3. حوّل كل مسار قائم على ملفات إلى مُدخل في خريطة الأوجه، واستورد تخطيطًا مشتركًا صراحةً.
  4. انقل أجسام getServerSideProps إلى الدوال الخادمية، وغلِّف الصفحة بـ Burnish.
  5. انقل useState إلى use، وأضف تحديث DOM اليدوي الذي كان إعادة التصيير يتولاه.
  6. انقل تصدير head إلى this.head في مكوّن دالة.
  7. استبدل CSS-in-JS بملفات SASS يستوردها كل مكوّن.