` كابن أول. لهذين العدّادين عند React نفس «العنوان»: الابن الأول للابن الأول للجذر. هكذا يطابقهما بين التصيير السابق واللاحق، بغض النظر عن هيكلة منطقك.
-## Different components at the same position reset state {/*different-components-at-the-same-position-reset-state*/}
+## مكوّنات مختلفة في نفس الموضع تعيد تعيين الحالة {/*different-components-at-the-same-position-reset-state*/}
-In this example, ticking the checkbox will replace `
` with a ``:
+في هذا المثال، تفعيل المربع يستبدل `` بـ``:
@@ -561,13 +560,13 @@ label {
-Here, you switch between _different_ component types at the same position. Initially, the first child of the `
` contained a `Counter`. But when you swapped in a `p`, React removed the `Counter` from the UI tree and destroyed its state.
+هنا تبدّل بين أنواع مكوّنات _مختلفة_ في نفس الموضع. في البداية، كان الابن الأول للـ`
` يحتوي `Counter`. لكن عند استبداله بـ`p`، أزال React `Counter` من شجرة الواجهة ودمّر حالته.
-When `Counter` changes to `p`, the `Counter` is deleted and the `p` is added
+عندما يتحوّل `Counter` إلى `p`، يُحذف `Counter` ويُضاف `p`
@@ -577,13 +576,13 @@ When `Counter` changes to `p`, the `Counter` is deleted and the `p` is added
-When switching back, the `p` is deleted and the `Counter` is added
+عند العودة، يُحذف `p` ويُضاف `Counter`
-Also, **when you render a different component in the same position, it resets the state of its entire subtree.** To see how this works, increment the counter and then tick the checkbox:
+أيضاً، **عندما تعرض مكوّناً مختلفاً في نفس الموضع، تُعاد تعيين حالة الشجرة الفرعية كاملة.** لرؤية ذلك، زِد العدّاد ثم فعّل المربع:
@@ -672,13 +671,13 @@ label {
-The counter state gets reset when you click the checkbox. Although you render a `Counter`, the first child of the `div` changes from a `section` to a `div`. When the child `section` was removed from the DOM, the whole tree below it (including the `Counter` and its state) was destroyed as well.
+تُعاد تعيين حالة العدّاد عند النقر على المربع. رغم أنك تعرض `Counter`، يتغيّر الابن الأول للـ`div` من `section` إلى `div`. عند إزالة `section` من DOM، دُمّرت الشجرة بأكملها تحتها (بما فيها `Counter` وحالته).
-When `section` changes to `div`, the `section` is deleted and the new `div` is added
+عندما يتحوّل `section` إلى `div`، يُحذف `section` ويُضاف `div` جديد
@@ -688,19 +687,19 @@ When `section` changes to `div`, the `section` is deleted and the new `div` is a
-When switching back, the `div` is deleted and the new `section` is added
+عند العودة، يُحذف `div` وتُضاف `section` جديدة
-As a rule of thumb, **if you want to preserve the state between re-renders, the structure of your tree needs to "match up"** from one render to another. If the structure is different, the state gets destroyed because React destroys state when it removes a component from the tree.
+كقاعدة عامة، **إن أردت الحفاظ على الحالة بين عمليات إعادة التصيير، يجب أن «يتطابق» هيكل شجرتك** من تصيير إلى آخر. إذا اختلف الهيكل، تُدمَر الحالة لأن React يدمّر الحالة عند إزالة مكوّن من الشجرة.
-This is why you should not nest component function definitions.
+لهذا لا يجب تعريف دوال المكوّنات متداخلة.
-Here, the `MyTextField` component function is defined *inside* `MyComponent`:
+هنا، دالة مكوّن `MyTextField` معرّفة *داخل* `MyComponent`:
@@ -735,13 +734,13 @@ export default function MyComponent() {
-Every time you click the button, the input state disappears! This is because a *different* `MyTextField` function is created for every render of `MyComponent`. You're rendering a *different* component in the same position, so React resets all state below. This leads to bugs and performance problems. To avoid this problem, **always declare component functions at the top level, and don't nest their definitions.**
+في كل نقرة على الزر، تختفي حالة الحقل! لأن دالة `MyTextField` *مختلفة* تُنشأ في كل تصيير لـ`MyComponent`. أنت تعرض مكوّناً *مختلفاً* في نفس الموضع، فيعيد React تعيين كل الحالة أسفله. هذا يسبب علل ومشاكل أداء. لتجنّب المشكلة، **عرّف دوال المكوّنات دائماً في المستوى الأعلى، ولا تدخل تعريفاتها.**
-## Resetting state at the same position {/*resetting-state-at-the-same-position*/}
+## إعادة تعيين الحالة في نفس الموضع {/*resetting-state-at-the-same-position*/}
-By default, React preserves state of a component while it stays at the same position. Usually, this is exactly what you want, so it makes sense as the default behavior. But sometimes, you may want to reset a component's state. Consider this app that lets two players keep track of their scores during each turn:
+افتراضياً، يحفظ React حالة المكوّن ما دام في نفس الموضع. غالباً هذا ما تريده، فيكون السلوك الافتراضي منطقياً. لكن أحياناً قد تريد إعادة تعيين حالة مكوّن. انظر هذا التطبيق الذي يتيح للاعبين متابعة نقاطهما في كل دور:
@@ -811,19 +810,19 @@ h1 {
-Currently, when you change the player, the score is preserved. The two `Counter`s appear in the same position, so React sees them as *the same* `Counter` whose `person` prop has changed.
+حالياً، عند تغيير اللاعب، تُحفَظ النقطة. يظهر العدّادان `Counter` في نفس الموضع، فيراهما React كـ*نفس* `Counter` الذي تغيّرت خاصية `person` له.
-But conceptually, in this app they should be two separate counters. They might appear in the same place in the UI, but one is a counter for Taylor, and another is a counter for Sarah.
+لكن مفهومياً، في هذا التطبيق ينبغي أن يكونا عدّادين منفصلين. قد يظهران في نفس مكان الواجهة، لكن أحدهما لتايلور والآخر لسارة.
-There are two ways to reset state when switching between them:
+هناك طريقتان لإعادة تعيين الحالة عند التبديل بينهما:
-1. Render components in different positions
-2. Give each component an explicit identity with `key`
+1. عرض المكوّنات في مواضع مختلفة
+2. إعطاء كل مكوّن هوية صريحة بـ`key`
-### Option 1: Rendering a component in different positions {/*option-1-rendering-a-component-in-different-positions*/}
+### الخيار 1: عرض المكوّن في مواضع مختلفة {/*option-1-rendering-a-component-in-different-positions*/}
-If you want these two `Counter`s to be independent, you can render them in two different positions:
+إن أردت استقلال هذين `Counter`، يمكنك عرضهما في موضعين مختلفين:
@@ -894,42 +893,42 @@ h1 {
-* Initially, `isPlayerA` is `true`. So the first position contains `Counter` state, and the second one is empty.
-* When you click the "Next player" button the first position clears but the second one now contains a `Counter`.
+* في البداية `isPlayerA` هو `true`. فيحتوي الموضع الأول على حالة `Counter`، والثاني فارغ.
+* عند النقر على زر «Next player!» يُفرغ الموضع الأول لكن الثاني يصبح يحتوي `Counter`.
-Initial state
+الحالة الابتدائية
-Clicking "next"
+النقر على «التالي»
-Clicking "next" again
+النقر على «التالي» مرة أخرى
-Each `Counter`'s state gets destroyed each time it's removed from the DOM. This is why they reset every time you click the button.
+تُدمَر حالة كل `Counter` في كل مرة يُزال فيها من DOM. لذلك يُعاد التعيين في كل نقرة على الزر.
-This solution is convenient when you only have a few independent components rendered in the same place. In this example, you only have two, so it's not a hassle to render both separately in the JSX.
+هذا الحل مناسب عندما يكون لديك قليل من المكوّنات المستقلة في نفس المكان. في هذا المثال، لديك اثنان فقط، فلا مشقة في عرضهما منفصلين في JSX.
-### Option 2: Resetting state with a key {/*option-2-resetting-state-with-a-key*/}
+### الخيار 2: إعادة تعيين الحالة بمفتاح `key` {/*option-2-resetting-state-with-a-key*/}
-There is also another, more generic, way to reset a component's state.
+هناك أيضاً طريقة أعم لإعادة تعيين حالة مكوّن.
-You might have seen `key`s when [rendering lists.](/learn/rendering-lists#keeping-list-items-in-order-with-key) Keys aren't just for lists! You can use keys to make React distinguish between any components. By default, React uses order within the parent ("first counter", "second counter") to discern between components. But keys let you tell React that this is not just a *first* counter, or a *second* counter, but a specific counter--for example, *Taylor's* counter. This way, React will know *Taylor's* counter wherever it appears in the tree!
+ربما رأيت `key` عند [عرض القوائم.](/learn/rendering-lists#keeping-list-items-in-order-with-key) المفاتيح ليست للقوائم فقط! يمكنك استخدامها ليميّز React بين أي مكوّنات. افتراضياً، React يستخدم الترتيب داخل الأب («العدّاد الأول»، «العدّاد الثاني») للتمييز. لكن المفاتيح تخبر React أن هذا ليس مجرد عدّاد *أول* أو *ثانٍ*، بل عدّاد محدد—مثلاً عدّاد *تايلور*. هكذا يعرف React عدّاد *تايلور* أينما ظهر في الشجرة!
-In this example, the two `
`s don't share state even though they appear in the same place in JSX:
+في هذا المثال، لا يتشارك وسما `
` في الحالة رغم ظهورهما في نفس المكان في JSX:
@@ -999,7 +998,7 @@ h1 {
-Switching between Taylor and Sarah does not preserve the state. This is because **you gave them different `key`s:**
+التبديل بين تايلور وسارة لا يحفظ الحالة. لأنك **أعطيتهما `key` مختلفين:**
```js
{isPlayerA ? (
@@ -1009,19 +1008,19 @@ Switching between Taylor and Sarah does not preserve the state. This is because
)}
```
-Specifying a `key` tells React to use the `key` itself as part of the position, instead of their order within the parent. This is why, even though you render them in the same place in JSX, React sees them as two different counters, and so they will never share state. Every time a counter appears on the screen, its state is created. Every time it is removed, its state is destroyed. Toggling between them resets their state over and over.
+تحديد `key` يخبر React باستخدام المفتاح نفسه كجزء من الموضع، بدلاً من ترتيبهما داخل الأب. لذلك، رغم عرضهما في نفس المكان في JSX، يراهما React كعدّادين مختلفين ولن يتشاركا الحالة أبداً. في كل مرة يظهر فيها عدّاد، تُنشأ حالته. في كل مرة يُزال، تُدمَر حالته. التبديل بينهما يعيد تعيين الحالة مراراً.
-Remember that keys are not globally unique. They only specify the position *within the parent*.
+تذكّر أن المفاتيح ليست فريدة عالمياً. إنها تحدد الموضع *داخل الأب* فقط.
-### Resetting a form with a key {/*resetting-a-form-with-a-key*/}
+### إعادة تعيين نموذج بمفتاح {/*resetting-a-form-with-a-key*/}
-Resetting state with a key is particularly useful when dealing with forms.
+إعادة تعيين الحالة بمفتاح مفيدة جداً مع النماذج.
-In this chat app, the `
` component contains the text input state:
+في تطبيق المحادثة هذا، يحتوي مكوّن `` على حالة حقل النص:
@@ -1116,17 +1115,17 @@ textarea {
-Try entering something into the input, and then press "Alice" or "Bob" to choose a different recipient. You will notice that the input state is preserved because the `` is rendered at the same position in the tree.
+جرّب إدخال نص ثم اضغط «Alice» أو «Bob» لاختيار مستلم آخر. ستلاحظ أن حالة الحقل تُحفَظ لأن `` يُصيَّر في نفس الموضع في الشجرة.
-**In many apps, this may be the desired behavior, but not in a chat app!** You don't want to let the user send a message they already typed to a wrong person due to an accidental click. To fix it, add a `key`:
+**في كثير من التطبيقات قد يكون هذا السلوك المرغوب، لكن ليس في تطبيق محادثة!** لا تريد أن يرسل المستخدم رسالة كتبها بالفعل إلى شخص خطأ بسبب نقرة خاطئة. لإصلاح ذلك، أضف `key`:
```js
```
-This ensures that when you select a different recipient, the `Chat` component will be recreated from scratch, including any state in the tree below it. React will also re-create the DOM elements instead of reusing them.
+هذا يضمن أنه عند اختيار مستلم مختلف، يُعاد إنشاء مكوّن `Chat` من الصفر، بما في ذلك أي حالة في الشجرة تحته. كما يعيد React إنشاء عناصر DOM بدلاً من إعادة استخدامها.
-Now switching the recipient always clears the text field:
+الآن تبديل المستلم يفرغ حقل النص دائماً:
@@ -1223,24 +1222,24 @@ textarea {
-#### Preserving state for removed components {/*preserving-state-for-removed-components*/}
+#### الحفاظ على الحالة لمكوّنات مُزالة {/*preserving-state-for-removed-components*/}
-In a real chat app, you'd probably want to recover the input state when the user selects the previous recipient again. There are a few ways to keep the state "alive" for a component that's no longer visible:
+في تطبيق محادثة حقيقي، قد تريد استرجاع حالة الحقل عندما يعيد المستخدم اختيار المستلم السابق. هناك طرق للإبقاء على الحالة «حية» لمكوّن لم يعد مرئياً:
-- You could render _all_ chats instead of just the current one, but hide all the others with CSS. The chats would not get removed from the tree, so their local state would be preserved. This solution works great for simple UIs. But it can get very slow if the hidden trees are large and contain a lot of DOM nodes.
-- You could [lift the state up](/learn/sharing-state-between-components) and hold the pending message for each recipient in the parent component. This way, when the child components get removed, it doesn't matter, because it's the parent that keeps the important information. This is the most common solution.
-- You might also use a different source in addition to React state. For example, you probably want a message draft to persist even if the user accidentally closes the page. To implement this, you could have the `Chat` component initialize its state by reading from the [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), and save the drafts there too.
+- يمكنك عرض _كل_ المحادثات بدلاً من الحالية فقط، وإخفاء البقية بـCSS. لا تُزال المحادثات من الشجرة، فتُحفَظ حالتها المحلية. ينجح هذا مع واجهات بسيطة. لكنه قد يبطئ كثيراً إذا كانت الأشجار المخفية كبيرة وفيها الكثير من عقد DOM.
+- يمكنك [رفع الحالة](/learn/sharing-state-between-components) والاحتفاظ بالرسالة المعلّقة لكل مستلم في المكوّن الأب. عندها لا يهم إزالة المكوّنات الأبناء لأن الأب يحتفظ بالمعلومات المهمة. هذا هو الحل الأشيع.
+- قد تستخدم مصدراً آخر إلى جانب حالة React. مثلاً، غالباً تريد بقاء مسودة الرسالة حتى لو أغلق المستخدم الصفحة بالخطأ. لتنفيذ ذلك، يمكن لمكوّن `Chat` أن يهيئ حالته بقراءة [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)، ويحفظ المسودات هناك أيضاً.
-No matter which strategy you pick, a chat _with Alice_ is conceptually distinct from a chat _with Bob_, so it makes sense to give a `key` to the `` tree based on the current recipient.
+أي استراتيجية اخترتها، محادثة _مع أليس_ مفهومياً مختلفة عن محادثة _مع بوب_، فينطقي إعطاء `key` لشجرة `` حسب المستلم الحالي.
-- React keeps state for as long as the same component is rendered at the same position.
-- State is not kept in JSX tags. It's associated with the tree position in which you put that JSX.
-- You can force a subtree to reset its state by giving it a different key.
-- Don't nest component definitions, or you'll reset state by accident.
+- يحتفظ React بالحالة ما دام نفس المكوّن يُصيَّر في نفس الموضع.
+- الحالة لا تُخزَّن في وسوم JSX. إنها مرتبطة بموضع الشجرة حيث وضعت ذلك JSX.
+- يمكنك إجبار شجرة فرعية على إعادة تعيين حالتها بإعطائها مفتاحاً مختلفاً.
+- لا تدخل تعريفات المكوّنات، وإلا أعدت تعيين الحالة عن غير قصد.
@@ -1248,9 +1247,9 @@ No matter which strategy you pick, a chat _with Alice_ is conceptually distinct
-#### Fix disappearing input text {/*fix-disappearing-input-text*/}
+#### إصلاح اختفاء نص الحقل {/*fix-disappearing-input-text*/}
-This example shows a message when you press the button. However, pressing the button also accidentally resets the input. Why does this happen? Fix it so that pressing the button does not reset the input text.
+يعرض هذا المثال رسالة عند الضغط على الزر. لكن الضغط يعيد تعيين الحقل عن غير قصد أيضاً. لماذا؟ أصلحه بحيث لا يعيد الضغط تعيين نص الحقل.
@@ -1299,9 +1298,9 @@ textarea { display: block; margin: 10px 0; }
-The problem is that `Form` is rendered in different positions. In the `if` branch, it is the second child of the ``, but in the `else` branch, it is the first child. Therefore, the component type in each position changes. The first position changes between holding a `p` and a `Form`, while the second position changes between holding a `Form` and a `button`. React resets the state every time the component type changes.
+المشكلة أن `Form` يُصيَّر في مواضع مختلفة. في فرع `if` هو الابن الثاني للـ`
`، وفي فرع `else` هو الابن الأول. لذلك يتغيّر نوع المكوّن في كل موضع. الموضع الأول يتبدّل بين `p` و`Form`، والثاني بين `Form` و`button`. يعيد React تعيين الحالة في كل مرة يتغيّر فيها نوع المكوّن.
-The easiest solution is to unify the branches so that `Form` always renders in the same position:
+أسهل حل هو توحيد الفرعين بحيث يبقى `Form` دائماً في نفس الموضع:
@@ -1347,7 +1346,7 @@ textarea { display: block; margin: 10px 0; }
-Technically, you could also add `null` before `
` in the `else` branch to match the `if` branch structure:
+تقنياً، يمكنك أيضاً إضافة `null` قبل `
` في فرع `else` لمطابقة هيكل فرع `if`:
@@ -1395,19 +1394,19 @@ textarea { display: block; margin: 10px 0; }
-This way, `Form` is always the second child, so it stays in the same position and keeps its state. But this approach is much less obvious and introduces a risk that someone else will remove that `null`.
+بهذا الشكل، `Form` دائماً الابن الثاني، فيبقى في نفس الموضع وتحتفظ حالته. لكن هذا النهج أقل وضوحاً ويعرّضك لخطر أن يحذف أحدهم ذلك `null`.
-#### Swap two form fields {/*swap-two-form-fields*/}
+#### تبديل حقلي نموذج {/*swap-two-form-fields*/}
-This form lets you enter first and last name. It also has a checkbox controlling which field goes first. When you tick the checkbox, the "Last name" field will appear before the "First name" field.
+هذا النموذج يتيح إدخال الاسم الأول والأخير. وفيه مربع يحدد أي الحقلين يظهر أولاً. عند تفعيله، يظهر حقل «الاسم الأخير» قبل «الاسم الأول».
-It almost works, but there is a bug. If you fill in the "First name" input and tick the checkbox, the text will stay in the first input (which is now "Last name"). Fix it so that the input text *also* moves when you reverse the order.
+يكاد يعمل، لكن فيه علة. إن ملأت حقل «الاسم الأول» ثم فعّلت المربع، يبقى النص في الحقل الأول (الذي أصبح الآن «الاسم الأخير»). أصلح ذلك بحيث ينتقل نص الحقل *أيضاً* عند عكس الترتيب.
-It seems like for these fields, their position within the parent is not enough. Is there some way to tell React how to match up the state between re-renders?
+يبدو أن موضع الحقلين داخل الأب لا يكفي. هل هناك طريقة لتخبر React كيف تطابق الحالة بين التصييرات؟
@@ -1471,7 +1470,7 @@ label { display: block; margin: 10px 0; }
-Give a `key` to both `` components in both `if` and `else` branches. This tells React how to "match up" the correct state for either `` even if their order within the parent changes:
+أعطِ `key` لكل من `` في فرعي `if` و`else`. هذا يخبر React كيف «يطابق» الحالة الصحيحة لكل `` حتى لو تغيّر ترتيبهما داخل الأب:
@@ -1533,11 +1532,11 @@ label { display: block; margin: 10px 0; }
-#### Reset a detail form {/*reset-a-detail-form*/}
+#### إعادة تعيين نموذج التفاصيل {/*reset-a-detail-form*/}
-This is an editable contact list. You can edit the selected contact's details and then either press "Save" to update it, or "Reset" to undo your changes.
+هذه قائمة جهات اتصال قابلة للتحرير. يمكنك تعديل تفاصيل جهة الاتصال المختارة ثم الضغط على «Save» للتحديث أو «Reset» للتراجع.
-When you select a different contact (for example, Alice), the state updates but the form keeps showing the previous contact's details. Fix it so that the form gets reset when the selected contact changes.
+عند اختيار جهة اتصال أخرى (مثلاً أليس)، تتحدّث الحالة لكن النموذج يظل يعرض تفاصيل الجهة السابقة. أصلح ذلك بحيث يُعاد تعيين النموذج عند تغيّر جهة الاتصال المختارة.
@@ -1689,7 +1688,7 @@ button {
-Give `key={selectedId}` to the `EditContact` component. This way, switching between different contacts will reset the form:
+أعطِ `key={selectedId}` لمكوّن `EditContact`. عندها يُعاد تعيين النموذج عند التبديل بين جهات الاتصال:
@@ -1842,13 +1841,13 @@ button {
-#### Clear an image while it's loading {/*clear-an-image-while-its-loading*/}
+#### مسح الصورة أثناء التحميل {/*clear-an-image-while-its-loading*/}
-When you press "Next", the browser starts loading the next image. However, because it's displayed in the same `
` tag, by default you would still see the previous image until the next one loads. This may be undesirable if it's important for the text to always match the image. Change it so that the moment you press "Next", the previous image immediately clears.
+عند الضغط على «Next»، يبدأ المتصفح بتحميل الصورة التالية. لكن بما أنها تُعرض في نفس وسم `
`، سترى افتراضياً الصورة السابقة حتى تنتهي التالية. قد لا ترغب بذلك إن كان من المهم أن يطابق النص الصورة دائماً. غيّر السلوك بحيث بمجرد الضغط على «Next» تُزال الصورة السابقة فوراً.
-Is there a way to tell React to re-create the DOM instead of reusing it?
+هل هناك طريقة لتخبر React بإعادة إنشاء DOM بدلاً من إعادة استخدامه؟
@@ -1918,7 +1917,7 @@ img { width: 150px; height: 150px; }
-You can provide a `key` to the `
` tag. When that `key` changes, React will re-create the `
` DOM node from scratch. This causes a brief flash when each image loads, so it's not something you'd want to do for every image in your app. But it makes sense if you want to ensure the image always matches the text.
+يمكنك إعطاء `key` لوسم `
`. عند تغيّر ذلك `key`، يعيد React إنشاء عقدة `
` في DOM من الصفر. يسبب ذلك وميضاً قصيراً عند تحميل كل صورة، فليس من المنطقي فعله لكل صورة في تطبيقك. لكنه مناسب إن أردت ضمان تطابق الصورة مع النص دائماً.
@@ -1986,11 +1985,11 @@ img { width: 150px; height: 150px; }
-#### Fix misplaced state in the list {/*fix-misplaced-state-in-the-list*/}
+#### إصلاح الحالة الموضوعة خطأ في القائمة {/*fix-misplaced-state-in-the-list*/}
-In this list, each `Contact` has state that determines whether "Show email" has been pressed for it. Press "Show email" for Alice, and then tick the "Show in reverse order" checkbox. You will notice that it's _Taylor's_ email that is expanded now, but Alice's--which has moved to the bottom--appears collapsed.
+في هذه القائمة، لكل `Contact` حالة تحدد ما إذا ضُغط «Show email» له. اضغط «Show email» لأليس، ثم فعّل «Show in reverse order». ستلاحظ أن بريد *تايلور* هو الموسّع الآن، بينما بريد أليس—المنقولة للأسفل—مطوي.
-Fix it so that the expanded state is associated with each contact, regardless of the chosen ordering.
+أصلح ذلك بحيث ترتبط حالة التوسيع بكل جهة اتصال بغض النظر عن الترتيب المختار.
@@ -2080,16 +2079,16 @@ button {
-The problem is that this example was using index as a `key`:
+المشكلة أن المثال كان يستخدم الفهرس كـ`key`:
```js
{displayedContacts.map((contact, i) =>
```
-However, you want the state to be associated with _each particular contact_.
+لكنك تريد ربط الحالة بـ*كل جهة اتصال على حدة*.
-Using the contact ID as a `key` instead fixes the issue:
+استخدام معرف جهة الاتصال كـ`key` يصلح المشكلة:
@@ -2177,7 +2176,7 @@ button {
-State is associated with the tree position. A `key` lets you specify a named position instead of relying on order.
+الحالة مرتبطة بموضع الشجرة. يتيح لك `key` تحديد موضع مسمّى بدلاً من الاعتماد على الترتيب فقط.
diff --git a/src/content/learn/queueing-a-series-of-state-updates.md b/src/content/learn/queueing-a-series-of-state-updates.md
index 41de6529a..ad871db37 100644
--- a/src/content/learn/queueing-a-series-of-state-updates.md
+++ b/src/content/learn/queueing-a-series-of-state-updates.md
@@ -1,23 +1,23 @@
---
-title: Queueing a Series of State Updates
+title: ترتيب سلسلة من تحديثات الحالة
---
-Setting a state variable will queue another render. But sometimes you might want to perform multiple operations on the value before queueing the next render. To do this, it helps to understand how React batches state updates.
+تعيين متغير حالة يضع عملية رسم أخرى في الطابور. لكن أحيانًا قد ترغب في تنفيذ عدة عمليات على القيمة قبل طلب الرسم التالي. لفعل ذلك، يفيد أن تفهم كيف يجمع React تحديثات الحالة.
-* What "batching" is and how React uses it to process multiple state updates
-* How to apply several updates to the same state variable in a row
+* ما «التجميع» وكيف يستخدمه React لمعالجة عدة تحديثات للحالة
+* كيف تطبق عدة تحديثات على نفس متغير الحالة متتاليةً
-## React batches state updates {/*react-batches-state-updates*/}
+## React يجمع تحديثات الحالة {/*react-batches-state-updates*/}
-You might expect that clicking the "+3" button will increment the counter three times because it calls `setNumber(number + 1)` three times:
+قد تتوقع أن النقر على زر «+3» يزيد العداد ثلاث مرات لأنه يستدعي `setNumber(number + 1)` ثلاث مرات:
@@ -47,7 +47,7 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; }
-However, as you might recall from the previous section, [each render's state values are fixed](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time), so the value of `number` inside the first render's event handler is always `0`, no matter how many times you call `setNumber(1)`:
+لكن كما قد تتذكر من القسم السابق، [قيم حالة كل رسم ثابتة](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time)، لذا قيمة `number` داخل معالج حدث الرسم الأول تكون دائمًا `0` مهما استدعيت `setNumber(1)`:
```js
setNumber(0 + 1);
@@ -55,21 +55,21 @@ setNumber(0 + 1);
setNumber(0 + 1);
```
-But there is one other factor at play here. **React waits until *all* code in the event handlers has run before processing your state updates.** This is why the re-render only happens *after* all these `setNumber()` calls.
+لكن هناك عامل آخر. **React ينتظر حتى يُنفَّذ كل الكود في معالجات الأحداث قبل معالجة تحديثات الحالة.** لذلك لا يحدث إعادة الرسم إلا *بعد* كل استدعاءات `setNumber()` هذه.
-This might remind you of a waiter taking an order at the restaurant. A waiter doesn't run to the kitchen at the mention of your first dish! Instead, they let you finish your order, let you make changes to it, and even take orders from other people at the table.
+قد يذكرك ذلك بنادل يأخذ طلبًا في مطعم. النادل لا يركض إلى المطبخ عند ذكر أول طبق! بل يتركك تكمل طلبك وتعدّله، وقد يأخذ طلبات آخرين على نفس الطاولة.
-
+
-This lets you update multiple state variables--even from multiple components--without triggering too many [re-renders.](/learn/render-and-commit#re-renders-when-state-updates) But this also means that the UI won't be updated until _after_ your event handler, and any code in it, completes. This behavior, also known as **batching,** makes your React app run much faster. It also avoids dealing with confusing "half-finished" renders where only some of the variables have been updated.
+هذا يتيح لك تحديث عدة متغيرات حتى من عدة مكوّنات دون إطلاق عدد كبير من [إعادات الرسم.](/learn/render-and-commit#re-renders-when-state-updates) لكنه يعني أيضًا أن الواجهة لا تُحدَّث حتى *بعد* انتهاء معالج الحدث وكل ما فيه. هذا السلوك، المعروف أيضًا باسم **التجميع،** يجعل تطبيق React أسرع كثيرًا. ويتجنب التعامل مع رسم «نصف مكتمل» مربك حيث تُحدَّث بعض المتغيرات فقط.
-**React does not batch across *multiple* intentional events like clicks**--each click is handled separately. Rest assured that React only does batching when it's generally safe to do. This ensures that, for example, if the first button click disables a form, the second click would not submit it again.
+**React لا يجمع بين عدة أحداث مقصودة مثل النقرات** — كل نقرة تُعالَج على حدة. اطمئن إلى أن React يجمع فقط عندما يكون ذلك آمنًا عمومًا. يضمن ذلك مثلًا أنه إن عطّلت النقرة الأولى نموذجًا، فلن يُعاد إرساله بالنقرة الثانية.
-## Updating the same state multiple times before the next render {/*updating-the-same-state-multiple-times-before-the-next-render*/}
+## تحديث نفس الحالة عدة مرات قبل الرسم التالي {/*updating-the-same-state-multiple-times-before-the-next-render*/}
-It is an uncommon use case, but if you would like to update the same state variable multiple times before the next render, instead of passing the *next state value* like `setNumber(number + 1)`, you can pass a *function* that calculates the next state based on the previous one in the queue, like `setNumber(n => n + 1)`. It is a way to tell React to "do something with the state value" instead of just replacing it.
+حالة استخدام نادرة، لكن إن أردت تحديث نفس متغير الحالة عدة مرات قبل الرسم التالي، بدل تمرير *قيمة الحالة التالية* مثل `setNumber(number + 1)`، يمكنك تمرير *دالة* تحسب الحالة التالية اعتمادًا على السابقة في الطابور، مثل `setNumber(n => n + 1)`. هي طريقة لتقول لReact «افعل شيئًا بقيمة الحالة» بدل استبدالها فقط.
-Try incrementing the counter now:
+جرّب زيادة العداد الآن:
@@ -99,10 +99,10 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; }
-Here, `n => n + 1` is called an **updater function.** When you pass it to a state setter:
+هنا، `n => n + 1` تُسمى **دالة المحدّث.** عند تمريرها إلى مُعيّن الحالة:
-1. React queues this function to be processed after all the other code in the event handler has run.
-2. During the next render, React goes through the queue and gives you the final updated state.
+1. يضع React هذه الدالة في طابور لمعالجتها بعد انتهاء كل الكود الآخر في معالج الحدث.
+2. أثناء الرسم التالي، يمر React على الطابور ويعطيك الحالة النهائية بعد التحديث.
```js
setNumber(n => n + 1);
@@ -110,26 +110,26 @@ setNumber(n => n + 1);
setNumber(n => n + 1);
```
-Here's how React works through these lines of code while executing the event handler:
+هكذا يعمل React مع هذه الأسطر أثناء تنفيذ معالج الحدث:
-1. `setNumber(n => n + 1)`: `n => n + 1` is a function. React adds it to a queue.
-1. `setNumber(n => n + 1)`: `n => n + 1` is a function. React adds it to a queue.
-1. `setNumber(n => n + 1)`: `n => n + 1` is a function. React adds it to a queue.
+1. `setNumber(n => n + 1)`: `n => n + 1` دالة. React يضيفها إلى طابور.
+1. `setNumber(n => n + 1)`: `n => n + 1` دالة. React يضيفها إلى طابور.
+1. `setNumber(n => n + 1)`: `n => n + 1` دالة. React يضيفها إلى طابور.
-When you call `useState` during the next render, React goes through the queue. The previous `number` state was `0`, so that's what React passes to the first updater function as the `n` argument. Then React takes the return value of your previous updater function and passes it to the next updater as `n`, and so on:
+عند استدعاء `useState` أثناء الرسم التالي، يمر React على الطابور. كانت حالة `number` السابقة `0`، فيمرّر React ذلك إلى أول دالة محدّث كوسيط `n`. ثم يأخذ قيمة الإرجاع من دالة المحدّث السابقة ويمرّرها إلى التالية كـ `n`، وهكذا:
-| queued update | `n` | returns |
+| التحديث في الطابور | `n` | الإرجاع |
|--------------|---------|-----|
| `n => n + 1` | `0` | `0 + 1 = 1` |
| `n => n + 1` | `1` | `1 + 1 = 2` |
| `n => n + 1` | `2` | `2 + 1 = 3` |
-React stores `3` as the final result and returns it from `useState`.
+يخزن React `3` كنتيجة نهائية ويعيدها من `useState`.
-This is why clicking "+3" in the above example correctly increments the value by 3.
-### What happens if you update state after replacing it {/*what-happens-if-you-update-state-after-replacing-it*/}
+لذلك النقر على «+3» في المثال أعلاه يزيد القيمة بثلاثة بشكل صحيح.
+### ماذا يحدث إن حدّثت الحالة بعد استبدالها {/*what-happens-if-you-update-state-after-replacing-it*/}
-What about this event handler? What do you think `number` will be in the next render?
+وماذا عن معالج الحدث هذا؟ ما رأيك في قيمة `number` في الرسم التالي؟
```js
-Here's what this event handler tells React to do:
+هذا ما يطلبه معالج الحدث من React:
-1. `setNumber(number + 5)`: `number` is `0`, so `setNumber(0 + 5)`. React adds *"replace with `5`"* to its queue.
-2. `setNumber(n => n + 1)`: `n => n + 1` is an updater function. React adds *that function* to its queue.
+1. `setNumber(number + 5)`: `number` تساوي `0`، فيصبح `setNumber(0 + 5)`. React يضيف *«استبدال بـ `5`»* إلى طابوره.
+2. `setNumber(n => n + 1)`: `n => n + 1` دالة محدّث. React يضيف *تلك الدالة* إلى الطابور.
-During the next render, React goes through the state queue:
+أثناء الرسم التالي، يمر React على طابور الحالة:
-| queued update | `n` | returns |
+| التحديث في الطابور | `n` | الإرجاع |
|--------------|---------|-----|
-| "replace with `5`" | `0` (unused) | `5` |
+| «استبدال بـ `5`» | `0` (غير مستخدم) | `5` |
| `n => n + 1` | `5` | `5 + 1 = 6` |
-React stores `6` as the final result and returns it from `useState`.
+يخزن React `6` كنتيجة نهائية ويعيدها من `useState`.
-You may have noticed that `setState(5)` actually works like `setState(n => 5)`, but `n` is unused!
+قد لاحظت أن `setState(5)` يعمل فعلًا مثل `setState(n => 5)`، لكن `n` غير مستخدم!
-### What happens if you replace state after updating it {/*what-happens-if-you-replace-state-after-updating-it*/}
+### ماذا يحدث إن استبدلت الحالة بعد تحديثها {/*what-happens-if-you-replace-state-after-updating-it*/}
-Let's try one more example. What do you think `number` will be in the next render?
+لنجرب مثالًا آخر. ما رأيك في قيمة `number` في الرسم التالي؟
```js
-Here's how React works through these lines of code while executing this event handler:
+هكذا يعمل React مع هذه الأسطر أثناء تنفيذ معالج الحدث:
-1. `setNumber(number + 5)`: `number` is `0`, so `setNumber(0 + 5)`. React adds *"replace with `5`"* to its queue.
-2. `setNumber(n => n + 1)`: `n => n + 1` is an updater function. React adds *that function* to its queue.
-3. `setNumber(42)`: React adds *"replace with `42`"* to its queue.
+1. `setNumber(number + 5)`: `number` تساوي `0`، فيصبح `setNumber(0 + 5)`. React يضيف *«استبدال بـ `5`»* إلى الطابور.
+2. `setNumber(n => n + 1)`: `n => n + 1` دالة محدّث. React يضيف *تلك الدالة* إلى الطابور.
+3. `setNumber(42)`: React يضيف *«استبدال بـ `42`»* إلى الطابور.
-During the next render, React goes through the state queue:
+أثناء الرسم التالي، يمر React على طابور الحالة:
-| queued update | `n` | returns |
+| التحديث في الطابور | `n` | الإرجاع |
|--------------|---------|-----|
-| "replace with `5`" | `0` (unused) | `5` |
+| «استبدال بـ `5`» | `0` (غير مستخدم) | `5` |
| `n => n + 1` | `5` | `5 + 1 = 6` |
-| "replace with `42`" | `6` (unused) | `42` |
+| «استبدال بـ `42`» | `6` (غير مستخدم) | `42` |
-Then React stores `42` as the final result and returns it from `useState`.
+ثم يخزن React `42` كنتيجة نهائية ويعيدها من `useState`.
-To summarize, here's how you can think of what you're passing to the `setNumber` state setter:
+باختصار، هكذا يمكنك التفكير فيما تمرّره إلى مُعيّن الحالة `setNumber`:
-* **An updater function** (e.g. `n => n + 1`) gets added to the queue.
-* **Any other value** (e.g. number `5`) adds "replace with `5`" to the queue, ignoring what's already queued.
+* **دالة محدّث** (مثل `n => n + 1`) تُضاف إلى الطابور.
+* **أي قيمة أخرى** (مثل الرقم `5`) تضيف «استبدال بـ `5`» إلى الطابور، متجاهلةً ما في الطابور مسبقًا.
-After the event handler completes, React will trigger a re-render. During the re-render, React will process the queue. Updater functions run during rendering, so **updater functions must be [pure](/learn/keeping-components-pure)** and only *return* the result. Don't try to set state from inside of them or run other side effects. In Strict Mode, React will run each updater function twice (but discard the second result) to help you find mistakes.
+بعد انتهاء معالج الحدث، يطلق React إعادة رسم. أثناءها يعالج الطابور. دوال المحدّث تُنفَّذ أثناء الرسم، لذا **يجب أن تكون دوال المحدّث [نقية](/learn/keeping-components-pure)** وتُرجع النتيجة فقط. لا تحاول تعيين الحالة من داخلها أو تشغيل تأثيرات جانبية أخرى. في الوضع الصارم، يشغّل React كل دالة محدّث مرتين (لكن يتجاهل النتيجة الثانية) لمساعدتك على اكتشاف الأخطاء.
-### Naming conventions {/*naming-conventions*/}
+### تسميات متعارف عليها {/*naming-conventions*/}
-It's common to name the updater function argument by the first letters of the corresponding state variable:
+شائع تسمية وسيط دالة المحدّث بالحرفين الأولين من متغير الحالة المقابل:
```js
setEnabled(e => !e);
@@ -258,13 +258,13 @@ setLastName(ln => ln.reverse());
setFriendCount(fc => fc * 2);
```
-If you prefer more verbose code, another common convention is to repeat the full state variable name, like `setEnabled(enabled => !enabled)`, or to use a prefix like `setEnabled(prevEnabled => !prevEnabled)`.
+إن فضّلت كودًا أوضح، تسمية أخرى شائعة هي تكرار اسم متغير الحالة كاملًا، مثل `setEnabled(enabled => !enabled)`، أو بادئة مثل `setEnabled(prevEnabled => !prevEnabled)`.
-* Setting state does not change the variable in the existing render, but it requests a new render.
-* React processes state updates after event handlers have finished running. This is called batching.
-* To update some state multiple times in one event, you can use `setNumber(n => n + 1)` updater function.
+* تعيين الحالة لا يغيّر المتغير في الرسم الحالي، لكنه يطلب رسمًا جديدًا.
+* React يعالج تحديثات الحالة بعد انتهاء معالجات الأحداث. هذا يُسمى التجميع.
+* لتحديث بعض الحالة عدة مرات في حدث واحد، يمكنك استخدام دالة المحدّث `setNumber(n => n + 1)`.
@@ -272,13 +272,13 @@ If you prefer more verbose code, another common convention is to repeat the full
-#### Fix a request counter {/*fix-a-request-counter*/}
+#### إصلاح عدّاد الطلبات {/*fix-a-request-counter*/}
-You're working on an art marketplace app that lets the user submit multiple orders for an art item at the same time. Each time the user presses the "Buy" button, the "Pending" counter should increase by one. After three seconds, the "Pending" counter should decrease, and the "Completed" counter should increase.
+تعمل على تطبيق سوق فنون يتيح للمستخدم تقديم عدة طلبات لقطعة فنية في آن واحد. في كل ضغطة على زر «Buy»، يجب أن يزيد عدّاد «Pending» بواحد. بعد ثلاث ثوانٍ، يجب أن ينقص عدّاد «Pending» ويزيد عدّاد «Completed».
-However, the "Pending" counter does not behave as intended. When you press "Buy", it decreases to `-1` (which should not be possible!). And if you click fast twice, both counters seem to behave unpredictably.
+لكن عدّاد «Pending» لا يتصرف كما يُراد. عند الضغط على «Buy» ينخفض إلى `-1` (وهذا لا يجب أن يحدث!). وإن نقرت بسرعة مرتين، يبدو أن العدّادين يتصرفان بشكل غير متوقع.
-Why does this happen? Fix both counters.
+لماذا يحدث هذا؟ أصلح العدّادين.
@@ -322,7 +322,7 @@ function delay(ms) {
-Inside the `handleClick` event handler, the values of `pending` and `completed` correspond to what they were at the time of the click event. For the first render, `pending` was `0`, so `setPending(pending - 1)` becomes `setPending(-1)`, which is wrong. Since you want to *increment* or *decrement* the counters, rather than set them to a concrete value determined during the click, you can instead pass the updater functions:
+داخل معالج الحدث `handleClick`، قيم `pending` و`completed` تطابق ما كانت عليه وقت حدث النقر. في الرسم الأول، كانت `pending` تساوي `0`، فيصبح `setPending(pending - 1)` هو `setPending(-1)`، وهذا خطأ. بما أنك تريد *زيادة* أو *نقصان* العدّادات بدل تعيينها لقيمة محددة وقت النقر، يمكنك تمرير دوال المحدّث بدل ذلك:
@@ -364,23 +364,23 @@ function delay(ms) {
-This ensures that when you increment or decrement a counter, you do it in relation to its *latest* state rather than what the state was at the time of the click.
+هذا يضمن أن الزيادة أو النقصان يتم بالنسبة إلى *أحدث* حالة لا ما كانت عليه وقت النقر.
-#### Implement the state queue yourself {/*implement-the-state-queue-yourself*/}
+#### نفّذ طابور الحالة بنفسك {/*implement-the-state-queue-yourself*/}
-In this challenge, you will reimplement a tiny part of React from scratch! It's not as hard as it sounds.
+في هذا التحدي، ستعيد تنفيذ جزء صغير من React من الصفر! الأمر أسهل مما يبدو.
-Scroll through the sandbox preview. Notice that it shows **four test cases.** They correspond to the examples you've seen earlier on this page. Your task is to implement the `getFinalState` function so that it returns the correct result for each of those cases. If you implement it correctly, all four tests should pass.
+مرّر في معاينة الـ sandbox. لاحظ أنها تعرض **أربع حالات اختبار.** تطابق الأمثلة التي رأيتها سابقًا في هذه الصفحة. مهمتك تنفيذ الدالة `getFinalState` لتعيد النتيجة الصحيحة لكل حالة. إن نفّذتها صحيحًا، يجب أن تنجح الاختبارات الأربعة.
-You will receive two arguments: `baseState` is the initial state (like `0`), and the `queue` is an array which contains a mix of numbers (like `5`) and updater functions (like `n => n + 1`) in the order they were added.
+ستستقبل وسيطين: `baseState` هي الحالة الأولية (مثل `0`)، و`queue` مصفوفة فيها أرقام (مثل `5`) ودوال محدّث (مثل `n => n + 1`) بالترتيب الذي أُضيفت به.
-Your task is to return the final state, just like the tables on this page show!
+مهمتك إرجاع الحالة النهائية، كما توضح الجداول في هذه الصفحة!
-If you're feeling stuck, start with this code structure:
+إن شعرت بالجمود، ابدأ بهيكل الكود هذا:
```js
export function getFinalState(baseState, queue) {
@@ -398,7 +398,7 @@ export function getFinalState(baseState, queue) {
}
```
-Fill out the missing lines!
+أكمل الأسطر الناقصة!
@@ -495,7 +495,7 @@ function TestCase({
-This is the exact algorithm described on this page that React uses to calculate the final state:
+هذا نفس الخوارزمية الموضحة في هذه الصفحة التي يستخدمها React لحساب الحالة النهائية:
@@ -596,8 +596,8 @@ function TestCase({
-Now you know how this part of React works!
+الآن تعرف كيف يعمل هذا الجزء من React!
-
\ No newline at end of file
+
diff --git a/src/content/learn/react-compiler/debugging.md b/src/content/learn/react-compiler/debugging.md
index 1883125a6..f274aa706 100644
--- a/src/content/learn/react-compiler/debugging.md
+++ b/src/content/learn/react-compiler/debugging.md
@@ -1,60 +1,60 @@
---
-title: Debugging and Troubleshooting
+title: التصحيح واستكشاف الأخطاء
---
-This guide helps you identify and fix issues when using React Compiler. Learn how to debug compilation problems and resolve common issues.
+يساعدك هذا الدليل على تحديد المشكلات وإصلاحها عند استخدام مُصرّف React. تعلّم كيفية تصحيح مشكلات التجميع وحل المشكلات الشائعة.
-* The difference between compiler errors and runtime issues
-* Common patterns that break compilation
-* Step-by-step debugging workflow
+* الفرق بين أخطاء المُصرّف ومشكلات وقت التشغيل
+* الأنماط الشائعة التي تكسر التجميع
+* مسار تصحيح خطوة بخطوة
-## Understanding Compiler Behavior {/*understanding-compiler-behavior*/}
+## فهم سلوك المُصرّف {/*understanding-compiler-behavior*/}
-React Compiler is designed to handle code that follows the [Rules of React](/reference/rules). When it encounters code that might break these rules, it safely skips optimization rather than risk changing your app's behavior.
+صُمم مُصرّف React للتعامل مع الشيفرة التي تتبع [قواعد React](/reference/rules). عندما يصادف شيفرة قد تكسر هذه القواعد، يتخطى التحسين بأمان بدلاً من المخاطرة بتغيير سلوك تطبيقك.
-### Compiler Errors vs Runtime Issues {/*compiler-errors-vs-runtime-issues*/}
+### أخطاء المُصرّف مقابل مشكلات وقت التشغيل {/*compiler-errors-vs-runtime-issues*/}
-**Compiler errors** occur at build time and prevent your code from compiling. These are rare because the compiler is designed to skip problematic code rather than fail.
+**أخطاء المُصرّف** تحدث وقت البناء وتمنع تجميع الشيفرة. نادرة لأن المُصرّف مُصمَّم لتخطي الشيفرة المشكوك فيها بدلاً من الفشل.
-**Runtime issues** occur when compiled code behaves differently than expected. Most of the time, if you encounter an issue with React Compiler, it's a runtime issue. This typically happens when your code violates the Rules of React in subtle ways that the compiler couldn't detect, and the compiler mistakenly compiled a component it should have skipped.
+**مشكلات وقت التشغيل** تحدث عندما تتصرف الشيفرة المُجمَّعة بخلاف المتوقع. في أغلب الأحيان، إن واجهت مشكلة مع مُصرّف React، فهي مشكلة وقت تشغيل. يحدث ذلك عادةً عندما تخالف الشيفرة قواعد React بطرق دقيقة لم يستطع المُصرّف اكتشافها، فيُجمِّع المُصرّف خطأً مكوّناً كان يجب أن يتخطاه.
-When debugging runtime issues, focus your efforts on finding Rules of React violations in the affected components that were not detected by the ESLint rule. The compiler relies on your code following these rules, and when they're broken in ways it can't detect, that's when runtime problems occur.
+عند تصحيح مشكلات وقت التشغيل، ركّز على إيجاد مخالفات قواعد React في المكوّنات المتأثرة التي لم تكتشفها قاعدة ESLint. يعتمد المُصرّف على التزام شيفرتك بهذه القواعد، وعند كسرها بطرق لا يمكنه اكتشافها، تحدث مشكلات وقت التشغيل.
-## Common Breaking Patterns {/*common-breaking-patterns*/}
+## أنماط الاختراق الشائعة {/*common-breaking-patterns*/}
-One of the main ways React Compiler can break your app is if your code was written to rely on memoization for correctness. This means your app depends on specific values being memoized to work properly. Since the compiler may memoize differently than your manual approach, this can lead to unexpected behavior like effects over-firing, infinite loops, or missing updates.
+من أهم الطرق التي قد يكسر بها مُصرّف React تطبيقك أن تكون الشيفرة مكتوبة لتعتمد على التذكّر للصحة. أي أن التطبيق يعتمد على تذكّر قيم معيّنة ليعمل بشكل صحيح. وبما أن المُصرّف قد يُذكّر بخلاف طريقتك اليدوية، قد يظهر سلوك غير متوقع مثل إطلاق التأثيرات أكثر من اللازم، أو حلقات لا نهائية، أو تحديثات مفقودة.
-Common scenarios where this occurs:
+سيناريوهات شائعة:
-- **Effects that rely on referential equality** - When effects depend on objects or arrays maintaining the same reference across renders
-- **Dependency arrays that need stable references** - When unstable dependencies cause effects to fire too often or create infinite loops
-- **Conditional logic based on reference checks** - When code uses referential equality checks for caching or optimization
+- **تأثيرات تعتمد على تساوي المراجع** — عندما تعتمد التأثيرات على بقاء نفس مرجع الكائنات أو المصفوفات بين عمليات الرسم
+- **مصفوفات تبعيات تحتاج مراجع ثابتة** — عندما تسبب تبعيات غير مستقرة إطلاق التأثيرات كثيراً أو إنشاء حلقات لا نهائية
+- **منطق شرطي يعتمد على فحوصات المرجع** — عندما تستخدم الشيفرة تساوي المراجع للتخزين المؤقت أو التحسين
-## Debugging Workflow {/*debugging-workflow*/}
+## مسار التصحيح {/*debugging-workflow*/}
-Follow these steps when you encounter issues:
+اتبع هذه الخطوات عند مواجهة مشكلات:
-### Compiler Build Errors {/*compiler-build-errors*/}
+### أخطاء بناء المُصرّف {/*compiler-build-errors*/}
-If you encounter a compiler error that unexpectedly breaks your build, this is likely a bug in the compiler. Report it to the [facebook/react](https://github.com/facebook/react/issues) repository with:
-- The error message
-- The code that caused the error
-- Your React and compiler versions
+إن واجهت خطأ مُصرّف يكسر البناء بغير متوقع، فالأرجح أنه خلل في المُصرّف. أبلغ عنه في مستودع [facebook/react](https://github.com/facebook/react/issues) مع:
+- رسالة الخطأ
+- الشيفرة التي سببت الخطأ
+- إصدارات React والمُصرّف لديك
-### Runtime Issues {/*runtime-issues*/}
+### مشكلات وقت التشغيل {/*runtime-issues*/}
-For runtime behavior issues:
+لمشكلات سلوك وقت التشغيل:
-### 1. Temporarily Disable Compilation {/*temporarily-disable-compilation*/}
+### 1. تعطيل التجميع مؤقتاً {/*temporarily-disable-compilation*/}
-Use `"use no memo"` to isolate whether an issue is compiler-related:
+استخدم `"use no memo"` لمعرفة ما إن كانت المشكلة مرتبطة بالمُصرّف:
```js
function ProblematicComponent() {
@@ -63,31 +63,31 @@ function ProblematicComponent() {
}
```
-If the issue disappears, it's likely related to a Rules of React violation.
+إن اختفت المشكلة، فالأرجح أنها مرتبطة بمخالفة قواعد React.
-You can also try removing manual memoization (useMemo, useCallback, memo) from the problematic component to verify that your app works correctly without any memoization. If the bug still occurs when all memoization is removed, you have a Rules of React violation that needs to be fixed.
+يمكنك أيضاً محاولة إزالة التذكّر اليدوي (`useMemo`، `useCallback`، `memo`) من المكوّن المشكوك فيه للتحقق من أن التطبيق يعمل بلا أي تذكّر. إن استمر الخطأ بعد إزالة كل التذكّر، فلديك مخالفة لقواعد React تحتاج إلى إصلاح.
-### 2. Fix Issues Step by Step {/*fix-issues-step-by-step*/}
+### 2. إصلاح المشكلات خطوة بخطوة {/*fix-issues-step-by-step*/}
-1. Identify the root cause (often memoization-for-correctness)
-2. Test after each fix
-3. Remove `"use no memo"` once fixed
-4. Verify the component shows the ✨ badge in React DevTools
+1. حدّد السبب الجذري (غالباً الاعتماد على التذكّر للصحة)
+2. اختبر بعد كل إصلاح
+3. أزل `"use no memo"` بعد الإصلاح
+4. تحقق من ظهور شارة ✨ للمكوّن في React DevTools
-## Reporting Compiler Bugs {/*reporting-compiler-bugs*/}
+## الإبلاغ عن أخطاء المُصرّف {/*reporting-compiler-bugs*/}
-If you believe you've found a compiler bug:
+إن ظننت أنك وجدت خللاً في المُصرّف:
-1. **Verify it's not a Rules of React violation** - Check with ESLint
-2. **Create a minimal reproduction** - Isolate the issue in a small example
-3. **Test without the compiler** - Confirm the issue only occurs with compilation
-4. **File an [issue](https://github.com/facebook/react/issues/new?template=compiler_bug_report.yml)**:
- - React and compiler versions
- - Minimal reproduction code
- - Expected vs actual behavior
- - Any error messages
+1. **تحقق أنها ليست مخالفة لقواعد React** — راجع ESLint
+2. **أنشئ أصغر إعادة إنتاج ممكنة** — عزل المشكلة في مثال صغير
+3. **اختبر بلا المُصرّف** — تأكد أن المشكلة تحدث فقط مع التجميع
+4. **قدّم [بلاغاً](https://github.com/facebook/react/issues/new?template=compiler_bug_report.yml)**:
+ - إصدارات React والمُصرّف
+ - شيفرة إعادة الإنتاج الدنيا
+ - السلوك المتوقع مقابل الفعلي
+ - أي رسائل خطأ
-## Next Steps {/*next-steps*/}
+## الخطوات التالية {/*next-steps*/}
-- Review the [Rules of React](/reference/rules) to prevent issues
-- Check the [incremental adoption guide](/learn/react-compiler/incremental-adoption) for gradual rollout strategies
\ No newline at end of file
+- راجع [قواعد React](/reference/rules) لمنع المشكلات
+- راجع [دليل التبني التدريجي](/learn/react-compiler/incremental-adoption) لاستراتيجيات التفعيل التدريجي
diff --git a/src/content/learn/react-compiler/incremental-adoption.md b/src/content/learn/react-compiler/incremental-adoption.md
index 56d932034..a9200af77 100644
--- a/src/content/learn/react-compiler/incremental-adoption.md
+++ b/src/content/learn/react-compiler/incremental-adoption.md
@@ -1,49 +1,49 @@
---
-title: Incremental Adoption
+title: التبني التدريجي
---
-React Compiler can be adopted incrementally, allowing you to try it on specific parts of your codebase first. This guide shows you how to gradually roll out the compiler in existing projects.
+يمكن تبني مُصرّف React تدريجياً، فيسمح لك بتجربته على أجزاء محددة من قاعدة الشيفرة أولاً. يوضح هذا الدليل كيفية تفعيل المُصرّف تدريجياً في مشاريع قائمة.
-* Why incremental adoption is recommended
-* Using Babel overrides for directory-based adoption
-* Using the "use memo" directive for opt-in compilation
-* Using the "use no memo" directive to exclude components
-* Runtime feature flags with gating
-* Monitoring your adoption progress
+* لماذا يُنصح بالتبني التدريجي
+* استخدام تجاوزات Babel للتبني حسب المجلد
+* استخدام توجيه «use memo» للاشتراك في التجميع
+* استخدام توجيه «use no memo» لاستبعاد مكوّنات
+* أعلام الميزات وقت التشغيل مع البوابات (gating)
+* مراقبة تقدّم التبني
-## Why Incremental Adoption? {/*why-incremental-adoption*/}
+## لماذا التبني التدريجي؟ {/*why-incremental-adoption*/}
-React Compiler is designed to optimize your entire codebase automatically, but you don't have to adopt it all at once. Incremental adoption gives you control over the rollout process, letting you test the compiler on small parts of your app before expanding to the rest.
+صُمم مُصرّف React ليُحسِّن قاعدة الشيفرة بأكملها تلقائياً، لكن لا يلزمك تبنيه دفعة واحدة. يمنحك التبني التدريجي تحكماً في عملية التفعيل، لتختبر المُصرّف على أجزاء صغيرة من التطبيق قبل التوسع.
-Starting small helps you build confidence in the compiler's optimizations. You can verify that your app behaves correctly with compiled code, measure performance improvements, and identify any edge cases specific to your codebase. This approach is especially valuable for production applications where stability is critical.
+البدء بجزء صغير يبني ثقتك في تحسينات المُصرّف. يمكنك التحقق من أن التطبيق يتصرف بشكل صحيح مع الشيفرة المُجمَّعة، وقياس تحسينات الأداء، وتحديد أي حالات حافة خاصة بقاعدة الشيفرة. هذا مفيد خصوصاً للتطبيقات الإنتاجية حيث الاستقرار حاسم.
-Incremental adoption also makes it easier to address any Rules of React violations the compiler might find. Instead of fixing violations across your entire codebase at once, you can tackle them systematically as you expand compiler coverage. This keeps the migration manageable and reduces the risk of introducing bugs.
+يسهّل التبني التدريجي أيضاً معالجة أي مخالفات لقواعد React قد يجدها المُصرّف. بدلاً من إصلاح المخالفات في كل القاعدة دفعة واحدة، يمكنك معالجتها بشكل منظم مع توسيع تغطية المُصرّف. يبقي ذلك الهجرة قابلة للإدارة ويقلل خطر إدخال أخطاء.
-By controlling which parts of your code get compiled, you can also run A/B tests to measure the real-world impact of the compiler's optimizations. This data helps you make informed decisions about full adoption and demonstrates the value to your team.
+بالتحكم في الأجزاء المُجمَّعة من الشيفرة، يمكنك أيضاً تشغيل اختبارات A/B لقياس أثر التحسينات في الواقع. تساعدك هذه البيانات على اتخاذ قرارات مستنيرة بشأن التبني الكامل وإظهار القيمة لفريقك.
-## Approaches to Incremental Adoption {/*approaches-to-incremental-adoption*/}
+## أساليب التبني التدريجي {/*approaches-to-incremental-adoption*/}
-There are three main approaches to adopt React Compiler incrementally:
+هناك ثلاثة أساليب رئيسية لتبني مُصرّف React تدريجياً:
-1. **Babel overrides** - Apply the compiler to specific directories
-2. **Opt-in with "use memo"** - Only compile components that explicitly opt in
-3. **Runtime gating** - Control compilation with feature flags
+1. **تجاوزات Babel** — تطبيق المُصرّف على مجلدات محددة
+2. **الاشتراك بتوجيه «use memo»** — تجميع المكوّنات التي تختار صراحةً الاشتراك فقط
+3. **البوابات وقت التشغيل** — التحكم في التجميع بأعلام ميزات
-All approaches allow you to test the compiler on specific parts of your application before full rollout.
+كل الأساليب تسمح لك باختبار المُصرّف على أجزاء محددة من التطبيق قبل التفعيل الكامل.
-## Directory-Based Adoption with Babel Overrides {/*directory-based-adoption*/}
+## التبني حسب المجلد بتجاوزات Babel {/*directory-based-adoption-with-babel-overrides*/}
-Babel's `overrides` option lets you apply different plugins to different parts of your codebase. This is ideal for gradually adopting React Compiler directory by directory.
+خيار `overrides` في Babel يتيح تطبيق إضافات مختلفة على أجزاء مختلفة من قاعدة الشيفرة. مثالي لتبني مُصرّف React مجلداً مجلداً.
-### Basic Configuration {/*basic-configuration*/}
+### الإعداد الأساسي {/*basic-configuration*/}
-Start by applying the compiler to a specific directory:
+ابدأ بتطبيق المُصرّف على مجلد محدد:
```js
// babel.config.js
@@ -62,9 +62,9 @@ module.exports = {
};
```
-### Expanding Coverage {/*expanding-coverage*/}
+### توسيع التغطية {/*expanding-coverage*/}
-As you gain confidence, add more directories:
+مع ازدياد الثقة، أضف مجلدات أكثر:
```js
// babel.config.js
@@ -89,9 +89,9 @@ module.exports = {
};
```
-### With Compiler Options {/*with-compiler-options*/}
+### مع خيارات المُصرّف {/*with-compiler-options*/}
-You can also configure compiler options per override:
+يمكنك أيضاً ضبط خيارات المُصرّف لكل تجاوز:
```js
// babel.config.js
@@ -119,15 +119,15 @@ module.exports = {
```
-## Opt-in Mode with "use memo" {/*opt-in-mode-with-use-memo*/}
+## وضع الاشتراك بتوجيه «use memo» {/*opt-in-mode-with-use-memo*/}
-For maximum control, you can use `compilationMode: 'annotation'` to only compile components and hooks that explicitly opt in with the `"use memo"` directive.
+لأقصى تحكم، يمكنك استخدام `compilationMode: 'annotation'` لتجميع المكوّنات والخطافات التي تختار صراحةً الاشتراك بتوجيه `"use memo"` فقط.
-This approach gives you fine-grained control over individual components and hooks. It's useful when you want to test the compiler on specific components without affecting entire directories.
+يمنحك هذا الأسلوب تحكماً دقيقاً في كل مكوّن وخطاف. مفيد عندما تريد اختبار المُصرّف على مكوّنات محددة دون تأثير مجلدات بأكملها.
-### Annotation Mode Configuration {/*annotation-mode-configuration*/}
+### إعداد وضع التعليقات {/*annotation-mode-configuration*/}
```js
// babel.config.js
@@ -140,9 +140,9 @@ module.exports = {
};
```
-### Using the Directive {/*using-the-directive*/}
+### استخدام التوجيه {/*using-the-directive*/}
-Add `"use memo"` at the beginning of functions you want to compile:
+أضف `"use memo"` في بداية الدوال التي تريد تجميعها:
```js
function TodoList({ todos }) {
@@ -166,22 +166,22 @@ function useSortedData(data) {
}
```
-With `compilationMode: 'annotation'`, you must:
-- Add `"use memo"` to every component you want optimized
-- Add `"use memo"` to every custom hook
-- Remember to add it to new components
+مع `compilationMode: 'annotation'`، يجب أن:
+- تضيف `"use memo"` إلى كل مكوّن تريد تحسينه
+- تضيف `"use memo"` إلى كل خطاف مخصص
+- تتذكر إضافته للمكوّنات الجديدة
-This gives you precise control over which components are compiled while you evaluate the compiler's impact.
+يمنحك ذلك تحكماً دقيقاً في المكوّنات المُجمَّعة أثناء تقييم أثر المُصرّف.
-## Runtime Feature Flags with Gating {/*runtime-feature-flags-with-gating*/}
+## أعلام الميزات وقت التشغيل مع البوابات {/*runtime-feature-flags-with-gating*/}
-The `gating` option enables you to control compilation at runtime using feature flags. This is useful for running A/B tests or gradually rolling out the compiler based on user segments.
+خيار `gating` يتيح التحكم في التجميع وقت التشغيل باستخدام أعلام ميزات. مفيد لتشغيل اختبارات A/B أو تفعيل المُصرّف تدريجياً حسب شرائح المستخدمين.
-### How Gating Works {/*how-gating-works*/}
+### كيف تعمل البوابات {/*how-gating-works*/}
-The compiler wraps optimized code in a runtime check. If the gate returns `true`, the optimized version runs. Otherwise, the original code runs.
+يلفّ المُصرّف الشيفرة المُحسَّنة بفحص وقت تشغيل. إن أعادت البوابة `true`، يعمل الإصدار المُحسَّن. وإلا تعمل الشيفرة الأصلية.
-### Gating Configuration {/*gating-configuration*/}
+### إعداد البوابات {/*gating-configuration*/}
```js
// babel.config.js
@@ -197,9 +197,9 @@ module.exports = {
};
```
-### Implementing the Feature Flag {/*implementing-the-feature-flag*/}
+### تنفيذ علم الميزة {/*implementing-the-feature-flag*/}
-Create a module that exports your gating function:
+أنشئ وحدة تصدّر دالة البوابة:
```js
// ReactCompilerFeatureFlags.js
@@ -209,17 +209,17 @@ export function isCompilerEnabled() {
}
```
-## Troubleshooting Adoption {/*troubleshooting-adoption*/}
+## استكشاف أخطاء التبني {/*troubleshooting-adoption*/}
-If you encounter issues during adoption:
+إن واجهت مشكلات أثناء التبني:
-1. Use `"use no memo"` to temporarily exclude problematic components
-2. Check the [debugging guide](/learn/react-compiler/debugging) for common issues
-3. Fix Rules of React violations identified by the ESLint plugin
-4. Consider using `compilationMode: 'annotation'` for more gradual adoption
+1. استخدم `"use no memo"` لاستبعاد المكوّنات المشكوك فيها مؤقتاً
+2. راجع [دليل التصحيح](/learn/react-compiler/debugging) للمشكلات الشائعة
+3. أصلح مخالفات قواعد React التي يحددها إضافة ESLint
+4. فكّر في `compilationMode: 'annotation'` لتبني أكثر تدرجاً
-## Next Steps {/*next-steps*/}
+## الخطوات التالية {/*next-steps*/}
-- Read the [configuration guide](/reference/react-compiler/configuration) for more options
-- Learn about [debugging techniques](/learn/react-compiler/debugging)
-- Check the [API reference](/reference/react-compiler/configuration) for all compiler options
\ No newline at end of file
+- اقرأ [دليل الإعداد](/reference/react-compiler/configuration) لمزيد من الخيارات
+- تعرّف على [تقنيات التصحيح](/learn/react-compiler/debugging)
+- راجع [مرجع واجهة البرمجة](/reference/react-compiler/configuration) لكل خيارات المُصرّف
diff --git a/src/content/learn/react-compiler/index.md b/src/content/learn/react-compiler/index.md
index 480187ed5..e107847d8 100644
--- a/src/content/learn/react-compiler/index.md
+++ b/src/content/learn/react-compiler/index.md
@@ -1,33 +1,32 @@
---
-title: React Compiler
+title: مُصرّف React
---
-## Introduction {/*introduction*/}
+## مقدمة {/*introduction*/}
-Learn [what React Compiler does](/learn/react-compiler/introduction) and how it automatically optimizes your React application by handling memoization for you, eliminating the need for manual `useMemo`, `useCallback`, and `React.memo`.
+تعرّف على [ما يفعله مُصرّف React](/learn/react-compiler/introduction) وكيف يُحسِّن تطبيقك تلقائياً عبر التعامل مع التذكّر (memoization) نيابةً عنك، فلا تحتاج إلى `useMemo` و`useCallback` و`React.memo` يدوياً.
-## Installation {/*installation*/}
+## التثبيت {/*installation*/}
-Get started with [installing React Compiler](/learn/react-compiler/installation) and learn how to configure it with your build tools.
+ابدأ بـ [تثبيت مُصرّف React](/learn/react-compiler/installation) وتعرّف على ضبطه مع أدوات البناء لديك.
+## التبني التدريجي {/*incremental-adoption*/}
-## Incremental Adoption {/*incremental-adoption*/}
+تعرّف على [استراتيجيات تبني مُصرّف React تدريجياً](/learn/react-compiler/incremental-adoption) في قاعدة الشيفرة الحالية إن لم تكن مستعداً لتفعيله في كل مكان بعد.
-Learn [strategies for gradually adopting React Compiler](/learn/react-compiler/incremental-adoption) in your existing codebase if you're not ready to enable it everywhere yet.
+## التصحيح واستكشاف الأخطاء {/*debugging-and-troubleshooting*/}
-## Debugging and Troubleshooting {/*debugging-and-troubleshooting*/}
+عندما لا يعمل كل شيء كما تتوقع، استخدم [دليل التصحيح](/learn/react-compiler/debugging) لفهم الفرق بين أخطاء المُصرّف ومشكلات وقت التشغيل، وتحديد أنماط الاختراق الشائعة، واتباع مسار تصحيح منظم.
-When things don't work as expected, use our [debugging guide](/learn/react-compiler/debugging) to understand the difference between compiler errors and runtime issues, identify common breaking patterns, and follow a systematic debugging workflow.
+## الإعداد والمرجع {/*configuration-and-reference*/}
-## Configuration and Reference {/*configuration-and-reference*/}
+لخيارات الإعداد التفصيلية ومرجع واجهة البرمجة:
-For detailed configuration options and API reference:
+- [خيارات الإعداد](/reference/react-compiler/configuration) — كل خيارات المُصرّف بما فيها التوافق مع إصدارات React
+- [التوجيهات](/reference/react-compiler/directives) — التحكم في التجميع على مستوى الدالة
+- [تجميع المكتبات](/reference/react-compiler/compiling-libraries) — شحن مكتبات مُجمَّعة مسبقاً
-- [Configuration Options](/reference/react-compiler/configuration) - All compiler configuration options including React version compatibility
-- [Directives](/reference/react-compiler/directives) - Function-level compilation control
-- [Compiling Libraries](/reference/react-compiler/compiling-libraries) - Shipping pre-compiled libraries
+## موارد إضافية {/*additional-resources*/}
-## Additional resources {/*additional-resources*/}
-
-In addition to these docs, we recommend checking the [React Compiler Working Group](https://github.com/reactwg/react-compiler) for additional information and discussion about the compiler.
+إضافةً إلى هذه الوثائق، ننصح بمراجعة [مجموعة عمل مُصرّف React](https://github.com/reactwg/react-compiler) لمزيد من المعلومات والنقاش حول المُصرّف.
diff --git a/src/content/learn/react-compiler/installation.md b/src/content/learn/react-compiler/installation.md
index 92cf0b74e..2e0ef0a57 100644
--- a/src/content/learn/react-compiler/installation.md
+++ b/src/content/learn/react-compiler/installation.md
@@ -1,56 +1,56 @@
---
-title: Installation
+title: التثبيت
---
-This guide will help you install and configure React Compiler in your React application.
+يساعدك هذا الدليل على تثبيت مُصرّف React وضبطه في تطبيق React لديك.
-* How to install React Compiler
-* Basic configuration for different build tools
-* How to verify your setup is working
+* كيفية تثبيت مُصرّف React
+* الإعداد الأساسي لأدوات بناء مختلفة
+* كيفية التحقق من أن الإعداد يعمل
-## Prerequisites {/*prerequisites*/}
+## المتطلبات {/*prerequisites*/}
-React Compiler is designed to work best with React 19, but it also supports React 17 and 18. Learn more about [React version compatibility](/reference/react-compiler/target).
+صُمم مُصرّف React ليعمل أفضل مع React 19، لكنه يدعم أيضاً React 17 و18. اطّلع على [توافق إصدارات React](/reference/react-compiler/target).
-## Installation {/*installation*/}
+## التثبيت {/*installation*/}
-Install React Compiler as a `devDependency`:
+ثبّت مُصرّف React كـ `devDependency`:
npm install -D babel-plugin-react-compiler@latest
-Or with Yarn:
+أو مع Yarn:
yarn add -D babel-plugin-react-compiler@latest
-Or with pnpm:
+أو مع pnpm:
pnpm install -D babel-plugin-react-compiler@latest
-## Basic Setup {/*basic-setup*/}
+## الإعداد الأساسي {/*basic-setup*/}
-React Compiler is designed to work by default without any configuration. However, if you need to configure it in special circumstances (for example, to target React versions below 19), refer to the [compiler options reference](/reference/react-compiler/configuration).
+صُمم مُصرّف React ليعمل افتراضياً بلا إعداد. لكن إن احتجت إلى ضبطه في حالات خاصة (مثلاً لاستهداف إصدارات React أقل من 19)، راجع [مرجع خيارات المُصرّف](/reference/react-compiler/configuration).
-The setup process depends on your build tool. React Compiler includes a Babel plugin that integrates with your build pipeline.
+تعتمد خطوات الإعداد على أداة البناء لديك. يتضمّن مُصرّف React إضافة Babel تندمج مع مسار البناء.
-React Compiler must run **first** in your Babel plugin pipeline. The compiler needs the original source information for proper analysis, so it must process your code before other transformations.
+يجب أن يعمل مُصرّف React **أولاً** في سلسلة إضافات Babel. يحتاج المُصرّف إلى معلومات المصدر الأصلية للتحليل الصحيح، فيجب أن يعالج شيفرتك قبل التحويلات الأخرى.
### Babel {/*babel*/}
-Create or update your `babel.config.js`:
+أنشئ أو حدّث `babel.config.js`:
```js {3}
module.exports = {
@@ -64,7 +64,7 @@ module.exports = {
### Vite {/*vite*/}
-If you use Vite, you can add the plugin to vite-plugin-react:
+إن كنت تستخدم Vite، يمكنك إضافة الإضافة إلى vite-plugin-react:
```js {3,9}
// vite.config.js
@@ -82,7 +82,7 @@ export default defineConfig({
});
```
-Alternatively, if you prefer a separate Babel plugin for Vite:
+بديلاً، إن فضّلت إضافة Babel منفصلة لـ Vite:
npm install -D vite-plugin-babel
@@ -108,10 +108,10 @@ export default defineConfig({
### Next.js {/*usage-with-nextjs*/}
-Please refer to the [Next.js docs](https://nextjs.org/docs/app/api-reference/next-config-js/reactCompiler) for more information.
+راجع [وثائق Next.js](https://nextjs.org/docs/app/api-reference/next-config-js/reactCompiler) لمزيد من المعلومات.
### React Router {/*usage-with-react-router*/}
-Install `vite-plugin-babel`, and add the compiler's Babel plugin to it:
+ثبّت `vite-plugin-babel`، وأضف إضافة Babel للمُصرّف:
{`npm install vite-plugin-babel`}
@@ -143,63 +143,63 @@ export default defineConfig({
### Webpack {/*usage-with-webpack*/}
-A community webpack loader is [now available here](https://github.com/SukkaW/react-compiler-webpack).
+مُحمّل Webpack مجتمعي [متاح هنا](https://github.com/SukkaW/react-compiler-webpack).
### Expo {/*usage-with-expo*/}
-Please refer to [Expo's docs](https://docs.expo.dev/guides/react-compiler/) to enable and use the React Compiler in Expo apps.
+راجع [وثائق Expo](https://docs.expo.dev/guides/react-compiler/) لتفعيل واستخدام مُصرّف React في تطبيقات Expo.
### Metro (React Native) {/*usage-with-react-native-metro*/}
-React Native uses Babel via Metro, so refer to the [Usage with Babel](#babel) section for installation instructions.
+يستخدم React Native Babel عبر Metro، فارجع إلى قسم [الاستخدام مع Babel](#babel) لتعليمات التثبيت.
### Rspack {/*usage-with-rspack*/}
-Please refer to [Rspack's docs](https://rspack.dev/guide/tech/react#react-compiler) to enable and use the React Compiler in Rspack apps.
+راجع [وثائق Rspack](https://rspack.dev/guide/tech/react#react-compiler) لتفعيل واستخدام مُصرّف React في تطبيقات Rspack.
### Rsbuild {/*usage-with-rsbuild*/}
-Please refer to [Rsbuild's docs](https://rsbuild.dev/guide/framework/react#react-compiler) to enable and use the React Compiler in Rsbuild apps.
+راجع [وثائق Rsbuild](https://rsbuild.dev/guide/framework/react#react-compiler) لتفعيل واستخدام مُصرّف React في تطبيقات Rsbuild.
-## ESLint Integration {/*eslint-integration*/}
+## تكامل ESLint {/*eslint-integration*/}
-React Compiler includes an ESLint rule that helps identify code that can't be optimized. When the ESLint rule reports an error, it means the compiler will skip optimizing that specific component or hook. This is safe: the compiler will continue optimizing other parts of your codebase. You don't need to fix all violations immediately. Address them at your own pace to gradually increase the number of optimized components.
+يتضمّن مُصرّف React قاعدة ESLint تساعد على تحديد الشيفرة التي لا يمكن تحسينها. عندما تُبلغ القاعدة عن خطأ، يعني ذلك أن المُصرّف سيتخطى تحسين ذلك المكوّن أو الخطاف تحديداً. هذا آمِن: سيستمر المُصرّف في تحسين أجزاء أخرى من قاعدة الشيفرة. لا يلزم إصلاح كل المخالفات فوراً. عالجها بوتيرتك لزيادة عدد المكوّنات المُحسَّنة تدريجياً.
-Install the ESLint plugin:
+ثبّت إضافة ESLint:
npm install -D eslint-plugin-react-hooks@latest
-If you haven't already configured eslint-plugin-react-hooks, follow the [installation instructions in the readme](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/README.md#installation). The compiler rules are available in the `recommended-latest` preset.
+إن لم تكن قد ضبطت `eslint-plugin-react-hooks` بعد، اتبع [تعليمات التثبيت في الملف README](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/README.md#installation). قواعد المُصرّف متاحة في الإعداد المسبق `recommended-latest`.
-The ESLint rule will:
-- Identify violations of the [Rules of React](/reference/rules)
-- Show which components can't be optimized
-- Provide helpful error messages for fixing issues
+ستقوم قاعدة ESLint بـ:
+- تحديد مخالفات [قواعد React](/reference/rules)
+- إظهار المكوّنات التي لا يمكن تحسينها
+- تقديم رسائل خطأ مفيدة لإصلاح المشكلات
-## Verify Your Setup {/*verify-your-setup*/}
+## التحقق من الإعداد {/*verify-your-setup*/}
-After installation, verify that React Compiler is working correctly.
+بعد التثبيت، تحقق من أن مُصرّف React يعمل بشكل صحيح.
-### Check React DevTools {/*check-react-devtools*/}
+### التحقق عبر React DevTools {/*check-react-devtools*/}
-Components optimized by React Compiler will show a "Memo ✨" badge in React DevTools:
+المكوّنات التي يُحسِّنها مُصرّف React تعرض شارة «Memo ✨» في React DevTools:
-1. Install the [React Developer Tools](/learn/react-developer-tools) browser extension
-2. Open your app in development mode
-3. Open React DevTools
-4. Look for the ✨ emoji next to component names
+1. ثبّت [إضافة React Developer Tools](/learn/react-developer-tools) للمتصفّح
+2. افتح تطبيقك في وضع التطوير
+3. افتح React DevTools
+4. ابحث عن الرمز ✨ بجانب أسماء المكوّنات
-If the compiler is working:
-- Components will show a "Memo ✨" badge in React DevTools
-- Expensive calculations will be automatically memoized
-- No manual `useMemo` is required
+إن كان المُصرّف يعمل:
+- ستظهر شارة «Memo ✨» في React DevTools
+- ستُذكَّر الحسابات المكلفة تلقائياً
+- لا حاجة إلى `useMemo` يدوي
-### Check Build Output {/*check-build-output*/}
+### التحقق من مخرجات البناء {/*check-build-output*/}
-You can also verify the compiler is running by checking your build output. The compiled code will include automatic memoization logic that the compiler adds automatically.
+يمكنك أيضاً التحقق من تشغيل المُصرّف بفحص مخرجات البناء. ستتضمّن الشيفرة المُجمَّعة منطق التذكّر التلقائي الذي يضيفه المُصرّف.
```js
import { c as _c } from "react/compiler-runtime";
@@ -217,11 +217,11 @@ export default function MyApp() {
```
-## Troubleshooting {/*troubleshooting*/}
+## استكشاف الأخطاء {/*troubleshooting*/}
-### Opting out specific components {/*opting-out-specific-components*/}
+### استبعاد مكوّنات محددة {/*opting-out-specific-components*/}
-If a component is causing issues after compilation, you can temporarily opt it out using the `"use no memo"` directive:
+إن سبب مكوّن ما مشكلات بعد التجميع، يمكنك استبعاده مؤقتاً بتوجيه `"use no memo"`:
```js
function ProblematicComponent() {
@@ -230,16 +230,16 @@ function ProblematicComponent() {
}
```
-This tells the compiler to skip optimization for this specific component. You should fix the underlying issue and remove the directive once resolved.
+يخبر ذلك المُصرّف بتخطي التحسين لهذا المكوّن. يجب إصلاح السبب الجذري وإزالة التوجيه بعد الحل.
-For more troubleshooting help, see the [debugging guide](/learn/react-compiler/debugging).
+لمزيد من المساعدة في استكشاف الأخطاء، راجع [دليل التصحيح](/learn/react-compiler/debugging).
-## Next Steps {/*next-steps*/}
+## الخطوات التالية {/*next-steps*/}
-Now that you have React Compiler installed, learn more about:
+بعد تثبيت مُصرّف React، تعرّف على:
-- [React version compatibility](/reference/react-compiler/target) for React 17 and 18
-- [Configuration options](/reference/react-compiler/configuration) to customize the compiler
-- [Incremental adoption strategies](/learn/react-compiler/incremental-adoption) for existing codebases
-- [Debugging techniques](/learn/react-compiler/debugging) for troubleshooting issues
-- [Compiling Libraries guide](/reference/react-compiler/compiling-libraries) for compiling your React library
+- [توافق إصدارات React](/reference/react-compiler/target) لـ React 17 و18
+- [خيارات الإعداد](/reference/react-compiler/configuration) لتخصيص المُصرّف
+- [استراتيجيات التبني التدريجي](/learn/react-compiler/incremental-adoption) لقواعد شيفرة قائمة
+- [تقنيات التصحيح](/learn/react-compiler/debugging) لاستكشاف المشكلات
+- [دليل تجميع المكتبات](/reference/react-compiler/compiling-libraries) لتجميع مكتبة React لديك
diff --git a/src/content/learn/react-compiler/introduction.md b/src/content/learn/react-compiler/introduction.md
index ff5d6eae4..8382e5620 100644
--- a/src/content/learn/react-compiler/introduction.md
+++ b/src/content/learn/react-compiler/introduction.md
@@ -1,28 +1,28 @@
---
-title: Introduction
+title: مقدمة
---
-React Compiler is a new build-time tool that automatically optimizes your React app. It works with plain JavaScript, and understands the [Rules of React](/reference/rules), so you don't need to rewrite any code to use it.
+مُصرّف React أداة جديدة وقت البناء تُحسِّن تطبيق React تلقائياً. يعمل مع JavaScript العادي، ويفهم [قواعد React](/reference/rules)، فلا تحتاج إلى إعادة كتابة الشيفرة لاستخدامه.
-* What React Compiler does
-* Getting started with the compiler
-* Incremental adoption strategies
-* Debugging and troubleshooting when things go wrong
-* Using the compiler on your React library
+* ما الذي يفعله مُصرّف React
+* البدء بالمُصرّف
+* استراتيجيات التبني التدريجي
+* التصحيح واستكشاف الأخطاء عند حدوث مشكلات
+* استخدام المُصرّف في مكتبة React لديك
-## What does React Compiler do? {/*what-does-react-compiler-do*/}
+## ما الذي يفعله مُصرّف React؟ {/*what-does-react-compiler-do*/}
-React Compiler automatically optimizes your React application at build time. React is often fast enough without optimization, but sometimes you need to manually memoize components and values to keep your app responsive. This manual memoization is tedious, easy to get wrong, and adds extra code to maintain. React Compiler does this optimization automatically for you, freeing you from this mental burden so you can focus on building features.
+يُحسِّن مُصرّف React تطبيقك تلقائياً وقت البناء. React غالباً سريع بلا تحسين، لكن أحياناً تحتاج إلى تذكّر المكوّنات والقيم يدوياً ليبقى التطبيق سريع الاستجابة. هذا التذكّر اليدوي مُرهِق، وسهل الخطأ، ويزيد الشيفرة التي تُصان. يطبّق مُصرّف React هذا التحسين تلقائياً، فيُخفّف عنك هذا العبء الذهني لتتفرّغ لبناء الميزات.
-### Before React Compiler {/*before-react-compiler*/}
+### قبل مُصرّف React {/*before-react-compiler*/}
-Without the compiler, you need to manually memoize components and values to optimize re-renders:
+بدون المُصرّف، تحتاج إلى تذكّر المكوّنات والقيم يدوياً لتقليل إعادة الرسم:
```js
import { useMemo, useCallback, memo } from 'react';
@@ -49,21 +49,21 @@ const ExpensiveComponent = memo(function ExpensiveComponent({ data, onClick }) {
-This manual memoization has a subtle bug that breaks memoization:
+في هذا التذكّر اليدوي خلل دقيق يكسر التذكّر:
```js [[2, 1, "() => handleClick(item)"]]
- handleClick(item)} />
```
-Even though `handleClick` is wrapped in `useCallback`, the arrow function `() => handleClick(item)` creates a new function every time the component renders. This means that `Item` will always receive a new `onClick` prop, breaking memoization.
+رغم أن `handleClick` ملفوف بـ `useCallback`، فإن الدالة السهمية `() => handleClick(item)` تنشئ دالة جديدة في كل مرة يُعاد فيها رسم المكوّن. يعني ذلك أن `Item` ستتلقى دائماً `onClick` جديداً، فيُكسر التذكّر.
-React Compiler is able to optimize this correctly with or without the arrow function, ensuring that `Item` only re-renders when `props.onClick` changes.
+يستطيع مُصرّف React تحسين هذا بشكل صحيح مع الدالة السهمية أو بدونها، فيضمن أن `Item` تعاد رسمها فقط عند تغيّر `props.onClick`.
-### After React Compiler {/*after-react-compiler*/}
+### بعد مُصرّف React {/*after-react-compiler*/}
-With React Compiler, you write the same code without manual memoization:
+مع مُصرّف React تكتب الشيفرة نفسها بلا تذكّر يدوي:
```js
function ExpensiveComponent({ data, onClick }) {
@@ -83,23 +83,23 @@ function ExpensiveComponent({ data, onClick }) {
}
```
-_[See this example in the React Compiler Playground](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAogB4AOCmYeAbggMIQC2Fh1OAFMEQCYBDHAIA0RQowA2eOAGsiAXwCURYAB1iROITA4iFGBERgwCPgBEhAogF4iCStVoMACoeO1MAcy6DhSgG4NDSItHT0ACwFMPkkmaTlbIi48HAQWFRsAPlUQ0PFMKRlZFLSWADo8PkC8hSDMPJgEHFhiLjzQgB4+eiyO-OADIwQTM0thcpYBClL02xz2zXz8zoBJMqJZBABPG2BU9Mq+BQKiuT2uTJyomLizkoOMk4B6PqX8pSUFfs7nnro3qEapgFCAFEA)_
+_[اطلع على هذا المثال في ملعب مُصرّف React](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAogB4AOCmYeAbggMIQC2Fh1OAFMEQCYBDHAIA0RQowA2eOAGsiAXwCURYAB1iROITA4iFGBERgwCPgBEhAogF4iCStVoMACoeO1MAcy6DhSgG4NDSItHT0ACwFMPkkmaTlbIi48HAQWFRsAPlUQ0PFMKRlZFLSWADo8PkC8hSDMPJgEHFhiLjzQgB4+eiyO-OADIwQTM0thcpYBClL02xz2zXz8zoBJMqJZBABPG2BU9Mq+BQKiuT2uTJyomLizkoOMk4B6PqX8pSUFfs7nnro3qEapgFCAFEA)_
-React Compiler automatically applies the optimal memoization, ensuring your app only re-renders when necessary.
+يطبّق مُصرّف React تلقائياً أفضل تذكّر، فيضمن أن يُعاد رسم تطبيقك فقط عند الحاجة.
-#### What kind of memoization does React Compiler add? {/*what-kind-of-memoization-does-react-compiler-add*/}
+#### أي نوع من التذكّر يضيفه مُصرّف React؟ {/*what-kind-of-memoization-does-react-compiler-add*/}
-React Compiler's automatic memoization is primarily focused on **improving update performance** (re-rendering existing components), so it focuses on these two use cases:
+يركّز التذكّر التلقائي لمُصرّف React أساساً على **تحسين الأداء عند التحديث** (إعادة رسم المكوّنات الموجودة)، فيركّز على حالتين:
-1. **Skipping cascading re-rendering of components**
- * Re-rendering `` causes many components in its component tree to re-render, even though only `` has changed
-1. **Skipping expensive calculations from outside of React**
- * For example, calling `expensivelyProcessAReallyLargeArrayOfObjects()` inside of your component or hook that needs that data
+1. **تخطي إعادة الرسم المتسلسلة للمكوّنات**
+ * إعادة رسم `` تُسبب إعادة رسم مكوّنات كثيرة في شجرته رغم أن `` وحده تغيّر
+1. **تخطي الحسابات المكلفة من خارج React**
+ * مثلاً استدعاء `expensivelyProcessAReallyLargeArrayOfObjects()` داخل مكوّن أو خطاف يحتاج تلك البيانات
-#### Optimizing Re-renders {/*optimizing-re-renders*/}
+#### تحسين إعادة الرسم {/*optimizing-re-renders*/}
-React lets you express your UI as a function of their current state (more concretely: their props, state, and context). In its current implementation, when a component's state changes, React will re-render that component _and all of its children_ — unless you have applied some form of manual memoization with `useMemo()`, `useCallback()`, or `React.memo()`. For example, in the following example, `` will re-render whenever ``'s state changes:
+يسمح لك React بأن تعبّر عن واجهتك كدالة لحالتها الحالية (بشكل أدق: الـ props والحالة والسياق). في التنفيذ الحالي، عند تغيّر حالة مكوّن، يُعاد رسم ذلك المكوّن _وجميع أبنائه_ — ما لم تطبّق شكلاً من التذكّر اليدوي بـ `useMemo()` أو `useCallback()` أو `React.memo()`. مثلاً في المثال التالي، `` تُعاد رسمها عندما تتغيّر حالة ``:
```javascript
function FriendList({ friends }) {
@@ -118,74 +118,74 @@ function FriendList({ friends }) {
);
}
```
-[_See this example in the React Compiler Playground_](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAYjHgpgCYAyeYOAFMEWuZVWEQL4CURwADrEicQgyKEANnkwIAwtEw4iAXiJQwCMhWoB5TDLmKsTXgG5hRInjRFGbXZwB0UygHMcACzWr1ABn4hEWsYBBxYYgAeADkIHQ4uAHoAPksRbisiMIiYYkYs6yiqPAA3FMLrIiiwAAcAQ0wU4GlZBSUcbklDNqikusaKkKrgR0TnAFt62sYHdmp+VRT7SqrqhOo6Bnl6mCoiAGsEAE9VUfmqZzwqLrHqM7ubolTVol5eTOGigFkEMDB6u4EAAhKA4HCEZ5DNZ9ErlLIWYTcEDcIA)
+[_اطلع على هذا المثال في ملعب مُصرّف React_](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAYjHgpgCYAyeYOAFMEWuZVWEQL4CURwADrEicQgyKEANnkwIAwtEw4iAXiJQwCMhWoB5TDLmKsTXgG5hRInjRFGbXZwB0UygHMcACzWr1ABn4hEWsYBBxYYgAeADkIHQ4uAHoAPksRbisiMIiYYkYs6yiqPAA3FMLrIiiwAAcAQ0wU4GlZBSUcbklDNqikusaKkKrgR0TnAFt62sYHdmp+VRT7SqrqhOo6Bnl6mCoiAGsEAE9VUfmqZzwqLrHqM7ubolTVol5eTOGigFkEMDB6u4EAAhKA4HCEZ5DNZ9ErlLIWYTcEDcIA)
-React Compiler automatically applies the equivalent of manual memoization, ensuring that only the relevant parts of an app re-render as state changes, which is sometimes referred to as "fine-grained reactivity". In the above example, React Compiler determines that the return value of `` can be reused even as `friends` changes, and can avoid recreating this JSX _and_ avoid re-rendering `` as the count changes.
+يطبّق مُصرّف React تلقائياً ما يعادل التذكّر اليدوي، فيضمن أن تُعاد رسم الأجزاء ذات الصلة فقط مع تغيّر الحالة، وهو ما يُسمى أحياناً «تفاعلية دقيقة الحبيبات». في المثال أعلاه، يحدد مُصرّف React أن قيمة إرجاع `` يمكن إعادة استخدامها حتى عند تغيّر `friends`، ويمكنه تجنب إعادة إنشاء هذا الـ JSX _وتجنب_ إعادة رسم `` عند تغيّر العدّ.
-#### Expensive calculations also get memoized {/*expensive-calculations-also-get-memoized*/}
+#### تُذكَّر الحسابات المكلفة أيضاً {/*expensive-calculations-also-get-memoized*/}
-React Compiler can also automatically memoize expensive calculations used during rendering:
+يمكن لمُصرّف React أيضاً تذكّر الحسابات المكلفة المستخدمة أثناء الرسم تلقائياً:
```js
-// **Not** memoized by React Compiler, since this is not a component or hook
+// **لا** يُذكَّر بواسطة مُصرّف React، لأنها ليست مكوّناً ولا خطافاً
function expensivelyProcessAReallyLargeArrayOfObjects() { /* ... */ }
-// Memoized by React Compiler since this is a component
+// يُذكَّر بواسطة مُصرّف React لأنها مكوّن
function TableContainer({ items }) {
- // This function call would be memoized:
+ // سيُذكَّر استدعاء هذه الدالة:
const data = expensivelyProcessAReallyLargeArrayOfObjects(items);
// ...
}
```
-[_See this example in the React Compiler Playground_](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAejQAgFTYHIQAuumAtgqRAJYBeCAJpgEYCemASggIZyGYDCEUgAcqAGwQwANJjBUAdokyEAFlTCZ1meUUxdMcIcIjyE8vhBiYVECAGsAOvIBmURYSonMCAB7CzcgBuCGIsAAowEIhgYACCnFxioQAyXDAA5gixMDBcLADyzvlMAFYIvGAAFACUmMCYaNiYAHStOFgAvk5OGJgAshTUdIysHNy8AkbikrIKSqpaWvqGIiZmhE6u7p7ymAAqXEwSguZcCpKV9VSEFBodtcBOmAYmYHz0XIT6ALzefgFUYKhCJRBAxeLcJIsVIZLI5PKFYplCqVa63aoAbm6u0wMAQhFguwAPPRAQA+YAfL4dIloUmBMlODogDpAA)
+[_اطلع على هذا المثال في ملعب مُصرّف React_](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAejQAgFTYHIQAuumAtgqRAJYBeCAJpgEYCemASggIZyGYDCEUgAcqAGwQwANJjBUAdokyEAFlTCZ1meUUxdMcIcIjyE8vhBiYVECAGsAOvIBmURYSonMCAB7CzcgBuCGIsAAowEIhgYACCnFxioQAyXDAA5gixMDBcLADyzvlMAFYIvGAAFACUmMCYaNiYAHStOFgAvk5OGJgAshTUdIysHNy8AkbikrIKSqpaWvqGIiZmhE6u7p7ymAAqXEwSguZcCpKV9VSEFBodtcBOmAYmYHz0XIT6ALzefgFUYKhCJRBAxeLcJIsVIZLI5PKFYplCqVa63aoAbm6u0wMAQhFguwAPPRAQA+YAfL4dIloUmBMlODogDpAA)
-However, if `expensivelyProcessAReallyLargeArrayOfObjects` is truly an expensive function, you may want to consider implementing its own memoization outside of React, because:
+لكن إن كانت `expensivelyProcessAReallyLargeArrayOfObjects` مكلفة فعلاً، فقد ترغب في تنفيذ تذكّرها خارج React، لأن:
-- React Compiler only memoizes React components and hooks, not every function
-- React Compiler's memoization is not shared across multiple components or hooks
+- يُذكّر مُصرّف React مكوّنات React والخطافات فقط، وليس كل دالة
+- تذكّر مُصرّف React لا يُشارك بين مكوّنات أو خطافات متعددة
-So if `expensivelyProcessAReallyLargeArrayOfObjects` was used in many different components, even if the same exact items were passed down, that expensive calculation would be run repeatedly. We recommend [profiling](reference/react/useMemo#how-to-tell-if-a-calculation-is-expensive) first to see if it really is that expensive before making code more complicated.
+فإن استُخدمت `expensivelyProcessAReallyLargeArrayOfObjects` في مكوّنات كثيرة مختلفة، حتى مع تمرير نفس العناصر تماماً، فسيُنفَّذ ذلك الحساب المكلف مراراً. ننصح [بالقياس بالملف الشخصي](reference/react/useMemo#how-to-tell-if-a-calculation-is-expensive) أولاً لمعرفة ما إن كانت مكلفة فعلاً قبل تعقيد الشيفرة.
-## Should I try out the compiler? {/*should-i-try-out-the-compiler*/}
+## هل أجرّب المُصرّف؟ {/*should-i-try-out-the-compiler*/}
-We encourage everyone to start using React Compiler. While the compiler is still an optional addition to React today, in the future some features may require the compiler in order to fully work.
+نشجع الجميع على البدء بمُصرّف React. رغم أن المُصرّف ما زال إضافة اختيارية إلى React اليوم، فقد تتطلّب بعض الميزات مستقبلاً المُصرّف لتعمل بالكامل.
-### Is it safe to use? {/*is-it-safe-to-use*/}
+### هل استخدامه آمِن؟ {/*is-it-safe-to-use*/}
-React Compiler is now stable and has been tested extensively in production. While it has been used in production at companies like Meta, rolling out the compiler to production for your app will depend on the health of your codebase and how well you've followed the [Rules of React](/reference/rules).
+مُصرّف React مستقر الآن ومُختبَر على نطاق واسع في الإنتاج. رغم استخدامه في الإنتاج في شركات مثل Meta، فاعتماد المُصرّف في إنتاج تطبيقك يعتمد على صحة قاعدة الشيفرة لديك ومدى التزامك بـ [قواعد React](/reference/rules).
-## What build tools are supported? {/*what-build-tools-are-supported*/}
+## ما أدوات البناء المدعومة؟ {/*what-build-tools-are-supported*/}
-React Compiler can be installed across [several build tools](/learn/react-compiler/installation) such as Babel, Vite, Metro, and Rsbuild.
+يمكن تثبيت مُصرّف React مع [عدة أدوات بناء](/learn/react-compiler/installation) مثل Babel وVite وMetro وRsbuild.
-React Compiler is primarily a light Babel plugin wrapper around the core compiler, which was designed to be decoupled from Babel itself. While the initial stable version of the compiler will remain primarily a Babel plugin, we are working with the swc and [oxc](https://github.com/oxc-project/oxc/issues/10048) teams to build first class support for React Compiler so you won't have to add Babel back to your build pipelines in the future.
+مُصرّف React في الأساس غلاف خفيف لإضافة Babel حول نواة المُصرّف، التي صُممت لتنفصل عن Babel نفسه. رغم أن الإصدار المستقر الأول للمُصرّف سيبقى أساساً إضافة Babel، نعمل مع فرق swc و[oxc](https://github.com/oxc-project/oxc/issues/10048) لبناء دعم من الدرجة الأولى لمُصرّف React حتى لا تحتاج لإعادة Babel إلى مسارات البناء مستقبلاً.
-Next.js users can enable the swc-invoked React Compiler by using [v15.3.1](https://github.com/vercel/next.js/releases/tag/v15.3.1) and up.
+يمكن لمستخدمي Next.js تفعيل مُصرّف React المستدعى عبر swc باستخدام [v15.3.1](https://github.com/vercel/next.js/releases/tag/v15.3.1) فما فوق.
-## What should I do about useMemo, useCallback, and React.memo? {/*what-should-i-do-about-usememo-usecallback-and-reactmemo*/}
+## ماذا أفعل بشأن useMemo وuseCallback وReact.memo؟ {/*what-should-i-do-about-usememo-usecallback-and-reactmemo*/}
-By default, React Compiler will memoize your code based on its analysis and heuristics. In most cases, this memoization will be as precise, or moreso, than what you may have written.
+بشكل افتراضي، يُذكّر مُصرّف React شيفرتك بناءً على تحليله واستدلالاته. في أغلب الحالات يكون هذا التذكّر دقيقاً مثل ما كتبته أو أكثر.
-However, in some cases developers may need more control over memoization. The `useMemo` and `useCallback` hooks can continue to be used with React Compiler as an escape hatch to provide control over which values are memoized. A common use-case for this is if a memoized value is used as an effect dependency, in order to ensure that an effect does not fire repeatedly even when its dependencies do not meaningfully change.
+لكن أحياناً يحتاج المطوّرون إلى تحكم أدق في التذكّر. يمكن الاستمرار في استخدام `useMemo` و`useCallback` مع مُصرّف React كمخرج طارئ لتحديد القيم المُذكَّرة. حالة شائعة هي إن كانت قيمة مُذكَّرة تُستخدم كتبعية لتأثير، لضمان عدم إطلاق التأثير مراراً حتى عندما لا تتغيّر تبعياته بمعنى جوهري.
-For new code, we recommend relying on the compiler for memoization and using `useMemo`/`useCallback` where needed to achieve precise control.
+للشيفرة الجديدة، ننصح بالاعتماد على المُصرّف للتذكّر واستخدام `useMemo`/`useCallback` حيث يلزم للتحكم الدقيق.
-For existing code, we recommend either leaving existing memoization in place (removing it can change compilation output) or carefully testing before removing the memoization.
+للشيفرة الموجودة، ننصح إما بإبقاء التذكّر الحالي (إزالته قد يغيّر مخرجات التجميع) أو الاختبار بعناية قبل إزالة التذكّر.
-## Try React Compiler {/*try-react-compiler*/}
+## جرّب مُصرّف React {/*try-react-compiler*/}
-This section will help you get started with React Compiler and understand how to use it effectively in your projects.
+يساعدك هذا القسم على البدء بمُصرّف React وفهم استخدامه الفعّال في مشاريعك.
-* **[Installation](/learn/react-compiler/installation)** - Install React Compiler and configure it for your build tools
-* **[React Version Compatibility](/reference/react-compiler/target)** - Support for React 17, 18, and 19
-* **[Configuration](/reference/react-compiler/configuration)** - Customize the compiler for your specific needs
-* **[Incremental Adoption](/learn/react-compiler/incremental-adoption)** - Strategies for gradually rolling out the compiler in existing codebases
-* **[Debugging and Troubleshooting](/learn/react-compiler/debugging)** - Identify and fix issues when using the compiler
-* **[Compiling Libraries](/reference/react-compiler/compiling-libraries)** - Best practices for shipping compiled code
-* **[API Reference](/reference/react-compiler/configuration)** - Detailed documentation of all configuration options
+* **[التثبيت](/learn/react-compiler/installation)** — تثبيت مُصرّف React وضبطه لأدوات البناء لديك
+* **[توافق إصدارات React](/reference/react-compiler/target)** — دعم React 17 و18 و19
+* **[الإعداد](/reference/react-compiler/configuration)** — تخصيص المُصرّف لاحتياجاتك
+* **[التبني التدريجي](/learn/react-compiler/incremental-adoption)** — استراتيجيات تفعيل المُصرّف تدريجياً في قواعد شيفرة قائمة
+* **[التصحيح واستكشاف الأخطاء](/learn/react-compiler/debugging)** — تحديد المشكلات وإصلاحها عند استخدام المُصرّف
+* **[تجميع المكتبات](/reference/react-compiler/compiling-libraries)** — أفضل الممارسات لشحن شيفرة مُجمَّعة
+* **[مرجع واجهة البرمجة](/reference/react-compiler/configuration)** — توثيق تفصيلي لكل خيارات الإعداد
-## Additional resources {/*additional-resources*/}
+## موارد إضافية {/*additional-resources*/}
-In addition to these docs, we recommend checking the [React Compiler Working Group](https://github.com/reactwg/react-compiler) for additional information and discussion about the compiler.
+إضافةً إلى هذه الوثائق، ننصح بمراجعة [مجموعة عمل مُصرّف React](https://github.com/reactwg/react-compiler) لمزيد من المعلومات والنقاش حول المُصرّف.
diff --git a/src/content/learn/referencing-values-with-refs.md b/src/content/learn/referencing-values-with-refs.md
index 4386e2bdc..df16a9637 100644
--- a/src/content/learn/referencing-values-with-refs.md
+++ b/src/content/learn/referencing-values-with-refs.md
@@ -1,37 +1,37 @@
---
-title: 'Referencing Values with Refs'
+title: 'الإشارة إلى قيم باستخدام المراجع'
---
-When you want a component to "remember" some information, but you don't want that information to [trigger new renders](/learn/render-and-commit), you can use a *ref*.
+عندما تريد أن «يتذكر» المكوّن بعض المعلومات، لكنك لا تريد أن تسبب [رسمًا جديدًا](/learn/render-and-commit)، يمكنك استخدام *مرجع* (ref).
-- How to add a ref to your component
-- How to update a ref's value
-- How refs are different from state
-- How to use refs safely
+- كيف تضيف مرجعًا إلى مكوّنك
+- كيف تُحدّث قيمة المرجع
+- كيف تختلف المراجع عن الحالة
+- كيف تستخدم المراجع بأمان
-## Adding a ref to your component {/*adding-a-ref-to-your-component*/}
+## إضافة مرجع إلى مكوّنك {/*adding-a-ref-to-your-component*/}
-You can add a ref to your component by importing the `useRef` Hook from React:
+يمكنك إضافة مرجع باستيراد Hook `useRef` من React:
```js
import { useRef } from 'react';
```
-Inside your component, call the `useRef` Hook and pass the initial value that you want to reference as the only argument. For example, here is a ref to the value `0`:
+داخل المكوّن، استدعِ `useRef` ومرّر القيمة الأولية التي تريد الإشارة إليها كوسيط وحيد. مثلًا، مرجع إلى القيمة `0`:
```js
const ref = useRef(0);
```
-`useRef` returns an object like this:
+`useRef` يعيد كائنًا مثل:
```js
{
@@ -39,11 +39,11 @@ const ref = useRef(0);
}
```
-
+
-You can access the current value of that ref through the `ref.current` property. This value is intentionally mutable, meaning you can both read and write to it. It's like a secret pocket of your component that React doesn't track. (This is what makes it an "escape hatch" from React's one-way data flow--more on that below!)
+تصل إلى القيمة الحالية للمرجع عبر الخاصية `ref.current`. هذه القيمة قابلة للتعديل عن قصد؛ يمكنك قراءتها وكتابتها. مثل جيب سري في مكوّنك لا يتتبعه React. (هذا ما يجعله «مخرجًا طارئًا» من تدفق البيانات أحادي الاتجاه في React — المزيد أدناه!)
-Here, a button will increment `ref.current` on every click:
+هنا، زر يزيد `ref.current` في كل نقرة:
@@ -68,20 +68,20 @@ export default function Counter() {
-The ref points to a number, but, like [state](/learn/state-a-components-memory), you could point to anything: a string, an object, or even a function. Unlike state, ref is a plain JavaScript object with the `current` property that you can read and modify.
+المرجع يشير إلى رقم، لكن كـ [الحالة](/learn/state-a-components-memory) يمكن أن يشير إلى أي شيء: نصًا، كائنًا، أو حتى دالة. بخلاف الحالة، المرجع كائن JavaScript عادي بخاصية `current` يمكنك قراءتها وتعديلها.
-Note that **the component doesn't re-render with every increment.** Like state, refs are retained by React between re-renders. However, setting state re-renders a component. Changing a ref does not!
+لاحظ أن **المكوّن لا يُعاد رسمه مع كل زيادة.** كالحالة، React يحتفظ بالمراجع بين إعادات الرسم. لكن تعيين الحالة يُعيد رسم المكوّن. تغيير المرجع لا يفعل ذلك!
-## Example: building a stopwatch {/*example-building-a-stopwatch*/}
+## مثال: بناء ساعة إيقاف {/*example-building-a-stopwatch*/}
-You can combine refs and state in a single component. For example, let's make a stopwatch that the user can start or stop by pressing a button. In order to display how much time has passed since the user pressed "Start", you will need to keep track of when the Start button was pressed and what the current time is. **This information is used for rendering, so you'll keep it in state:**
+يمكنك الجمع بين المراجع والحالة في مكوّن واحد. مثلًا، لنصنع ساعة إيقاف يبدأ المستخدم إيقافها أو تشغيلها بزر. لعرض الوقت المنقضي منذ الضغط على «Start»، تحتاج تتبع وقت الضغط والوقت الحالي. **هذه المعلومات تُستخدم للرسم، فتبقى في الحالة:**
```js
const [startTime, setStartTime] = useState(null);
const [now, setNow] = useState(null);
```
-When the user presses "Start", you'll use [`setInterval`](https://developer.mozilla.org/docs/Web/API/setInterval) in order to update the time every 10 milliseconds:
+عند الضغط على «Start»، ستستخدم [`setInterval`](https://developer.mozilla.org/docs/Web/API/setInterval) لتحديث الوقت كل 10 مللي ثانية:
@@ -121,7 +121,7 @@ export default function Stopwatch() {
-When the "Stop" button is pressed, you need to cancel the existing interval so that it stops updating the `now` state variable. You can do this by calling [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval), but you need to give it the interval ID that was previously returned by the `setInterval` call when the user pressed Start. You need to keep the interval ID somewhere. **Since the interval ID is not used for rendering, you can keep it in a ref:**
+عند الضغط على «Stop»، تحتاج إلغاء الفاصل الزمني الحالي ليتوقف تحديث `now`. يمكنك ذلك باستدعاء [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval)، لكن تحتاج معرف الفاصل الذي أعاده `setInterval` عند Start. تحتاج مكانًا لحفظ معرف الفاصل. **بما أن معرف الفاصل لا يُستخدم للرسم، يمكنك الاحتفاظ به في مرجع:**
@@ -168,20 +168,20 @@ export default function Stopwatch() {
-When a piece of information is used for rendering, keep it in state. When a piece of information is only needed by event handlers and changing it doesn't require a re-render, using a ref may be more efficient.
+إن كانت المعلومة تُستخدم للرسم، احتفظ بها في الحالة. إن كانت تُحتاج فقط لمعالجات الأحداث وتغييرها لا يتطلب إعادة رسم، قد يكون المرجع أكثر كفاءة.
-## Differences between refs and state {/*differences-between-refs-and-state*/}
+## الفروق بين المراجع والحالة {/*differences-between-refs-and-state*/}
-Perhaps you're thinking refs seem less "strict" than state—you can mutate them instead of always having to use a state setting function, for instance. But in most cases, you'll want to use state. Refs are an "escape hatch" you won't need often. Here's how state and refs compare:
+قد تبدو المراجع أقل «صرامة» من الحالة — يمكنك تعديلها مباشرة بدل دالة التعيين دائمًا. لكن في أغلب الحالات تفضّل الحالة. المراجع «مخرج طارئ» لا تحتاجه كثيرًا. هكذا تقارن الحالة والمراجع:
-| refs | state |
+| المراجع | الحالة |
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
-| `useRef(initialValue)` returns `{ current: initialValue }` | `useState(initialValue)` returns the current value of a state variable and a state setter function ( `[value, setValue]`) |
-| Doesn't trigger re-render when you change it. | Triggers re-render when you change it. |
-| Mutable—you can modify and update `current`'s value outside of the rendering process. | "Immutable"—you must use the state setting function to modify state variables to queue a re-render. |
-| You shouldn't read (or write) the `current` value during rendering. | You can read state at any time. However, each render has its own [snapshot](/learn/state-as-a-snapshot) of state which does not change.
+| `useRef(initialValue)` يعيد `{ current: initialValue }` | `useState(initialValue)` يعيد القيمة الحالية ودالة التعيين ( `[value, setValue]`) |
+| لا يطلق إعادة رسم عند تغييره. | يطلق إعادة رسم عند تغييره. |
+| قابل للتعديل — يمكنك تعديل `current` خارج عملية الرسم. | «غير قابل للتعديل المباشر» — يجب استخدام دالة التعيين لتعديل الحالة وطلب إعادة الرسم. |
+| لا يجب قراءة (أو كتابة) `current` أثناء الرسم. | يمكن قراءة الحالة في أي وقت. لكن كل رسم له [لقطة](/learn/state-as-a-snapshot) من الحالة لا تتغير.
-Here is a counter button that's implemented with state:
+إليك زر عدّاد مُنفَّذ بالحالة:
@@ -205,9 +205,9 @@ export default function Counter() {
-Because the `count` value is displayed, it makes sense to use a state value for it. When the counter's value is set with `setCount()`, React re-renders the component and the screen updates to reflect the new count.
+بما أن قيمة `count` تُعرض، من المنطقي استخدام الحالة. عند تعيينها بـ `setCount()`، يعيد React رسم المكوّن وتتحدث الشاشة.
-If you tried to implement this with a ref, React would never re-render the component, so you'd never see the count change! See how clicking this button **does not update its text**:
+إن حاولت تنفيذ ذلك بمرجع، لن يعيد React رسم المكوّن فلن ترى العدّ يتغير! لاحظ أن النقر **لا يحدّث النص:**
@@ -232,13 +232,13 @@ export default function Counter() {
-This is why reading `ref.current` during render leads to unreliable code. If you need that, use state instead.
+لذلك قراءة `ref.current` أثناء الرسم تؤدي إلى سلوك غير موثوق. إن احتجت ذلك، استخدم الحالة.
-#### How does useRef work inside? {/*how-does-use-ref-work-inside*/}
+#### كيف يعمل useRef داخليًا؟ {/*how-does-use-ref-work-inside*/}
-Although both `useState` and `useRef` are provided by React, in principle `useRef` could be implemented _on top of_ `useState`. You can imagine that inside of React, `useRef` is implemented like this:
+رغم أن `useState` و`useRef` من React، ففي المبدأ يمكن تنفيذ `useRef` *فوق* `useState`. تتخيل أن React ينفّذ `useRef` هكذا:
```js
// Inside of React
@@ -248,52 +248,52 @@ function useRef(initialValue) {
}
```
-During the first render, `useRef` returns `{ current: initialValue }`. This object is stored by React, so during the next render the same object will be returned. Note how the state setter is unused in this example. It is unnecessary because `useRef` always needs to return the same object!
+في الرسم الأول، `useRef` يعيد `{ current: initialValue }`. React يخزّن هذا الكائن، فيُعاد نفس الكائن في الرسم التالي. لاحظ أن دالة التعيين غير مستخدمة هنا. لا حاجة لها لأن `useRef` يجب أن يعيد دائمًا نفس الكائن!
-React provides a built-in version of `useRef` because it is common enough in practice. But you can think of it as a regular state variable without a setter. If you're familiar with object-oriented programming, refs might remind you of instance fields--but instead of `this.something` you write `somethingRef.current`.
+يوفّر React `useRef` مدمجًا لأنه شائع عمليًا. لكن يمكنك اعتباره متغير حالة بلا مُعيّن. إن كنت تعرف البرمجة كائنية التوجيه، قد تذكرك المراجع بحقول المثيل — لكن بدل `this.something` تكتب `somethingRef.current`.
-## When to use refs {/*when-to-use-refs*/}
+## متى تستخدم المراجع {/*when-to-use-refs*/}
-Typically, you will use a ref when your component needs to "step outside" React and communicate with external APIs—often a browser API that won't impact the appearance of the component. Here are a few of these rare situations:
+غالبًا تستخدم مرجعًا عندما يحتاج المكوّن «الخروج» من React والتواصل مع واجهات خارجية — غالبًا واجهة المتصفح التي لا تؤثر مباشرة على مظهر المكوّن. أمثلة نادرة:
-- Storing [timeout IDs](https://developer.mozilla.org/docs/Web/API/setTimeout)
-- Storing and manipulating [DOM elements](https://developer.mozilla.org/docs/Web/API/Element), which we cover on [the next page](/learn/manipulating-the-dom-with-refs)
-- Storing other objects that aren't necessary to calculate the JSX.
+- تخزين [معرفات المؤقتات](https://developer.mozilla.org/docs/Web/API/setTimeout)
+- تخزين والتعامل مع [عناصر DOM](https://developer.mozilla.org/docs/Web/API/Element)، كما في [الصفحة التالية](/learn/manipulating-the-dom-with-refs)
+- تخزين كائنات أخرى غير ضرورية لحساب الـ JSX.
-If your component needs to store some value, but it doesn't impact the rendering logic, choose refs.
+إن احتاج المكوّن تخزين قيمة لا تؤثر على منطق الرسم، اختر المراجع.
-## Best practices for refs {/*best-practices-for-refs*/}
+## أفضل الممارسات للمراجع {/*best-practices-for-refs*/}
-Following these principles will make your components more predictable:
+اتباع هذه المبادئ يجعل مكوّناتك أكثر قابلية للتوقع:
-- **Treat refs as an escape hatch.** Refs are useful when you work with external systems or browser APIs. If much of your application logic and data flow relies on refs, you might want to rethink your approach.
-- **Don't read or write `ref.current` during rendering.** If some information is needed during rendering, use [state](/learn/state-a-components-memory) instead. Since React doesn't know when `ref.current` changes, even reading it while rendering makes your component's behavior difficult to predict. (The only exception to this is code like `if (!ref.current) ref.current = new Thing()` which only sets the ref once during the first render.)
+- **عامل المراجع كمخرج طارئ.** مفيدة مع الأنظمة الخارجية أو واجهات المتصفح. إن اعتمد منطق تطبيقك كثيرًا على المراجع، قد تحتاج إعادة النظر في التصميم.
+- **لا تقرأ أو تكتب `ref.current` أثناء الرسم.** إن كانت المعلومة مطلوبة أثناء الرسم، استخدم [الحالة](/learn/state-a-components-memory). بما أن React لا يعلم متى يتغير `ref.current`، حتى قراءته أثناء الرسم تجعل السلوك صعب التوقع. (الاستثناء الوحيد تقريبًا كود مثل `if (!ref.current) ref.current = new Thing()` الذي يضبط المرجع مرة في الرسم الأول.)
-Limitations of React state don't apply to refs. For example, state acts like a [snapshot for every render](/learn/state-as-a-snapshot) and [doesn't update synchronously.](/learn/queueing-a-series-of-state-updates) But when you mutate the current value of a ref, it changes immediately:
+قيود حالة React لا تنطبق على المراجع. مثلًا، الحالة [لقطة لكل رسم](/learn/state-as-a-snapshot) و[لا تُحدَّث متزامنًا.](/learn/queueing-a-series-of-state-updates) لكن عند تعديل `current` للمرجع، يتغير فورًا:
```js
ref.current = 5;
console.log(ref.current); // 5
```
-This is because **the ref itself is a regular JavaScript object,** and so it behaves like one.
+لأن **المرجع نفسه كائن JavaScript عادي** فيتصرف كذلك.
-You also don't need to worry about [avoiding mutation](/learn/updating-objects-in-state) when you work with a ref. As long as the object you're mutating isn't used for rendering, React doesn't care what you do with the ref or its contents.
+لا تحتاج أيضًا القلق من [تجنب التعديل المباشر](/learn/updating-objects-in-state) عند العمل بمرجع. ما دام الكائن الذي تعدّله لا يُستخدم للرسم، لا يهم React ما تفعل بالمرجع أو محتواه.
-## Refs and the DOM {/*refs-and-the-dom*/}
+## المراجع و DOM {/*refs-and-the-dom*/}
-You can point a ref to any value. However, the most common use case for a ref is to access a DOM element. For example, this is handy if you want to focus an input programmatically. When you pass a ref to a `ref` attribute in JSX, like ``, React will put the corresponding DOM element into `myRef.current`. Once the element is removed from the DOM, React will update `myRef.current` to be `null`. You can read more about this in [Manipulating the DOM with Refs.](/learn/manipulating-the-dom-with-refs)
+يمكن أن يشير المرجع إلى أي قيمة. لكن الاستخدام الأشهر هو الوصول لعنصر DOM. مثلًا، لتوجيه التركيز لحقل برمجيًا. عند تمرير مرجع لخاصية `ref` في JSX مثل `
`، يضع React العنصر المقابل في `myRef.current`. عند إزالة العنصر، يحدّث `myRef.current` إلى `null`. التفاصيل في [التعامل مع DOM باستخدام المراجع.](/learn/manipulating-the-dom-with-refs)
-- Refs are an escape hatch to hold onto values that aren't used for rendering. You won't need them often.
-- A ref is a plain JavaScript object with a single property called `current`, which you can read or set.
-- You can ask React to give you a ref by calling the `useRef` Hook.
-- Like state, refs let you retain information between re-renders of a component.
-- Unlike state, setting the ref's `current` value does not trigger a re-render.
-- Don't read or write `ref.current` during rendering. This makes your component hard to predict.
+- المراجع مخرج طارئ للاحتفاظ بقيم لا تُستخدم للرسم. لا تحتاجها كثيرًا.
+- المرجع كائن JavaScript عادي بخاصية واحدة `current` يمكن قراءتها أو تعيينها.
+- تطلب مرجعًا من React باستدعاء Hook `useRef`.
+- كالحالة، تبقي المراجع معلومات بين إعادات رسم المكوّن.
+- بخلاف الحالة، تعيين `current` لا يطلق إعادة رسم.
+- لا تقرأ أو تكتب `ref.current` أثناء الرسم. يصعّب التنبؤ بسلوك المكوّن.
@@ -301,13 +301,13 @@ You can point a ref to any value. However, the most common use case for a ref is
-#### Fix a broken chat input {/*fix-a-broken-chat-input*/}
+#### إصلاح حقل دردشة معطوب {/*fix-a-broken-chat-input*/}
-Type a message and click "Send". You will notice there is a three second delay before you see the "Sent!" alert. During this delay, you can see an "Undo" button. Click it. This "Undo" button is supposed to stop the "Sent!" message from appearing. It does this by calling [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout) for the timeout ID saved during `handleSend`. However, even after "Undo" is clicked, the "Sent!" message still appears. Find why it doesn't work, and fix it.
+اكتب رسالة واضغط «Send». ستلاحظ تأخيرًا ثلاث ثوانٍ قبل تنبيه «Sent!». خلاله يظهر زر «Undo». النقر عليه يفترض أن يمنع ظهور «Sent!» عبر [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout) لمعرف المؤقت المحفوظ في `handleSend`. لكن حتى بعد «Undo» يظهر «Sent!» أيضًا. اكتشف السبب وأصلحه.
-Regular variables like `let timeoutID` don't "survive" between re-renders because every render runs your component (and initializes its variables) from scratch. Should you keep the timeout ID somewhere else?
+المتغيرات العادية مثل `let timeoutID` لا «تبقى» بين إعادات الرسم لأن كل رسم يعيد تشغيل المكوّن (ويبدأ المتغيرات) من الصفر. أين تحفظ معرف المؤقت؟
@@ -360,7 +360,7 @@ export default function Chat() {
-Whenever your component re-renders (such as when you set state), all local variables get initialized from scratch. This is why you can't save the timeout ID in a local variable like `timeoutID` and then expect another event handler to "see" it in the future. Instead, store it in a ref, which React will preserve between renders.
+عند إعادة رسم المكوّن (مثلًا عند تعيين الحالة)، تُهيأ كل المتغيرات المحلية من جديد. لذلك لا يمكن حفظ معرف المؤقت في `timeoutID` وتوقع أن معالجًا آخر «يراه» لاحقًا. خزّنه في مرجع يحفظه React بين الرسوم.
@@ -412,9 +412,9 @@ export default function Chat() {
-#### Fix a component failing to re-render {/*fix-a-component-failing-to-re-render*/}
+#### إصلاح مكوّن لا يُعاد رسمه {/*fix-a-component-failing-to-re-render*/}
-This button is supposed to toggle between showing "On" and "Off". However, it always shows "Off". What is wrong with this code? Fix it.
+يُفترض أن يبدّل هذا الزر بين «On» و«Off». لكنه يظهر دائمًا «Off». ما الخطأ؟ أصلحه.
@@ -438,7 +438,7 @@ export default function Toggle() {
-In this example, the current value of a ref is used to calculate the rendering output: `{isOnRef.current ? 'On' : 'Off'}`. This is a sign that this information should not be in a ref, and should have instead been put in state. To fix it, remove the ref and use state instead:
+هنا، قيمة المرجع تُستخدم لحساب المخرجات: `{isOnRef.current ? 'On' : 'Off'}`. هذا يدل أن المعلومة لا تنتمي لمرجع ويجب أن تكون حالة. أزل المرجع واستخدم الحالة:
@@ -462,17 +462,17 @@ export default function Toggle() {
-#### Fix debouncing {/*fix-debouncing*/}
+#### إصلاح التأجيل (debouncing) {/*fix-debouncing*/}
-In this example, all button click handlers are ["debounced".](https://kettanaito.com/blog/debounce-vs-throttle) To see what this means, press one of the buttons. Notice how the message appears a second later. If you press the button while waiting for the message, the timer will reset. So if you keep clicking the same button fast many times, the message won't appear until a second *after* you stop clicking. Debouncing lets you delay some action until the user "stops doing things".
+في هذا المثال، كل معالجات النقر [«مؤجّلة».](https://kettanaito.com/blog/debounce-vs-throttle) اضغط زرًا. لاحظ أن الرسالة تظهر بعد ثانية. إن ضغطت أثناء الانتظار، يُعاد ضبط المؤقت. إن نقرت بسرعة كثيرًا، لا تظهر الرسالة إلا بعد ثانية *من توقفك*. التأجيل يؤخر فعلًا حتى «يتوقف المستخدم».
-This example works, but not quite as intended. The buttons are not independent. To see the problem, click one of the buttons, and then immediately click another button. You'd expect that after a delay, you would see both button's messages. But only the last button's message shows up. The first button's message gets lost.
+المثال يعمل لكن ليس كما يُراد. الأزرار ليست مستقلة. اضغط زرًا ثم فورًا زرًا آخر. تتوقع رسالتي الزرين بعد التأخير، لكن تظهر رسالة الزر الأخير فقط. ضاعت رسالة الأولى.
-Why are the buttons interfering with each other? Find and fix the issue.
+لماذا تتداخل الأزرار؟ اعثر على المشكلة وأصلحها.
-The last timeout ID variable is shared between all `DebouncedButton` components. This is why clicking one button resets another button's timeout. Can you store a separate timeout ID for each button?
+متغير معرف المؤقت الأخير مشترك بين كل مكوّنات `DebouncedButton`. لذلك نقرة زر تلغي مؤقت زر آخر. هل يمكنك تخزين معرف مؤقت منفصل لكل زر؟
@@ -525,7 +525,7 @@ button { display: block; margin: 10px; }
-A variable like `timeoutID` is shared between all components. This is why clicking on the second button resets the first button's pending timeout. To fix this, you can keep timeout in a ref. Each button will get its own ref, so they won't conflict with each other. Notice how clicking two buttons fast will show both messages.
+متغير مثل `timeoutID` مشترك بين كل المكوّنات. لذلك النقر على الزر الثاني يلغي مؤقت الزر الأول. للإصلاح، احتفظ بالمؤقت في مرجع. لكل زر مرجعه الخاص فلا يحدث تعارض. لاحظ أن النقر السريع على زرين يعرض الرسالتين.
@@ -577,11 +577,11 @@ button { display: block; margin: 10px; }
-#### Read the latest state {/*read-the-latest-state*/}
+#### قراءة أحدث حالة {/*read-the-latest-state*/}
-In this example, after you press "Send", there is a small delay before the message is shown. Type "hello", press Send, and then quickly edit the input again. Despite your edits, the alert would still show "hello" (which was the value of state [at the time](/learn/state-as-a-snapshot#state-over-time) the button was clicked).
+في هذا المثال، بعد «Send» يوجد تأخير بسيط قبل عرض الرسالة. اكتب «hello»، اضغط Send، ثم عدّل الحقل بسرعة. رغم التعديل، التنبيه يظهر «hello» (قيمة الحالة [في لحظة](/learn/state-as-a-snapshot#state-over-time) النقر).
-Usually, this behavior is what you want in an app. However, there may be occasional cases where you want some asynchronous code to read the *latest* version of some state. Can you think of a way to make the alert show the *current* input text rather than what it was at the time of the click?
+عادة هذا السلوك مرغوب. لكن قد تحتاج أحيانًا أن يقرأ كود غير متزامن *أحدث* نسخة من الحالة. هل يمكنك جعل التنبيه يعرض نص الحقل *الحالي* لا ما كان عند النقر؟
@@ -616,7 +616,7 @@ export default function Chat() {
-State works [like a snapshot](/learn/state-as-a-snapshot), so you can't read the latest state from an asynchronous operation like a timeout. However, you can keep the latest input text in a ref. A ref is mutable, so you can read the `current` property at any time. Since the current text is also used for rendering, in this example, you will need *both* a state variable (for rendering), *and* a ref (to read it in the timeout). You will need to update the current ref value manually.
+الحالة [كلقطة](/learn/state-as-a-snapshot)، فلا تقرأ أحدث حالة من عملية غير متزامنة مثل `setTimeout`. لكن يمكنك الاحتفاظ بأحدث النص في مرجع. المرجع قابل للتعديل، فيمكن قراءة `current` في أي وقت. بما أن النص يُستخدم للرسم أيضًا، تحتاج هنا *حالة* (للرسم) *ومرجعًا* (للقراءة في المؤقت). حدّث المرجع يدويًا.
diff --git a/src/content/learn/removing-effect-dependencies.md b/src/content/learn/removing-effect-dependencies.md
index 61eb2e8d6..42ff2f643 100644
--- a/src/content/learn/removing-effect-dependencies.md
+++ b/src/content/learn/removing-effect-dependencies.md
@@ -1,26 +1,26 @@
---
-title: 'Removing Effect Dependencies'
+title: إزالة تبعيات التأثير
---
-When you write an Effect, the linter will verify that you've included every reactive value (like props and state) that the Effect reads in the list of your Effect's dependencies. This ensures that your Effect remains synchronized with the latest props and state of your component. Unnecessary dependencies may cause your Effect to run too often, or even create an infinite loop. Follow this guide to review and remove unnecessary dependencies from your Effects.
+عند كتابة تأثير، يتحقق المُدقِّق من أنك أدرجت كل قيمة تفاعلية (مثل الخصائص والحالة) يقرأها التأثير في قائمة تبعياته. هذا يضمن بقاء التأثير متزامناً مع أحدث الخصائص والحالة لمكوّنك. التبعيات غير الضرورية قد تجعل التأثير يعمل كثيراً، أو تخلق حلقة لا نهائية. اتبع هذا الدليل لمراجعة وإزالة التبعيات غير الضرورية من تأثيراتك.
-- How to fix infinite Effect dependency loops
-- What to do when you want to remove a dependency
-- How to read a value from your Effect without "reacting" to it
-- How and why to avoid object and function dependencies
-- Why suppressing the dependency linter is dangerous, and what to do instead
+- كيف تصلح حلقات تبعيات التأثير اللانهائية
+- ماذا تفعل عندما تريد إزالة تبعية
+- كيف تقرأ قيمة من التأثير دون «التفاعل» معها
+- كيف ولماذا تتجنّب تبعيات الكائنات والدوال
+- لماذا كتم مُدقِّق التبعيات خطير، وماذا تفعل بدلاً من ذلك
-## Dependencies should match the code {/*dependencies-should-match-the-code*/}
+## يجب أن تطابق التبعيات الشيفرة {/*dependencies-should-match-the-code*/}
-When you write an Effect, you first specify how to [start and stop](/learn/lifecycle-of-reactive-effects#the-lifecycle-of-an-effect) whatever you want your Effect to be doing:
+عند كتابة تأثير، تحدّد أولاً كيفية [البدء والإيقاف](/learn/lifecycle-of-reactive-effects#the-lifecycle-of-an-effect) لما تريد أن يفعله تأثيرك:
```js {5-7}
const serverUrl = 'https://localhost:1234';
@@ -34,7 +34,7 @@ function ChatRoom({ roomId }) {
}
```
-Then, if you leave the Effect dependencies empty (`[]`), the linter will suggest the correct dependencies:
+ثم، إن تركت تبعيات التأثير فارغة (`[]`)، يقترح المُدقِّق التبعيات الصحيحة:
@@ -96,7 +96,7 @@ button { margin-left: 10px; }
-Fill them in according to what the linter says:
+املأها وفق ما يقوله المُدقِّق:
```js {6}
function ChatRoom({ roomId }) {
@@ -109,7 +109,7 @@ function ChatRoom({ roomId }) {
}
```
-[Effects "react" to reactive values.](/learn/lifecycle-of-reactive-effects#effects-react-to-reactive-values) Since `roomId` is a reactive value (it can change due to a re-render), the linter verifies that you've specified it as a dependency. If `roomId` receives a different value, React will re-synchronize your Effect. This ensures that the chat stays connected to the selected room and "reacts" to the dropdown:
+[التأثيرات «تتفاعل» مع القيم التفاعلية.](/learn/lifecycle-of-reactive-effects#effects-react-to-reactive-values) وبما أن `roomId` قيمة تفاعلية (قد تتغيّر بسبب إعادة التصيير)، يتحقق المُدقِّق من أنك حدّدتها كتبعية. إن استلمت `roomId` قيمة مختلفة، يعيد React مزامنة تأثيرك. وهذا يضمن بقاء المحادثة متصلة بالغرفة المختارة وتتفاعل مع القائمة المنسدلة:
@@ -171,9 +171,9 @@ button { margin-left: 10px; }
-### To remove a dependency, prove that it's not a dependency {/*to-remove-a-dependency-prove-that-its-not-a-dependency*/}
+### لإزالة تبعية، أثبت أنها ليست تبعية {/*to-remove-a-dependency-prove-that-its-not-a-dependency*/}
-Notice that you can't "choose" the dependencies of your Effect. Every reactive value used by your Effect's code must be declared in your dependency list. The dependency list is determined by the surrounding code:
+لاحظ أنك لا تستطيع «اختيار» تبعيات تأثيرك. كل قيمة تفاعلية تستخدمها شيفرة التأثير يجب أن تُعلَن في قائمة التبعيات. تُحدَّد قائمة التبعيات بالشيفرة المحيطة:
```js [[2, 3, "roomId"], [2, 5, "roomId"], [2, 8, "roomId"]]
const serverUrl = 'https://localhost:1234';
@@ -188,7 +188,7 @@ function ChatRoom({ roomId }) { // This is a reactive value
}
```
-[Reactive values](/learn/lifecycle-of-reactive-effects#all-variables-declared-in-the-component-body-are-reactive) include props and all variables and functions declared directly inside of your component. Since `roomId` is a reactive value, you can't remove it from the dependency list. The linter wouldn't allow it:
+[القيم التفاعلية](/learn/lifecycle-of-reactive-effects#all-variables-declared-in-the-component-body-are-reactive) تشمل الخصائص وكل المتغيرات والدوال المعرّفة مباشرة داخل مكوّنك. وبما أن `roomId` تفاعلي، لا يمكنك حذفه من قائمة التبعيات. المُدقِّق لن يسمح:
```js {8}
const serverUrl = 'https://localhost:1234';
@@ -203,9 +203,9 @@ function ChatRoom({ roomId }) {
}
```
-And the linter would be right! Since `roomId` may change over time, this would introduce a bug in your code.
+والمُدقِّق على حق! وبما أن `roomId` قد يتغيّر مع الزمن، هذا يدخل علة في شيفرتك.
-**To remove a dependency, "prove" to the linter that it *doesn't need* to be a dependency.** For example, you can move `roomId` out of your component to prove that it's not reactive and won't change on re-renders:
+**لإزالة تبعية، «أثبت» للمُدقِّق أنها *لا تحتاج* إلى أن تكون تبعية.** مثلاً، انقل `roomId` خارج المكوّن لتثبت أنه ليس تفاعلياً ولن يتغيّر عند إعادة التصيير:
```js {2,9}
const serverUrl = 'https://localhost:1234';
@@ -221,7 +221,7 @@ function ChatRoom() {
}
```
-Now that `roomId` is not a reactive value (and can't change on a re-render), it doesn't need to be a dependency:
+وبما أن `roomId` لم يعد تفاعلياً (ولا يمكن أن يتغيّر عند إعادة التصيير)، لا يحتاج إلى أن يكون تبعية:
@@ -263,23 +263,23 @@ button { margin-left: 10px; }
-This is why you could now specify an [empty (`[]`) dependency list.](/learn/lifecycle-of-reactive-effects#what-an-effect-with-empty-dependencies-means) Your Effect *really doesn't* depend on any reactive value anymore, so it *really doesn't* need to re-run when any of the component's props or state change.
+لذلك يمكنك الآن تحديد [قائمة تبعيات فارغة (`[]`).](/learn/lifecycle-of-reactive-effects#what-an-effect-with-empty-dependencies-means) تأثيرك *لا يعتمد فعلاً* على أي قيمة تفاعلية بعد الآن، فلا *يحتاج فعلاً* إلى إعادة التشغيل عند تغيّر خصائص أو حالة المكوّن.
-### To change the dependencies, change the code {/*to-change-the-dependencies-change-the-code*/}
+### لتغيير التبعيات، غيّر الشيفرة {/*to-change-the-dependencies-change-the-code*/}
-You might have noticed a pattern in your workflow:
+ربما لاحظت نمطاً في سير عملك:
-1. First, you **change the code** of your Effect or how your reactive values are declared.
-2. Then, you follow the linter and adjust the dependencies to **match the code you have changed.**
-3. If you're not happy with the list of dependencies, you **go back to the first step** (and change the code again).
+1. أولاً **تغيّر شيفرة** التأثير أو كيف تُعرَف القيم التفاعلية.
+2. ثم تتبع المُدقِّق وتضبط التبعيات لت**طابق الشيفرة التي غيّرتها.**
+3. إن لم ترضَ عن قائمة التبعيات، **عد إلى الخطوة الأولى** (وغيّر الشيفرة من جديد).
-The last part is important. **If you want to change the dependencies, change the surrounding code first.** You can think of the dependency list as [a list of all the reactive values used by your Effect's code.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) You don't *choose* what to put on that list. The list *describes* your code. To change the dependency list, change the code.
+الجزء الأخير مهم. **إن أردت تغيير التبعيات، غيّر الشيفرة المحيطة أولاً.** يمكنك اعتبار قائمة التبعيات [قائمة بكل القيم التفاعلية التي تستخدمها شيفرة التأثير.](/learn/lifecycle-of-reactive-effects#react-verifies-that-you-specified-every-reactive-value-as-a-dependency) لا *تختار* ما تضعه في القائمة. القائمة *تصف* شيفرتك. لتغيير قائمة التبعيات، غيّر الشيفرة.
-This might feel like solving an equation. You might start with a goal (for example, to remove a dependency), and you need to "find" the code matching that goal. Not everyone finds solving equations fun, and the same thing could be said about writing Effects! Luckily, there is a list of common recipes that you can try below.
+قد يشعرك هذا بحل معادلة. قد تبدأ بهدف (مثلاً إزالة تبعية) وتحتاج إلى «إيجاد» الشيفرة التي تحققه. ليس الجميع يستمتع بحل المعادلات، ويمكن قول مثل ذلك عن كتابة التأثيرات! لحسن الحظ، توجد وصفات شائعة يمكنك تجربتها أدناه.
-If you have an existing codebase, you might have some Effects that suppress the linter like this:
+إن كان لديك قاعدة شيفرة قائمة، قد تجد تأثيرات تكتم المُدقِّق هكذا:
```js {3-4}
useEffect(() => {
@@ -289,17 +289,17 @@ useEffect(() => {
}, []);
```
-**When dependencies don't match the code, there is a very high risk of introducing bugs.** By suppressing the linter, you "lie" to React about the values your Effect depends on.
+**عندما لا تطابق التبعيات الشيفرة، خطر إدخال العلل مرتفع جداً.** بكتم المُدقِّق، «تكذب» على React بشأن القيم التي يعتمد عليها تأثيرك.
-Instead, use the techniques below.
+استخدم بدلاً من ذلك التقنيات أدناه.
-#### Why is suppressing the dependency linter so dangerous? {/*why-is-suppressing-the-dependency-linter-so-dangerous*/}
+#### لماذا كتم مُدقِّق التبعيات خطير؟ {/*why-is-suppressing-the-dependency-linter-so-dangerous*/}
-Suppressing the linter leads to very unintuitive bugs that are hard to find and fix. Here's one example:
+كتم المُدقِّق يؤدي إلى علل غير بديهية يصعب العثور عليها وإصلاحها. إليك مثالاً:
@@ -348,31 +348,31 @@ button { margin: 10px; }
-Let's say that you wanted to run the Effect "only on mount". You've read that [empty (`[]`) dependencies](/learn/lifecycle-of-reactive-effects#what-an-effect-with-empty-dependencies-means) do that, so you've decided to ignore the linter, and forcefully specified `[]` as the dependencies.
+لنقل أردت تشغيل التأثير «عند التثبيت فقط». قرأت أن [تبعيات فارغة (`[]`)](/learn/lifecycle-of-reactive-effects#what-an-effect-with-empty-dependencies-means) تفعل ذلك، فقررت تجاهل المُدقِّق وفرضت `[]` كتبعيات.
-This counter was supposed to increment every second by the amount configurable with the two buttons. However, since you "lied" to React that this Effect doesn't depend on anything, React forever keeps using the `onTick` function from the initial render. [During that render,](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) `count` was `0` and `increment` was `1`. This is why `onTick` from that render always calls `setCount(0 + 1)` every second, and you always see `1`. Bugs like this are harder to fix when they're spread across multiple components.
+كان المفترض أن يزداد العداد كل ثانية بالمقدار القابل للضبط بالزرّين. لكن بما أنك «كذبت» على React بأن التأثير لا يعتمد على شيء، يبقى React يستخدم دالة `onTick` من التصيير الأول إلى الأبد. [في ذلك التصيير](/learn/state-as-a-snapshot#rendering-takes-a-snapshot-in-time) كان `count` هو `0` و`increment` هو `1`. لذلك تستدعي `onTick` من ذلك التصيير دائماً `setCount(0 + 1)` كل ثانية، وترى دائماً `1`. مثل هذه العلل أصعب إصلاحها عندما تنتشر بين عدة مكوّنات.
-There's always a better solution than ignoring the linter! To fix this code, you need to add `onTick` to the dependency list. (To ensure the interval is only setup once, [make `onTick` an Effect Event.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events))
+يوجد دائماً حل أفضل من تجاهل المُدقِّق! لإصلاح هذه الشيفرة، أضف `onTick` إلى قائمة التبعيات. (لضمان إعداد الفترة مرة واحدة فقط، [اجعل `onTick` حدث تأثير Effect Event.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events))
-**We recommend treating the dependency lint error as a compilation error. If you don't suppress it, you will never see bugs like this.** The rest of this page documents the alternatives for this and other cases.
+**ننصحك باعتبار خطأ lint للتبعيات كخطأ تجميع. إن لم تكتم المُدقِّق، لن ترى مثل هذه العلل.** بقية الصفحة توثّق البدائل لهذه الحالات وغيرها.
-## Removing unnecessary dependencies {/*removing-unnecessary-dependencies*/}
+## إزالة التبعيات غير الضرورية {/*removing-unnecessary-dependencies*/}
-Every time you adjust the Effect's dependencies to reflect the code, look at the dependency list. Does it make sense for the Effect to re-run when any of these dependencies change? Sometimes, the answer is "no":
+في كل مرة تضبط فيها تبعيات التأثير لتعكس الشيفرة، انظر إلى قائمة التبعيات. هل من المنطقي أن يعاد تشغيل التأثير عند تغيّر أي منها؟ أحياناً الجواب «لا»:
-* You might want to re-execute *different parts* of your Effect under different conditions.
-* You might want to only read the *latest value* of some dependency instead of "reacting" to its changes.
-* A dependency may change too often *unintentionally* because it's an object or a function.
+* قد تريد إعادة تنفيذ *أجزاء مختلفة* من التأثير في ظروف مختلفة.
+* قد تريد قراءة *أحدث قيمة* لتبعية ما دون «التفاعل» مع تغيّراتها.
+* قد تتغيّر تبعية كثيراً *دون قصد* لأنها كائن أو دالة.
-To find the right solution, you'll need to answer a few questions about your Effect. Let's walk through them.
+لإيجاد الحل الصحيح، ستحتاج إلى الإجابة عن أسئلة عن تأثيرك. لنمرّ عليها.
-### Should this code move to an event handler? {/*should-this-code-move-to-an-event-handler*/}
+### هل ينبغي نقل هذه الشيفرة إلى معالج حدث؟ {/*should-this-code-move-to-an-event-handler*/}
-The first thing you should think about is whether this code should be an Effect at all.
+أول ما ينبغي أن تفكر فيه: هل ينبغي أن تكون هذه الشيفرة تأثيراً أصلاً؟
-Imagine a form. On submit, you set the `submitted` state variable to `true`. You need to send a POST request and show a notification. You've put this logic inside an Effect that "reacts" to `submitted` being `true`:
+تخيّل نموذجاً. عند الإرسال، تضبط متغير الحالة `submitted` إلى `true`. تحتاج إلى إرسال طلب POST وعرض إشعار. وضعت هذا المنطق داخل تأثير «يتفاعل» مع كون `submitted` هو `true`:
```js {6-8}
function Form() {
@@ -394,7 +394,7 @@ function Form() {
}
```
-Later, you want to style the notification message according to the current theme, so you read the current theme. Since `theme` is declared in the component body, it is a reactive value, so you add it as a dependency:
+لاحقاً، تريد تنسيق رسالة الإشعار حسب السمة الحالية، فتقرأ السمة الحالية. وبما أن `theme` معرّف في جسم المكوّن، فهو تفاعلي، فتضيفه كتبعية:
```js {3,9,11}
function Form() {
@@ -417,9 +417,9 @@ function Form() {
}
```
-By doing this, you've introduced a bug. Imagine you submit the form first and then switch between Dark and Light themes. The `theme` will change, the Effect will re-run, and so it will display the same notification again!
+بهذا أدخلت علة. تخيّل أنك أرسلت النموذج أولاً ثم بدّلت بين السمة الداكنة والفاتحة. ستتغيّر `theme`، فيعاد تشغيل التأثير، فيُعرض نفس الإشعار مرة أخرى!
-**The problem here is that this shouldn't be an Effect in the first place.** You want to send this POST request and show the notification in response to *submitting the form,* which is a particular interaction. To run some code in response to particular interaction, put that logic directly into the corresponding event handler:
+**المشكلة هنا أن هذا لا ينبغي أن يكون تأثيراً أصلاً.** تريد إرسال POST وعرض الإشعار استجابةً *لإرسال النموذج،* وهو تفاعل محدد. لتشغيل شيفرة استجابةً لتفاعل محدد، ضع المنطق مباشرة في معالج الحدث المناسب:
```js {6-7}
function Form() {
@@ -435,13 +435,13 @@ function Form() {
}
```
-Now that the code is in an event handler, it's not reactive--so it will only run when the user submits the form. Read more about [choosing between event handlers and Effects](/learn/separating-events-from-effects#reactive-values-and-reactive-logic) and [how to delete unnecessary Effects.](/learn/you-might-not-need-an-effect)
+وبما أن الشيفرة في معالج حدث، فليست تفاعلية—فتعمل فقط عند إرسال المستخدم للنموذج. اقرأ المزيد عن [الاختيار بين معالجات الأحداث والتأثيرات](/learn/separating-events-from-effects#reactive-values-and-reactive-logic) و[كيف تحذف التأثيرات غير الضرورية.](/learn/you-might-not-need-an-effect)
-### Is your Effect doing several unrelated things? {/*is-your-effect-doing-several-unrelated-things*/}
+### هل يفعل تأثيرك عدة أشياء غير مرتبطة؟ {/*is-your-effect-doing-several-unrelated-things*/}
-The next question you should ask yourself is whether your Effect is doing several unrelated things.
+السؤال التالي: هل يفعل تأثيرك عدة أشياء غير مرتبطة؟
-Imagine you're creating a shipping form where the user needs to choose their city and area. You fetch the list of `cities` from the server according to the selected `country` to show them in a dropdown:
+تخيّل أنك تنشئ نموذج شحن يحتاج فيه المستخدم إلى اختيار مدينته ومنطقته. تجلب قائمة `cities` من الخادم حسب `country` المختار لتعرضها في قائمة منسدلة:
```js
function ShippingForm({ country }) {
@@ -465,9 +465,9 @@ function ShippingForm({ country }) {
// ...
```
-This is a good example of [fetching data in an Effect.](/learn/you-might-not-need-an-effect#fetching-data) You are synchronizing the `cities` state with the network according to the `country` prop. You can't do this in an event handler because you need to fetch as soon as `ShippingForm` is displayed and whenever the `country` changes (no matter which interaction causes it).
+هذا مثال جيّد لـ[جلب البيانات في تأثير.](/learn/you-might-not-need-an-effect#fetching-data) تزامن حالة `cities` مع الشبكة حسب خاصية `country`. لا يمكنك فعل هذا في معالج حدث لأنك تحتاج الجلب بمجرد عرض `ShippingForm` وكلما تغيّر `country` (بغض النظر عن التفاعل الذي سبب ذلك).
-Now let's say you're adding a second select box for city areas, which should fetch the `areas` for the currently selected `city`. You might start by adding a second `fetch` call for the list of areas inside the same Effect:
+لنقل تضيف صندوق اختيار ثانياً لمناطق المدينة، يجب أن يجلب `areas` للمدينة المختارة حالياً `city`. قد تبدأ بإضافة استدعاء `fetch` ثانٍ لقائمة المناطق داخل نفس التأثير:
```js {15-24,28}
function ShippingForm({ country }) {
@@ -502,14 +502,14 @@ function ShippingForm({ country }) {
// ...
```
-However, since the Effect now uses the `city` state variable, you've had to add `city` to the list of dependencies. That, in turn, introduced a problem: when the user selects a different city, the Effect will re-run and call `fetchCities(country)`. As a result, you will be unnecessarily refetching the list of cities many times.
+لكن بما أن التأثير يستخدم الآن متغير الحالة `city`، اضطررت إلى إضافة `city` إلى التبعيات. وهذا أدخل مشكلة: عند اختيار مدينة أخرى، يعاد تشغيل التأثير ويستدعي `fetchCities(country)`. النتيجة إعادة جلب قائمة المدن كثيراً دون داعٍ.
-**The problem with this code is that you're synchronizing two different unrelated things:**
+**مشكلة هذه الشيفرة أنك تزامن شيئين مختلفين غير مرتبطين:**
-1. You want to synchronize the `cities` state to the network based on the `country` prop.
-1. You want to synchronize the `areas` state to the network based on the `city` state.
+1. تريد مزامنة حالة `cities` مع الشبكة حسب خاصية `country`.
+1. تريد مزامنة حالة `areas` مع الشبكة حسب حالة `city`.
-Split the logic into two Effects, each of which reacts to the prop that it needs to synchronize with:
+قسّم المنطق إلى تأثيرين، كل منهما يتفاعل مع الخاصية التي يحتاج للمزامنة معها:
```js {19-33}
function ShippingForm({ country }) {
@@ -549,13 +549,13 @@ function ShippingForm({ country }) {
// ...
```
-Now the first Effect only re-runs if the `country` changes, while the second Effect re-runs when the `city` changes. You've separated them by purpose: two different things are synchronized by two separate Effects. Two separate Effects have two separate dependency lists, so they won't trigger each other unintentionally.
+الآن يعاد تشغيل التأثير الأول فقط إذا تغيّر `country`، بينما يعاد تشغيل الثاني عند تغيّر `city`. فصلتهما حسب الغرض: شيئان مختلفان يزامنهما تأثيران منفصلان. لتأثيرين منفصلين قائمتان تبعيتان منفصلتان، فلا يطلق أحدهما الآخر عن غير قصد.
-The final code is longer than the original, but splitting these Effects is still correct. [Each Effect should represent an independent synchronization process.](/learn/lifecycle-of-reactive-effects#each-effect-represents-a-separate-synchronization-process) In this example, deleting one Effect doesn't break the other Effect's logic. This means they *synchronize different things,* and it's good to split them up. If you're concerned about duplication, you can improve this code by [extracting repetitive logic into a custom Hook.](/learn/reusing-logic-with-custom-hooks#when-to-use-custom-hooks)
+الشيفرة النهائية أطول من الأصل، لكن تقسيم التأثيرين ما زال صحيحاً. [كل تأثير ينبغي أن يمثل عملية مزامنة مستقلة.](/learn/lifecycle-of-reactive-effects#each-effect-represents-a-separate-synchronization-process) في هذا المثال، حذف أحد التأثيرين لا يكسر منطق الآخر. أي أنهما *يزامنان أشياء مختلفة،* فمن الجيد فصلهما. إن قلقك من التكرار، حسّن الشيفرة بـ[استخراج المنطق المتكرر إلى خطاف مخصّص.](/learn/reusing-logic-with-custom-hooks#when-to-use-custom-hooks)
-### Are you reading some state to calculate the next state? {/*are-you-reading-some-state-to-calculate-the-next-state*/}
+### هل تقرأ حالة لحساب الحالة التالية؟ {/*are-you-reading-some-state-to-calculate-the-next-state*/}
-This Effect updates the `messages` state variable with a newly created array every time a new message arrives:
+يحدّث هذا التأثير متغير الحالة `messages` بمصفوفة جديدة في كل مرة تصل رسالة جديدة:
```js {2,6-8}
function ChatRoom({ roomId }) {
@@ -569,7 +569,7 @@ function ChatRoom({ roomId }) {
// ...
```
-It uses the `messages` variable to [create a new array](/learn/updating-arrays-in-state) starting with all the existing messages and adds the new message at the end. However, since `messages` is a reactive value read by an Effect, it must be a dependency:
+يستخدم متغير `messages` لـ[إنشاء مصفوفة جديدة](/learn/updating-arrays-in-state) تبدأ بكل الرسائل القائمة ويضيف الرسالة الجديدة في النهاية. لكن بما أن `messages` قيمة تفاعلية يقرأها التأثير، يجب أن تكون تبعية:
```js {7,10}
function ChatRoom({ roomId }) {
@@ -585,11 +585,11 @@ function ChatRoom({ roomId }) {
// ...
```
-And making `messages` a dependency introduces a problem.
+وجعل `messages` تبعية يخلق مشكلة.
-Every time you receive a message, `setMessages()` causes the component to re-render with a new `messages` array that includes the received message. However, since this Effect now depends on `messages`, this will *also* re-synchronize the Effect. So every new message will make the chat re-connect. The user would not like that!
+في كل مرة تصل فيها رسالة، يتسبب `setMessages()` في إعادة تصيير المكوّن بمصفوفة `messages` جديدة تتضمن الرسالة المستلمة. لكن بما أن التأثير يعتمد الآن على `messages`، فسيُعاد أيضاً *مزامنة* التأثير. فيعيد كل رسالة جديدة اتصال المحادثة. المستخدم لا يريد ذلك!
-To fix the issue, don't read `messages` inside the Effect. Instead, pass an [updater function](/reference/react/useState#updating-state-based-on-the-previous-state) to `setMessages`:
+لإصلاح المشكلة، لا تقرأ `messages` داخل التأثير. بدلاً من ذلك، مرّر [دالة تحديث](/reference/react/useState#updating-state-based-on-the-previous-state) إلى `setMessages`:
```js {7,10}
function ChatRoom({ roomId }) {
@@ -605,11 +605,11 @@ function ChatRoom({ roomId }) {
// ...
```
-**Notice how your Effect does not read the `messages` variable at all now.** You only need to pass an updater function like `msgs => [...msgs, receivedMessage]`. React [puts your updater function in a queue](/learn/queueing-a-series-of-state-updates) and will provide the `msgs` argument to it during the next render. This is why the Effect itself doesn't need to depend on `messages` anymore. As a result of this fix, receiving a chat message will no longer make the chat re-connect.
+**لاحظ أن تأثيرك لا يقرأ متغير `messages` إطلاقاً الآن.** تحتاج فقط إلى تمرير دالة تحديث مثل `msgs => [...msgs, receivedMessage]`. React [يضع دالة التحديث في طابور](/learn/queueing-a-series-of-state-updates) ويزوّدها بالوسيط `msgs` أثناء التصيير التالي. لذلك لا يحتاج التأثير نفسه إلى الاعتماد على `messages` بعد الآن. نتيجة هذا الإصلاح، استلام رسالة محادثة لن يجعل المحادثة تعيد الاتصال.
-### Do you want to read a value without "reacting" to its changes? {/*do-you-want-to-read-a-value-without-reacting-to-its-changes*/}
+### هل تريد قراءة قيمة دون «التفاعل» مع تغيّراتها؟ {/*do-you-want-to-read-a-value-without-reacting-to-its-changes*/}
-Suppose that you want to play a sound when the user receives a new message unless `isMuted` is `true`:
+لنقل تريد تشغيل صوت عند استلام المستخدم رسالة جديدة ما لم يكن `isMuted` هو `true`:
```js {3,10-12}
function ChatRoom({ roomId }) {
@@ -628,7 +628,7 @@ function ChatRoom({ roomId }) {
// ...
```
-Since your Effect now uses `isMuted` in its code, you have to add it to the dependencies:
+وبما أن التأثير يستخدم الآن `isMuted` في شيفرته، يجب إضافته إلى التبعيات:
```js {10,15}
function ChatRoom({ roomId }) {
@@ -649,9 +649,9 @@ function ChatRoom({ roomId }) {
// ...
```
-The problem is that every time `isMuted` changes (for example, when the user presses the "Muted" toggle), the Effect will re-synchronize, and reconnect to the chat. This is not the desired user experience! (In this example, even disabling the linter would not work--if you do that, `isMuted` would get "stuck" with its old value.)
+المشكلة أنه في كل مرة يتغيّر فيها `isMuted` (مثلاً عند الضغط على مفتاح «Muted»)، يعيد التأثير المزامنة ويعيد الاتصال بالمحادثة. هذا ليس تجربة المستخدم المرغوبة! (في هذا المثال، حتى تعطيل المُدقِّق لا يعمل—إن فعلت، يبقى `isMuted` «عالقاً» بقيمته القديمة.)
-To solve this problem, you need to extract the logic that shouldn't be reactive out of the Effect. You don't want this Effect to "react" to the changes in `isMuted`. [Move this non-reactive piece of logic into an Effect Event:](/learn/separating-events-from-effects#declaring-an-effect-event)
+لحل المشكلة، استخرج المنطق الذي لا ينبغي أن يكون تفاعلياً من التأثير. لا تريد لهذا التأثير أن «يتفاعل» مع تغيّرات `isMuted`. [انقل هذا الجزء غير التفاعلي إلى حدث تأثير Effect Event:](/learn/separating-events-from-effects#declaring-an-effect-event)
```js {1,7-12,18,21}
import { useState, useEffect, useEffectEvent } from 'react';
@@ -678,11 +678,11 @@ function ChatRoom({ roomId }) {
// ...
```
-Effect Events let you split an Effect into reactive parts (which should "react" to reactive values like `roomId` and their changes) and non-reactive parts (which only read their latest values, like `onMessage` reads `isMuted`). **Now that you read `isMuted` inside an Effect Event, it doesn't need to be a dependency of your Effect.** As a result, the chat won't re-connect when you toggle the "Muted" setting on and off, solving the original issue!
+أحداث التأثير Effect Events تتيح تقسيم التأثير إلى أجزاء تفاعلية (ينبغي أن «تتفاعل» مع قيم مثل `roomId` وتغيّراتها) وأجزاء غير تفاعلية (تقرأ أحدث قيمها فقط، كما يقرأ `onMessage` قيمة `isMuted`). **وبما أنك تقرأ `isMuted` داخل حدث تأثير، لا يحتاج إلى أن يكون تبعية لتأثيرك.** النتيجة: لن تعيد المحادثة الاتصال عند تبديل إعداد «Muted»، فيُحلّ السلوك الأصلي!
-#### Wrapping an event handler from the props {/*wrapping-an-event-handler-from-the-props*/}
+#### لف معالج حدث من الخصائص {/*wrapping-an-event-handler-from-the-props*/}
-You might run into a similar problem when your component receives an event handler as a prop:
+قد تواجه مشكلة مماثلة عندما يستلم مكوّنك معالج حدث كخاصية:
```js {1,8,11}
function ChatRoom({ roomId, onReceiveMessage }) {
@@ -699,7 +699,7 @@ function ChatRoom({ roomId, onReceiveMessage }) {
// ...
```
-Suppose that the parent component passes a *different* `onReceiveMessage` function on every render:
+لنقل أن المكوّن الأب يمرّر دالة `onReceiveMessage` *مختلفة* في كل تصيير:
```js {3-5}
```
-Since `onReceiveMessage` is a dependency, it would cause the Effect to re-synchronize after every parent re-render. This would make it re-connect to the chat. To solve this, wrap the call in an Effect Event:
+وبما أن `onReceiveMessage` تبعية، ستسبب إعادة مزامنة التأثير بعد كل إعادة تصيير للأب. فيعيد الاتصال بالمحادثة. لحل ذلك، لفّ الاستدعاء في حدث تأثير:
```js {4-6,12,15}
function ChatRoom({ roomId, onReceiveMessage }) {
@@ -731,13 +731,13 @@ function ChatRoom({ roomId, onReceiveMessage }) {
// ...
```
-Effect Events aren't reactive, so you don't need to specify them as dependencies. As a result, the chat will no longer re-connect even if the parent component passes a function that's different on every re-render.
+أحداث التأثير ليست تفاعلية، فلا تحتاج إلى ذكرها كتبعيات. النتيجة: لن تعيد المحادثة الاتصال حتى لو مرّر الأب دالة مختلفة في كل إعادة تصيير.
-#### Separating reactive and non-reactive code {/*separating-reactive-and-non-reactive-code*/}
+#### فصل الشيفرة التفاعلية عن غير التفاعلية {/*separating-reactive-and-non-reactive-code*/}
-In this example, you want to log a visit every time `roomId` changes. You want to include the current `notificationCount` with every log, but you *don't* want a change to `notificationCount` to trigger a log event.
+في هذا المثال، تريد تسجيل زيارة في كل مرة يتغيّر فيها `roomId`. تريد تضمين `notificationCount` الحالي مع كل سجل، لكنك *لا* تريد أن يطلق تغيّر `notificationCount` حدث تسجيل إضافياً.
-The solution is again to split out the non-reactive code into an Effect Event:
+الحل مرة أخرى هو استخراج الشيفرة غير التفاعلية إلى حدث تأثير:
```js {2-4,7}
function Chat({ roomId, notificationCount }) {
@@ -752,11 +752,11 @@ function Chat({ roomId, notificationCount }) {
}
```
-You want your logic to be reactive with regards to `roomId`, so you read `roomId` inside of your Effect. However, you don't want a change to `notificationCount` to log an extra visit, so you read `notificationCount` inside of the Effect Event. [Learn more about reading the latest props and state from Effects using Effect Events.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events)
+تريد منطقك أن يتفاعل مع `roomId`، فتقرأ `roomId` داخل التأثير. لكنك لا تريد أن يؤدي تغيّر `notificationCount` إلى تسجيل زيارة إضافية، فتقرأ `notificationCount` داخل حدث التأثير. [تعرّف أكثر على قراءة أحدث الخصائص والحالة من التأثيرات باستخدام أحداث التأثير.](/learn/separating-events-from-effects#reading-latest-props-and-state-with-effect-events)
-### Does some reactive value change unintentionally? {/*does-some-reactive-value-change-unintentionally*/}
+### هل تتغيّر قيمة تفاعلية دون قصد؟ {/*does-some-reactive-value-change-unintentionally*/}
-Sometimes, you *do* want your Effect to "react" to a certain value, but that value changes more often than you'd like--and might not reflect any actual change from the user's perspective. For example, let's say that you create an `options` object in the body of your component, and then read that object from inside of your Effect:
+أحياناً *تريد* أن «يتفاعل» تأثيرك مع قيمة معيّنة، لكنها تتغيّر أكثر مما تريد—ولا تعكس بالضرورة تغيّراً حقيقياً من منظور المستخدم. مثلاً، لنقل تنشئ كائن `options` في جسم مكوّنك، ثم تقرأه من داخل التأثير:
```js {3-6,9}
function ChatRoom({ roomId }) {
@@ -772,7 +772,7 @@ function ChatRoom({ roomId }) {
// ...
```
-This object is declared in the component body, so it's a [reactive value.](/learn/lifecycle-of-reactive-effects#effects-react-to-reactive-values) When you read a reactive value like this inside an Effect, you declare it as a dependency. This ensures your Effect "reacts" to its changes:
+هذا الكائن معرّف في جسم المكوّن، فهو [قيمة تفاعلية.](/learn/lifecycle-of-reactive-effects#effects-react-to-reactive-values) عندما تقرأ قيمة تفاعلية هكذا داخل تأثير، تعلنها كتبعية. هذا يضمن أن التأثير «يتفاعل» مع تغيّراتها:
```js {3,6}
// ...
@@ -784,7 +784,7 @@ This object is declared in the component body, so it's a [reactive value.](/lear
// ...
```
-It is important to declare it as a dependency! This ensures, for example, that if the `roomId` changes, your Effect will re-connect to the chat with the new `options`. However, there is also a problem with the code above. To see it, try typing into the input in the sandbox below, and watch what happens in the console:
+من المهم إعلانها كتبعية! هذا يضمن مثلاً أنه إن تغيّر `roomId`، يعيد تأثيرك الاتصال بالمحادثة بـ`options` الجديدة. لكن هناك أيضاً مشكلة في الشيفرة أعلاه. لرؤيتها، اكتب في الحقل في الـsandbox أدناه وراقب الـconsole:
@@ -861,11 +861,11 @@ button { margin-left: 10px; }
-In the sandbox above, the input only updates the `message` state variable. From the user's perspective, this should not affect the chat connection. However, every time you update the `message`, your component re-renders. When your component re-renders, the code inside of it runs again from scratch.
+في الـsandbox أعلاه، الحقل يحدّث فقط متغير الحالة `message`. من منظور المستخدم، لا ينبغي أن يؤثر ذلك على اتصال المحادثة. لكن في كل مرة تحدّث فيها `message`، يُعاد تصيير مكوّنك. وعند إعادة التصيير، تعاد تشغيل الشيفرة داخله من البداية.
-A new `options` object is created from scratch on every re-render of the `ChatRoom` component. React sees that the `options` object is a *different object* from the `options` object created during the last render. This is why it re-synchronizes your Effect (which depends on `options`), and the chat re-connects as you type.
+يُنشأ كائن `options` جديد من الصفر في كل إعادة تصيير لمكوّن `ChatRoom`. يرى React أن كائن `options` *مختلف* عن الكائن المُنشأ في التصيير السابق. لذلك يعيد مزامنة التأثير (الذي يعتمد على `options`)، فتعيد المحادثة الاتصال أثناء الكتابة.
-**This problem only affects objects and functions. In JavaScript, each newly created object and function is considered distinct from all the others. It doesn't matter that the contents inside of them may be the same!**
+**هذه المشكلة تصيب الكائنات والدوال فقط. في JavaScript، كل كائن ودالة يُنشآن حديثاً يُعتبران مختلفين عن غيرهما. لا يهم أن المحتوى قد يكون نفسه!**
```js {7-8}
// During the first render
@@ -878,13 +878,13 @@ const options2 = { serverUrl: 'https://localhost:1234', roomId: 'music' };
console.log(Object.is(options1, options2)); // false
```
-**Object and function dependencies can make your Effect re-synchronize more often than you need.**
+**تبعيات الكائنات والدوال يمكن أن تجعل تأثيرك يعيد المزامنة أكثر من اللازم.**
-This is why, whenever possible, you should try to avoid objects and functions as your Effect's dependencies. Instead, try moving them outside the component, inside the Effect, or extracting primitive values out of them.
+لذلك، كلما أمكن، تجنّب جعل الكائنات والدوال تبعيات لتأثيرك. بدلاً من ذلك، انقلها خارج المكوّن أو داخل التأثير، أو استخرج منها قيماً أولية.
-#### Move static objects and functions outside your component {/*move-static-objects-and-functions-outside-your-component*/}
+#### نقل كائنات ودوال ثابتة خارج المكوّن {/*move-static-objects-and-functions-outside-your-component*/}
-If the object does not depend on any props and state, you can move that object outside your component:
+إن لم يعتمد الكائن على خصائص أو حالة، انقله خارج المكوّن:
```js {1-4,13}
const options = {
@@ -903,9 +903,9 @@ function ChatRoom() {
// ...
```
-This way, you *prove* to the linter that it's not reactive. It can't change as a result of a re-render, so it doesn't need to be a dependency. Now re-rendering `ChatRoom` won't cause your Effect to re-synchronize.
+بهذا *تثبت* للمُدقِّق أنه ليس تفاعلياً. لا يمكن أن يتغيّر بسبب إعادة التصيير، فلا يحتاج إلى أن يكون تبعية. إعادة تصيير `ChatRoom` لن تعيد مزامنة التأثير الآن.
-This works for functions too:
+ينطبق الأمر على الدوال أيضاً:
```js {1-6,12}
function createOptions() {
@@ -927,11 +927,11 @@ function ChatRoom() {
// ...
```
-Since `createOptions` is declared outside your component, it's not a reactive value. This is why it doesn't need to be specified in your Effect's dependencies, and why it won't ever cause your Effect to re-synchronize.
+وبما أن `createOptions` معرّفة خارج مكوّنك، فليست قيمة تفاعلية. لذلك لا تحتاج إلى أن تُذكر في تبعيات التأثير، ولن تسبب أبداً إعادة مزامنة غير مرغوبة.
-#### Move dynamic objects and functions inside your Effect {/*move-dynamic-objects-and-functions-inside-your-effect*/}
+#### نقل كائنات ودوال ديناميكية داخل التأثير {/*move-dynamic-objects-and-functions-inside-your-effect*/}
-If your object depends on some reactive value that may change as a result of a re-render, like a `roomId` prop, you can't pull it *outside* your component. You can, however, move its creation *inside* of your Effect's code:
+إن كان كائنك يعتمد على قيمة تفاعلية قد تتغيّر بإعادة التصيير، مثل خاصية `roomId`، لا يمكنك سحبه *خارج* المكوّن. لكن يمكنك نقل إنشائه *داخل* شيفرة التأثير:
```js {7-10,11,14}
const serverUrl = 'https://localhost:1234';
@@ -951,7 +951,7 @@ function ChatRoom({ roomId }) {
// ...
```
-Now that `options` is declared inside of your Effect, it is no longer a dependency of your Effect. Instead, the only reactive value used by your Effect is `roomId`. Since `roomId` is not an object or function, you can be sure that it won't be *unintentionally* different. In JavaScript, numbers and strings are compared by their content:
+وبما أن `options` أصبح معلناً داخل التأثير، لم يعد تبعية للتأثير. القيمة التفاعلية الوحيدة التي يستخدمها التأثير هي `roomId`. وبما أن `roomId` ليس كائناً ولا دالة، يمكنك التأكد أنه لن يختلف *دون قصد*. في JavaScript، تُقارن الأعداد والسلاسل بمحتواها:
```js {7-8}
// During the first render
@@ -964,7 +964,7 @@ const roomId2 = 'music';
console.log(Object.is(roomId1, roomId2)); // true
```
-Thanks to this fix, the chat no longer re-connects if you edit the input:
+بفضل هذا الإصلاح، لا تعيد المحادثة الاتصال عند تعديل الحقل:
@@ -1038,9 +1038,9 @@ button { margin-left: 10px; }
-However, it *does* re-connect when you change the `roomId` dropdown, as you would expect.
+لكنه *يعيد* الاتصال عند تغيّر قائمة `roomId` المنسدلة، كما تتوقع.
-This works for functions, too:
+ينطبق على الدوال أيضاً:
```js {7-12,14}
const serverUrl = 'https://localhost:1234';
@@ -1064,11 +1064,11 @@ function ChatRoom({ roomId }) {
// ...
```
-You can write your own functions to group pieces of logic inside your Effect. As long as you also declare them *inside* your Effect, they're not reactive values, and so they don't need to be dependencies of your Effect.
+يمكنك كتابة دوالك الخاصة لتجميع أجزاء المنطق داخل التأثير. ما دمت تعرّفها *داخل* التأثير أيضاً، فليست قيماً تفاعلية، ولا تحتاج إلى أن تكون تبعيات.
-#### Read primitive values from objects {/*read-primitive-values-from-objects*/}
+#### قراءة قيم أولية من الكائنات {/*read-primitive-values-from-objects*/}
-Sometimes, you may receive an object from props:
+أحياناً تستلم كائناً من الخصائص:
```js {1,5,8}
function ChatRoom({ options }) {
@@ -1082,7 +1082,7 @@ function ChatRoom({ options }) {
// ...
```
-The risk here is that the parent component will create the object during rendering:
+الخطر هنا أن المكوّن الأب قد ينشئ الكائن أثناء التصيير:
```js {3-6}
```
-This would cause your Effect to re-connect every time the parent component re-renders. To fix this, read information from the object *outside* the Effect, and avoid having object and function dependencies:
+هذا يجعل تأثيرك يعيد الاتصال في كل إعادة تصيير للأب. لإصلاحه، اقرأ المعلومات من الكائن *خارج* التأثير، وتجنّب تبعيات الكائنات والدوال:
```js {4,7-8,12}
function ChatRoom({ options }) {
@@ -1112,11 +1112,11 @@ function ChatRoom({ options }) {
// ...
```
-The logic gets a little repetitive (you read some values from an object outside an Effect, and then create an object with the same values inside the Effect). But it makes it very explicit what information your Effect *actually* depends on. If an object is re-created unintentionally by the parent component, the chat would not re-connect. However, if `options.roomId` or `options.serverUrl` really are different, the chat would re-connect.
+يصبح المنطق مكرراً قليلاً (تقرأ قيماً من كائن خارج التأثير، ثم تنشئ كائناً بنفس القيم داخل التأثير). لكنه يجعل ما يعتمد عليه التأثير *فعلاً* صريحاً جداً. إن أعاد الأب إنشاء الكائن دون قصد، لن تعيد المحادثة الاتصال. أما إن كان `options.roomId` أو `options.serverUrl` مختلفين فعلاً، فستعيد الاتصال.
-#### Calculate primitive values from functions {/*calculate-primitive-values-from-functions*/}
+#### حساب قيم أولية من الدوال {/*calculate-primitive-values-from-functions*/}
-The same approach can work for functions. For example, suppose the parent component passes a function:
+ينفع نفس النهج مع الدوال. مثلاً، لنقل يمرّر الأب دالة:
```js {3-8}
```
-To avoid making it a dependency (and causing it to re-connect on re-renders), call it outside the Effect. This gives you the `roomId` and `serverUrl` values that aren't objects, and that you can read from inside your Effect:
+لتجنّب جعلها تبعية (وما يسببه من إعادة اتصال عند إعادة التصيير)، استدعها خارج التأثير. يعطيك ذلك قيم `roomId` و`serverUrl` ليستا كائنين، ويمكنك قراءتهما من داخل التأثير:
```js {1,4}
function ChatRoom({ getOptions }) {
@@ -1148,32 +1148,32 @@ function ChatRoom({ getOptions }) {
// ...
```
-This only works for [pure](/learn/keeping-components-pure) functions because they are safe to call during rendering. If your function is an event handler, but you don't want its changes to re-synchronize your Effect, [wrap it into an Effect Event instead.](#do-you-want-to-read-a-value-without-reacting-to-its-changes)
+هذا ينفع مع [الدوال النقية](/learn/keeping-components-pure) لأن استدعاءها آمناً أثناء التصيير. إن كانت دالتك معالج حدث، لكنك لا تريد أن تغيّراتها تعيد مزامنة التأثير، [لفّها في حدث تأثير بدلاً من ذلك.](#do-you-want-to-read-a-value-without-reacting-to-its-changes)
-- Dependencies should always match the code.
-- When you're not happy with your dependencies, what you need to edit is the code.
-- Suppressing the linter leads to very confusing bugs, and you should always avoid it.
-- To remove a dependency, you need to "prove" to the linter that it's not necessary.
-- If some code should run in response to a specific interaction, move that code to an event handler.
-- If different parts of your Effect should re-run for different reasons, split it into several Effects.
-- If you want to update some state based on the previous state, pass an updater function.
-- If you want to read the latest value without "reacting" it, extract an Effect Event from your Effect.
-- In JavaScript, objects and functions are considered different if they were created at different times.
-- Try to avoid object and function dependencies. Move them outside the component or inside the Effect.
+- يجب أن تطابق التبعيات الشيفرة دائماً.
+- إن لم ترضَ عن تبعياتك، فما تحتاج تعديله هو الشيفرة.
+- كتم المُدقِّق يؤدي إلى علل مربكة، وتجنّبه دائماً أفضل.
+- لإزالة تبعية، «أثبت» للمُدقِّق أنها غير لازمة.
+- إن كان ينبغي تشغيل شيفرة استجابةً لتفاعل محدد، انقلها إلى معالج حدث.
+- إن كان أجزاء مختلفة من التأثير يجب أن تعاد لأسباب مختلفة، قسّمه إلى عدة تأثيرات.
+- إن أردت تحديث حالة بناءً على الحالة السابقة، مرّر دالة تحديث.
+- إن أردت قراءة أحدث قيمة دون «التفاعل» معها، استخرج حدث تأثير من التأثير.
+- في JavaScript، تُعتبر الكائنات والدوال مختلفة إذا أُنشئت في أوقات مختلفة.
+- تجنّب تبعيات الكائنات والدوال قدر الإمكان. انقلها خارج المكوّن أو داخل التأثير.
-#### Fix a resetting interval {/*fix-a-resetting-interval*/}
+#### إصلاح فترة تُعاد إنشاؤها {/*fix-a-resetting-interval*/}
-This Effect sets up an interval that ticks every second. You've noticed something strange happening: it seems like the interval gets destroyed and re-created every time it ticks. Fix the code so that the interval doesn't get constantly re-created.
+يضبط هذا التأثير فترة تدق كل ثانية. لاحظت شيئاً غريباً: يبدو أن الفترة تُدمَر وتُعاد إنشاؤها في كل دقة. أصلح الشيفرة حتى لا تُعاد إنشاء الفترة باستمرار.
-It seems like this Effect's code depends on `count`. Is there some way to not need this dependency? There should be a way to update the `count` state based on its previous value without adding a dependency on that value.
+يبدو أن شيفرة التأثير تعتمد على `count`. هل هناك طريقة لعدم الحاجة إلى هذه التبعية؟ ينبغي أن يكون بإمكانك تحديث حالة `count` بناءً على قيمتها السابقة دون إضافة تبعية عليها.
@@ -1205,9 +1205,9 @@ export default function Timer() {
-You want to update the `count` state to be `count + 1` from inside the Effect. However, this makes your Effect depend on `count`, which changes with every tick, and that's why your interval gets re-created on every tick.
+تريد تحديث حالة `count` لتصبح `count + 1` من داخل التأثير. لكن هذا يجعل التأثير يعتمد على `count`، الذي يتغيّر مع كل دقة، ولهذا تُعاد إنشاء الفترة في كل دقة.
-To solve this, use the [updater function](/reference/react/useState#updating-state-based-on-the-previous-state) and write `setCount(c => c + 1)` instead of `setCount(count + 1)`:
+لحل ذلك، استخدم [دالة التحديث](/reference/react/useState#updating-state-based-on-the-previous-state) واكتب `setCount(c => c + 1)` بدلاً من `setCount(count + 1)`:
@@ -1235,19 +1235,19 @@ export default function Timer() {
-Instead of reading `count` inside the Effect, you pass a `c => c + 1` instruction ("increment this number!") to React. React will apply it on the next render. And since you don't need to read the value of `count` inside your Effect anymore, you can keep your Effect's dependencies empty (`[]`). This prevents your Effect from re-creating the interval on every tick.
+بدلاً من قراءة `count` داخل التأثير، تمرّر تعليمات `c => c + 1` («زاد هذا العدد!») إلى React. يطبّقها React في التصيير التالي. وبما أنك لم تعد تحتاج قراءة `count` داخل التأثير، يمكنك الإبقاء على تبعيات التأثير فارغة (`[]`). يمنع ذلك إعادة إنشاء الفترة في كل دقة.
-#### Fix a retriggering animation {/*fix-a-retriggering-animation*/}
+#### إصلاح إعادة تشغيل الرسوم المتحركة {/*fix-a-retriggering-animation*/}
-In this example, when you press "Show", a welcome message fades in. The animation takes a second. When you press "Remove", the welcome message immediately disappears. The logic for the fade-in animation is implemented in the `animation.js` file as plain JavaScript [animation loop.](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) You don't need to change that logic. You can treat it as a third-party library. Your Effect creates an instance of `FadeInAnimation` for the DOM node, and then calls `start(duration)` or `stop()` to control the animation. The `duration` is controlled by a slider. Adjust the slider and see how the animation changes.
+في هذا المثال، عند الضغط على «Show»، تظهر رسالة ترحيب بتأثير تلاشٍ. الرسوم تستغرق ثانية. عند «Remove»، تختفي الرسالة فوراً. منطق التلاشٍ منفّذ في `animation.js` كـ[حلقة رسوم](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) بJavaScript عادي. لا تحتاج تغيير ذلك. يمكنك اعتباره مكتبة طرف ثالث. يُنشئ تأثيرك مثيل `FadeInAnimation` لعقدة DOM، ثم يستدعي `start(duration)` أو `stop()` للتحكم. يتحكم منزلق في `duration`. حرّك المنزلق ولاحظ التغيير.
-This code already works, but there is something you want to change. Currently, when you move the slider that controls the `duration` state variable, it retriggers the animation. Change the behavior so that the Effect does not "react" to the `duration` variable. When you press "Show", the Effect should use the current `duration` on the slider. However, moving the slider itself should not by itself retrigger the animation.
+الشيفرة تعمل، لكن تريد تغييراً: حالياً، عند تحريك المنزلق الذي يتحكم في `duration`، تُعاد تشغيل الرسوم. غيّر السلوك بحيث لا «يتفاعل» التأثير مع `duration`. عند «Show»، يستخدم التأثير قيمة `duration` الحالية من المنزلق. لكن تحريك المنزلق وحده لا ينبغي أن يعيد تشغيل الرسوم من تلقاء نفسه.
-Is there a line of code inside the Effect that should not be reactive? How can you move non-reactive code out of the Effect?
+هل هناك سطر في التأثير لا ينبغي أن يكون تفاعلياً؟ كيف تنقل الشيفرة غير التفاعلية خارج التأثير؟
@@ -1360,7 +1360,7 @@ html, body { min-height: 300px; }
-Your Effect needs to read the latest value of `duration`, but you don't want it to "react" to changes in `duration`. You use `duration` to start the animation, but starting animation isn't reactive. Extract the non-reactive line of code into an Effect Event, and call that function from your Effect.
+يحتاج تأثيرك إلى قراءة أحدث قيمة `duration`، لكنك لا تريد أن «يتفاعل» مع تغيّراتها. تستخدم `duration` لبدء الرسوم، لكن بدء الرسوم ليس تفاعلياً. استخرج السطر غير التفاعلي إلى حدث تأثير، واستدعِه من التأثير.
@@ -1467,19 +1467,19 @@ html, body { min-height: 300px; }
-Effect Events like `onAppear` are not reactive, so you can read `duration` inside without retriggering the animation.
+أحداث التأثير مثل `onAppear` ليست تفاعلية، فيمكنك قراءة `duration` داخلها دون إعادة تشغيل الرسوم.
-#### Fix a reconnecting chat {/*fix-a-reconnecting-chat*/}
+#### إصلاح محادثة تعيد الاتصال {/*fix-a-reconnecting-chat*/}
-In this example, every time you press "Toggle theme", the chat re-connects. Why does this happen? Fix the mistake so that the chat re-connects only when you edit the Server URL or choose a different chat room.
+في هذا المثال، في كل مرة تضغط فيها «Toggle theme»، تعيد المحادثة الاتصال. لماذا؟ أصلح الخطأ بحيث تعيد الاتصال فقط عند تعديل عنوان الخادم أو اختيار غرفة محادثة مختلفة.
-Treat `chat.js` as an external third-party library: you can consult it to check its API, but don't edit it.
+اعتبر `chat.js` مكتبة طرف ثالث خارجية: يمكنك الرجوع إليها لفحص واجهتها، لكن لا تعدّلها.
-There's more than one way to fix this, but ultimately you want to avoid having an object as your dependency.
+هناك أكثر من طريقة للإصلاح، لكن المطلوب في النهاية تجنّب كائن كتبعية.
@@ -1573,9 +1573,9 @@ label, button { display: block; margin-bottom: 5px; }
-Your Effect is re-running because it depends on the `options` object. Objects can be re-created unintentionally, you should try to avoid them as dependencies of your Effects whenever possible.
+يعاد تشغيل تأثيرك لأنه يعتمد على كائن `options`. قد تُعاد إنشاء الكائنات دون قصد، فتجنّبها كتبعيات كلما أمكن.
-The least invasive fix is to read `roomId` and `serverUrl` right outside the Effect, and then make the Effect depend on those primitive values (which can't change unintentionally). Inside the Effect, create an object and pass it to `createConnection`:
+أقل تدخّل هو قراءة `roomId` و`serverUrl` مباشرة خارج التأثير، ثم جعل التأثير يعتمد على تلك القيم الأولية (التي لا تتغيّر دون قصد). داخل التأثير، أنشئ كائناً ومرّره إلى `createConnection`:
@@ -1669,7 +1669,7 @@ label, button { display: block; margin-bottom: 5px; }
-It would be even better to replace the object `options` prop with the more specific `roomId` and `serverUrl` props:
+أفضل من ذلك استبدال خاصية الكائن `options` بالخصائص الأكثر تحديداً `roomId` و`serverUrl`:
@@ -1760,25 +1760,25 @@ label, button { display: block; margin-bottom: 5px; }
-Sticking to primitive props where possible makes it easier to optimize your components later.
+الالتزام بالخصائص الأولية حيثما أمكن يسهّل تحسين مكوّناتك لاحقاً.
-#### Fix a reconnecting chat, again {/*fix-a-reconnecting-chat-again*/}
+#### إصلاح محادثة تعيد الاتصال، مرة أخرى {/*fix-a-reconnecting-chat-again*/}
-This example connects to the chat either with or without encryption. Toggle the checkbox and notice the different messages in the console when the encryption is on and off. Try changing the room. Then, try toggling the theme. When you're connected to a chat room, you will receive new messages every few seconds. Verify that their color matches the theme you've picked.
+يتصل هذا المثال بالمحادثة مع تشفير أو بدونه. بدّل مربع الاختيار ولاحظ رسائل الـconsole المختلفة عند التفعيل والإلغاء. جرّب تغيير الغرفة. ثم بدّل السمة. عند الاتصال بغرفة، تصل رسائل جديدة كل بضع ثوانٍ. تحقق أن لونها يطابق السمة التي اخترتها.
-In this example, the chat re-connects every time you try to change the theme. Fix this. After the fix, changing the theme should not re-connect the chat, but toggling encryption settings or changing the room should re-connect.
+في هذا المثال، تعيد المحادثة الاتصال في كل مرة تحاول تغيير السمة. أصلح ذلك. بعد الإصلاح، تغيير السمة لا يعيد الاتصال، لكن تبديل التشفير أو تغيير الغرفة يعيدان الاتصال.
-Don't change any code in `chat.js`. Other than that, you can change any code as long as it results in the same behavior. For example, you may find it helpful to change which props are being passed down.
+لا تغيّر شيفرة `chat.js`. عدا ذلك، يمكنك تغيير أي شيفرة طالما بقي السلوك نفسه. قد يفيدك تغيير الخصائص الممرّرة.
-You're passing down two functions: `onMessage` and `createConnection`. Both of them are created from scratch every time `App` re-renders. They are considered to be new values every time, which is why they re-trigger your Effect.
+تمرّر دالتين: `onMessage` و`createConnection`. كلاهما يُنشآن من جديد في كل تصيير لـ`App`. تُعتبران قيمتين جديدتين في كل مرة، ولهذا يعيدان تشغيل التأثير.
-One of these functions is an event handler. Do you know some way to call an event handler an Effect without "reacting" to the new values of the event handler function? That would come in handy!
+إحدى الدالتين معالج حدث. هل تعرف طريقة لاستدعاء معالج حدث من التأثير دون «التفاعل» مع قيم الدالة الجديدة؟ سيفيدك ذلك!
-Another of these functions only exists to pass some state to an imported API method. Is this function really necessary? What is the essential information that's being passed down? You might need to move some imports from `App.js` to `ChatRoom.js`.
+الدالة الأخرى موجودة فقط لتمرير حالة إلى واجهة API مستوردة. هل هي ضرورية فعلاً؟ ما المعلومة الجوهرية الممرّرة؟ قد تحتاج نقل بعض الاستيرادات من `App.js` إلى `ChatRoom.js`.
@@ -1993,11 +1993,11 @@ label, button { display: block; margin-bottom: 5px; }
-There's more than one correct way to solve this, but here is one possible solution.
+هناك أكثر من حل صحيح، وهذا أحدها.
-In the original example, toggling the theme caused different `onMessage` and `createConnection` functions to be created and passed down. Since the Effect depended on these functions, the chat would re-connect every time you toggle the theme.
+في المثال الأصلي، تبديل السمة أنشأ دالتين مختلفتين `onMessage` و`createConnection` ومرّرهما. وبما أن التأثير يعتمد على هاتين الدالتين، كانت المحادثة تعيد الاتصال في كل تبديل للسمة.
-To fix the problem with `onMessage`, you needed to wrap it into an Effect Event:
+لمشكلة `onMessage`، يلزم لفّها في حدث تأثير:
```js {1,2,6}
export default function ChatRoom({ roomId, createConnection, onMessage }) {
@@ -2009,9 +2009,9 @@ export default function ChatRoom({ roomId, createConnection, onMessage }) {
// ...
```
-Unlike the `onMessage` prop, the `onReceiveMessage` Effect Event is not reactive. This is why it doesn't need to be a dependency of your Effect. As a result, changes to `onMessage` won't cause the chat to re-connect.
+بخلاف خاصية `onMessage`، حدث التأثير `onReceiveMessage` ليس تفاعلياً. لذلك لا يحتاج أن يكون تبعية لتأثيرك. ونتيجة لذلك، تغيّرات `onMessage` لن تجعل المحادثة تعيد الاتصال.
-You can't do the same with `createConnection` because it *should* be reactive. You *want* the Effect to re-trigger if the user switches between an encrypted and an unencryption connection, or if the user switches the current room. However, because `createConnection` is a function, you can't check whether the information it reads has *actually* changed or not. To solve this, instead of passing `createConnection` down from the `App` component, pass the raw `roomId` and `isEncrypted` values:
+لا يمكنك فعل الشيء نفسه مع `createConnection` لأنه *ينبغي* أن يكون تفاعلياً. *تريد* أن يعيد التأثير التشغيل إذا بدّل المستخدم بين اتصال مشفّر وغير مشفّر، أو إذا غيّر الغرفة الحالية. لكن بما أن `createConnection` دالة، لا يمكنك التحقق مما إذا كانت المعلومات التي تقرأها قد *تغيّرت فعلاً* أم لا. لحل ذلك، بدلاً من تمرير `createConnection` من مكوّن `App`، مرّر القيم الخام `roomId` و`isEncrypted`:
```js {2-3}
```
-Now you can move the `createConnection` function *inside* the Effect instead of passing it down from the `App`:
+الآن يمكنك نقل دالة `createConnection` *داخل* التأثير بدلاً من تمريرها من `App`:
```js {1-4,6,10-20}
import {
@@ -2049,7 +2049,7 @@ export default function ChatRoom({ roomId, isEncrypted, onMessage }) {
// ...
```
-After these two changes, your Effect no longer depends on any function values:
+بعد هذين التعديلين، لم يعد تأثيرك يعتمد على أي قيم دوال:
```js {1,8,10,21}
export default function ChatRoom({ roomId, isEncrypted, onMessage }) { // Reactive values
@@ -2075,7 +2075,7 @@ export default function ChatRoom({ roomId, isEncrypted, onMessage }) { // Reacti
}, [roomId, isEncrypted]); // ✅ All dependencies declared
```
-As a result, the chat re-connects only when something meaningful (`roomId` or `isEncrypted`) changes:
+فالمحادثة تعيد الاتصال فقط عند تغيّر شيء ذي معنى (`roomId` أو `isEncrypted`):
diff --git a/src/content/learn/responding-to-events.md b/src/content/learn/responding-to-events.md
index 78474217c..ae59eced8 100644
--- a/src/content/learn/responding-to-events.md
+++ b/src/content/learn/responding-to-events.md
@@ -1,24 +1,24 @@
---
-title: Responding to Events
+title: الاستجابة للأحداث
---
-React lets you add *event handlers* to your JSX. Event handlers are your own functions that will be triggered in response to interactions like clicking, hovering, focusing form inputs, and so on.
+يتيح لك React إضافة *معالجات أحداث* إلى JSX. معالجات الأحداث دوالك الخاصة التي تُستدعى استجابةً للتفاعلات مثل النقر، التمرير، تركيز حقول النماذج، وغير ذلك.
-* Different ways to write an event handler
-* How to pass event handling logic from a parent component
-* How events propagate and how to stop them
+* طرق مختلفة لكتابة معالج حدث
+* كيف تمرّر منطق معالجة الأحداث من مكوّن أب
+* كيف تنتشر الأحداث وكيف توقفها
-## Adding event handlers {/*adding-event-handlers*/}
+## إضافة معالجات أحداث {/*adding-event-handlers*/}
-To add an event handler, you will first define a function and then [pass it as a prop](/learn/passing-props-to-a-component) to the appropriate JSX tag. For example, here is a button that doesn't do anything yet:
+لإضافة معالج حدث، عرّف دالة ثم [مرّرها كخاصية](/learn/passing-props-to-a-component) إلى وسم JSX المناسب. مثلًا، زر لا يفعل شيئًا بعد:
@@ -34,11 +34,11 @@ export default function Button() {
-You can make it show a message when a user clicks by following these three steps:
+لجعله يعرض رسالة عند النقر، اتبع ثلاث خطوات:
-1. Declare a function called `handleClick` *inside* your `Button` component.
-2. Implement the logic inside that function (use `alert` to show the message).
-3. Add `onClick={handleClick}` to the `