> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# أفضل الممارسات

تحدد هذه الوثيقة أفضل الممارسات التي يجب اتباعها عند العمل في الواجهة الأمامية.

## إدارة الحالة

تقوم React و Jotai بإدارة الحالة في قاعدة الشيفرة.

### استخدم ذرات Jotai لتخزين الحالة

من الجيد إنشاء أكبر عدد ممكن من الذرات لتخزين الحالة الخاصة بك.

<Warning>
  من الأفضل استخدام ذرات إضافية بدلاً من محاولة أن تكون مقتضبًا باستخدام تمرير الخصائص.
</Warning>

```tsx theme={null}
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';

export const myAtomState = createAtomState<string>({
  key: 'myAtomState',
  defaultValue: 'default value',
});

export const MyComponent = () => {
  const [myAtom, setMyAtom] = useAtomState(myAtomState);

  return (
    <div>
      <input
        value={myAtom}
        onChange={(e) => setMyAtom(e.target.value)}
      />
    </div>
  );
}
```

### لا تستخدم `useRef` لتخزين الحالة

تجنب استخدام `useRef` لتخزين الحالة.

إذا كنت ترغب في تخزين الحالة، يجب أن تستخدم `useState` أو ذرات Jotai مع `useAtomState`.

انظر [كيفية إدارة إعادة العرض](#managing-re-renders) إذا شعرت أنك بحاجة إلى `useRef` لمنع بعض إعادة العرض من الحدوث.

## إدارة إعادة العرض

يمكن أن تكون إعادة العرض صعبة الإدارة في React.

إليك بعض القواعد التي يجب اتباعها لتجنب إعادة العرض غير الضرورية.

تذكر أنه يمكنك **دائمًا** تجنب إعادة العرض من خلال فهم سببها.

### العمل على المستوى الجذري

تجنب إعادة العرض في الميزات الجديدة أصبح سهلاً الآن عن طريق إزالتها على المستوى الجذري.

يحتوي المكون الجانبي "PageChangeEffect" على "useEffect" واحد فقط يحمل كل المنطق لتنفيذه على تغيير الصفحة.

بهذه الطريقة، تعرف أن هناك مكان واحد فقط يمكنه تحفيز إعادة العرض.

### تفكير دائماً مرتين قبل إضافة `useEffect` في الرمز الخاص بك

وكثيرا ما تكون عمليات إعادة التسليم ناجمة عن `فعالية الاستخدام` غير الضرورية.

يجب أن تفكر فيما إذا كنت بحاجة إلى \`useEffect'، أو إذا كنت تستطيع نقل المنطق في وظيفة معالج الأحداث.

ستجد أنه من السهل عموما نقل المنطق في دالة "handleClick" أو "handleChange".

يمكنك أيضًا العثور عليها في المكتبات مثل Apollo: `onCompleted`، `onError`، إلخ.

### استخدم مكون أخت لاستخراج \`تأثير الاستخدام' أو منطق جلب البيانات

إذا كنت تشعر أنك بحاجة إلى إضافة 'useEffect' في مكون الجذر الخاص بك، فيجب عليك النظر في استخراجه في مكون جانبي.

يمكنك تطبيق نفس الشيء على منطق جلب البيانات، مع الخُطافات Apollo.

```tsx theme={null}
// ❌ Bad, will cause re-renders even if data is not changing,
//    because useEffect needs to be re-evaluated
export const PageComponent = () => {
  const [data, setData] = useAtomState(dataState);
  const [someDependency] = useAtomState(someDependencyState);

  useEffect(() => {
    if(someDependency !== data) {
      setData(someDependency);
    }
  }, [someDependency]);

  return <div>{data}</div>;
};

export const App = () => (
  <PageComponent />
);
```

```tsx theme={null}
// ✅ Good, will not cause re-renders if data is not changing,
//   because useEffect is re-evaluated in another sibling component
export const PageComponent = () => {
  const [data, setData] = useAtomState(dataState);

  return <div>{data}</div>;
};

export const PageData = () => {
  const [data, setData] = useAtomState(dataState);
  const [someDependency] = useAtomState(someDependencyState);

  useEffect(() => {
    if(someDependency !== data) {
      setData(someDependency);
    }
  }, [someDependency]);

  return <></>;
};

export const App = () => (
  <>
    <PageData />
    <PageComponent />
  </>
);
```

### استخدم حالات عائلة الذرات والمحددات

تُعد حالات عائلة الذرات والمحددات طريقة رائعة لتجنّب عمليات إعادة التصيير.

إنها مفيدة عندما تحتاج إلى تخزين قائمة من العناصر.

### يجب ألا تستخدم `React.memo(MyComponent)`

تجنب استخدام `React.memo()` لأنه لا يحل سبب إعادة العرض، بل يكسر سلسلة إعادة العرض، مما قد يؤدي إلى سلوك غير متوقع ويجعل التعليمات البرمجية صعبة التعديل.

### حدد استخدام `useCallback` أو `useMemo`

غالبًا ما لا تكون ضرورية وستجعل التعليمات البرمجية أصعب في القراءة والصيانة لأداء غير ملحوظ.

## Console.logs

تصريحات `console.log` ذات قيمة أثناء التطوير، حيث تقدم رؤى في الوقت الفعلي عن قيمة المتغيرات وتدفق التعليمات البرمجية. ولكن، تركها في التعليمات البرمجية في الإنتاج قد يؤدي إلى عدة مشكلات:

1. **الأداء**: تسجيل كثير قد يؤثر على أداء وقت التشغيل، خاصة في التطبيقات على الجانب العميل.

2. **الأمان**: تسجيل البيانات الحساسة قد يكشف المعلومات الحرجة لأي شخص يقوم بتفتيش وحدة التحكم في المتصفح.

3. **النظافة**: ملء وحدة التحكم بالسجلات قد يحجب التحذيرات أو الأخطاء الهامة التي يحتاج المطورون أو الأدوات إلى رؤيتها.

4. **الاحترافية**: المستخدمون النهائيون أو العملاء الذين يفحصون وحدة التحكم ويجدون الكثير من تصريحات السجلات قد يشككون في جودة وتأنق التعليمات البرمجية.

تأكد من إزالة جميع تصريحات `console.log` قبل دفع التعليمات البرمجية إلى الإنتاج.

## التسمية

### تسمية المتغيرات

يجب أن تعبر أسماء المتغيرات بدقة عن الغرض أو وظيفة المتغير.

#### المشكلة مع الأسماء العامة

الأسماء العامة في البرمجة ليست مثالية لأنها تفتقر إلى التحديد، مما يؤدي إلى الغموض وتقليل قابلية قراءة التعليمات البرمجية. مثل هذه الأسماء تفشل في التعبير عن الغرض من المتغير أو الوظيفة، مما يجعل من الصعب على المطورين فهم نية التعليمات البرمجية دون تحقيق أعمق. يمكن أن يؤدي ذلك إلى زيادة وقت إزالة الأخطاء، وزيادة قابلية التعرض للأخطاء، وصعوبات في الصيانة والتعاون. في الوقت نفسه، تجعل التسمية الوصفية التعليمات البرمجية تفسيرية بذاتها وأسهل في التنقل، مما يعزز جودة التعليمات البرمجية وإنتاجية المطور.

```tsx theme={null}
// ❌ Bad, uses a generic name that doesn't communicate its
//    purpose or content clearly
const [value, setValue] = useState('');
```

```tsx theme={null}
// ✅ Good, uses a descriptive name
const [email, setEmail] = useState('');
```

#### بعض الكلمات يجب تجنبها في أسماء المتغيرات

* dummy

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

يجب أن تبدأ أسماء معالجات الأحداث بكلمة `handle`، بينما يعتبر `on` بادئة تستخدم لتسمية الأحداث في خصائص المكونات.

```tsx theme={null}
// ❌ Bad
const onEmailChange = (val: string) => {
  // ...
};
```

```tsx theme={null}
// ✅ Good
const handleEmailChange = (val: string) => {
  // ...
};
```

## الخصائص الاختيارية

تجنب تمرير القيمة الافتراضية لخاصية اختيارية.

**مثال**

خذ مكون`EmailField` المحدد أدناه:

```tsx theme={null}
type EmailFieldProps = {
  value: string;
  disabled?: boolean;
};

const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
  <TextInput value={value} disabled={disabled} fullWidth />
);
```

**الاستخدام**

```tsx theme={null}
// ❌ Bad, passing in the same value as the default value adds no value
const Form = () => <EmailField value="username@email.com" disabled={false} />;
```

```tsx theme={null}
// ✅ Good, assumes the default value
const Form = () => <EmailField value="username@email.com" />;
```

## المكون كخصائص

حاول قدر الإمكان تمرير المكونات غير المنشأة كمكونات، بحيث يمكن للأطفال تحديد ما يحتاجون لتمريره.

المثال الأكثر شيوعا لذلك هو مكونات الأيقونات:

```tsx theme={null}
const SomeParentComponent = () => <MyComponent Icon={MyIcon} />;

// In MyComponent
const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => {
  const theme = useTheme();

  return (
    <div>
      <MyIcon size={theme.icon.size.md}>
    </div>
  )
};
```

لفهم React أن المكون هو مكون، يجب عليك استخدام PascalCase، للتمكن من معاملته لاحقًا كـ `<MyIcon>`

## تمرير الخصائص: اجعلها محدودة

يشير تمرير الخصائص في سياق React إلى ممارسة تمرير متغيرات الحالة وأدوات تحكمها عبر العديد من طبقات المكونات، حتى لو لم تستخدمها المكونات الوسيطة. رغم أنها تكون ضرورية في بعض الأحيان، إلا أن تمرير الخصائص الزائد يمكن أن يؤدي إلى:

1. **انخفاض القابلية للقراءة**: يمكن أن يصبح تتبع مصدر الخاصية أو مكان استخدامها معقدا في هيكل مكون معقد.

2. **تحديات الصيانة**: قد تتطلب التغييرات في هيكل خاصية أحد المكونات تعديلات في عدة مكونات، حتى لو لم تستخدم الخاصية مباشرة.

3. **تقليل إعادة استخدام المكونات**: يصبح المكون الذي يتلقى الكثير من الخصائص لتمريرها فقط أقل شمولية وأصعب في إعادة استخدامه في سياقات مختلفة.

إذا شعرت أنك تستخدم تمرير الخصائص بشكل مفرط، راجع [أفضل ممارسات إدارة الحالة](#state-management).

## استيرادات

عند الاستيراد، اختر الأسماء المستعارة المتعينة بدلا من تحديد المسارات كاملة أو نسبية.

**الأسماء المستعارة**

```js theme={null}
{
  alias: {
    "~": path.resolve(__dirname, "src"),
    "@": path.resolve(__dirname, "src/modules"),
    "@testing": path.resolve(__dirname, "src/testing"),
  },
}
```

**الاستخدام**

```tsx theme={null}
// ❌ Bad, specifies the entire relative path
import {
  CatalogDecorator
} from '../../../../../testing/decorators/CatalogDecorator';
import {
  ComponentDecorator
} from '../../../../../testing/decorators/ComponentDecorator';
```

```tsx theme={null}
// ✅ Good, utilises the designated aliases
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from 'twenty-ui/testing';
```

## التحقق من المخططات

[Zod](https://github.com/colinhacks/zod) هو مدقق المخططات للكائنات غير المTyped:

```js theme={null}
const validationSchema = z
  .object({
    exist: z.boolean(),
    email: z
      .string()
      .email('Email must be a valid email'),
    password: z
      .string()
      .regex(PASSWORD_REGEX, 'Password must contain at least 8 characters'),
  })
  .required();

type Form = z.infer<typeof validationSchema>;
```

## التغييرات الجذرية

قم دائمًا بإجراء اختبارات يدوية شاملة قبل المتابعة لضمان أن التعديلات لم تسبب تعطيلًا في أماكن أخرى، نظرًا لأن الاختبارات لم تدمج حتى الآن بشكل كبير.
