diff --git a/src/content/learn/adding-interactivity.md b/src/content/learn/adding-interactivity.md
index 936c27214..d860b436c 100644
--- a/src/content/learn/adding-interactivity.md
+++ b/src/content/learn/adding-interactivity.md
@@ -798,4 +798,4 @@ function ItemList({ artworks, onToggle }) {
إذهب الى [الإستجابة الى الاحداث](/learn/responding-to-events) لتقرأ هذا الفصل صفحة بصفحة!
-أو، إذا كنت تفهم هذه المواضيع بالفعل، لماذا لا تقرأ عن [التحكم فى الحالة](/learn/managing-state)؟
+أو، إذا كنت تفهم هذه المواضيع بالفعل، لماذا لا تقرأ عن [إدارة الحالة](/learn/managing-state)؟
diff --git a/src/content/learn/reacting-to-input-with-state.md b/src/content/learn/reacting-to-input-with-state.md
index 522aa63a1..3144fe729 100644
--- a/src/content/learn/reacting-to-input-with-state.md
+++ b/src/content/learn/reacting-to-input-with-state.md
@@ -1,37 +1,38 @@
---
-title: Reacting to Input with State
+title: الاستجابة للمدخلات باستخدام الحالة
---
-React provides a declarative way to manipulate the UI. Instead of manipulating individual pieces of the UI directly, you describe the different states that your component can be in, and switch between them in response to the user input. This is similar to how designers think about the UI.
+توفر React طريقة تصريحيّة (declarative) لتعديل واجهة المستخدم (UI). فبدلًا من تعديل أجزاء منفردة من واجهة المستخدم مباشرةً، يمكنك وصف الحالات المختلفة التي يأخذها مكوّنك، والانتقال بينهم كاستجابة لمدخلات المستخدم. هذا مشابه لتصوّر المصمّمين عن واجهة المستخدم.
+
-* How declarative UI programming differs from imperative UI programming
-* How to enumerate the different visual states your component can be in
-* How to trigger the changes between the different visual states from code
-
+* كيف تختلف البرمجة التصريحيّة لواجهة المستخدم (declarative UI programming) عن البرمجة الأمريّة لواجهة المستخدم (imperative UI programming)
+* كيفية استعراض الحالات المرئية المختلفة التي يأخذها مكوّنك
+* كيفية تنشيط التغييرات بين الحالات المرئية المختلفة من خلال الكود
+
-## How declarative UI compares to imperative {/*how-declarative-ui-compares-to-imperative*/}
+## كيف تُقارَن واجهة المستخدم التصريحيّة (declarative UI) بالأمريّة (imperative) {/*how-declarative-ui-compares-to-imperative*/}
-When you design UI interactions, you probably think about how the UI *changes* in response to user actions. Consider a form that lets the user submit an answer:
+عندما تصمم تعاملات واجهة المستخدم، عليك غالبًا التفكير في كيفية *تغيّر* واجهة المستخدم كاستجابة لإجراءات المستخدم. فكر في نموذج يسمح للمستخدم بإرسال إجابة:
-* When you type something into the form, the "Submit" button **becomes enabled.**
-* When you press "Submit", both the form and the button **become disabled,** and a spinner **appears.**
-* If the network request succeeds, the form **gets hidden,** and the "Thank you" message **appears.**
-* If the network request fails, an error message **appears,** and the form **becomes enabled** again.
+* عندما تكتب شيئًا داخل النموذج، يصبح الزر "أرسل" **مفعلًا.**
+* عندما تضغط على "أرسل"، يصبح كلٌ من النموذج والزر **معطلا** و**يظهر** مؤشر التحميل.
+* لو نجح طلب الشبكة، يبدأ النموج **بالاختفاء،** و**تظهر** رسالة "شكرًا لك".
+* لو فشل طلب الشبكة، **تظهر** رسالة خطأٍ، ويصبح النموذج **مفعلًا** مجددا.
-In **imperative programming,** the above corresponds directly to how you implement interaction. You have to write the exact instructions to manipulate the UI depending on what just happened. Here's another way to think about this: imagine riding next to someone in a car and telling them turn by turn where to go.
+في **البرمجة الأمرية (imperative programming)**، يتوافق ما ذُكر أعلاه مباشرة مع طريقة تطبيق التعاملات. عليك أن تكتب التعليمات التامّة لتعديل واجهة المستخدم معتمدًا على ما حصل للتوّ. إليك طريقة أخرى لتفكر في هذا الأمر: تخيل نفسك راكبًا إلى جانب أحدهم في سيارة مع إخباره في كل منعطف تلو الآخر عن وجهة الذهاب.
-
+
-They don't know where you want to go, they just follow your commands. (And if you get the directions wrong, you end up in the wrong place!) It's called *imperative* because you have to "command" each element, from the spinner to the button, telling the computer *how* to update the UI.
+هو لا يعلم إلى أين تريد أن تذهب، هو يتبع أوامرك فقط. (ولو أنك أعطيته الاتجاهات الخاطئة، سوف ينتهي بك المطاف لوجهة خاطئة!) هذا يطلق عليه *أمري (imperative)* لأن عليك أن "تأمر" كل عنصر، بداية من مؤشر التحميل إلى الزر، مخبرًا الكمبيوتر عن *كيفية* تحديث واجهة المستخدم (UI).
-In this example of imperative UI programming, the form is built *without* React. It only uses the browser [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model):
+في هذا المثال للبرمجة الأمريّة لواجهة المستخدم، النموذج مبنيّ *بدون* React. باستخدام [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) الخاص بالمتصفح فقط:
@@ -87,7 +88,7 @@ function submitForm(answer) {
if (answer.toLowerCase() == 'istanbul') {
resolve();
} else {
- reject(new Error('Good guess but a wrong answer. Try again!'));
+ reject(new Error('توقع جيد ولكن إجابة خاطئة. حاول مرة أخرى!'));
}
}, 1500);
});
@@ -111,57 +112,56 @@ textarea.oninput = handleTextareaChange;
```html public/index.html
-
That's right!
+
هذا صحيح!
```
-Manipulating the UI imperatively works well enough for isolated examples, but it gets exponentially more difficult to manage in more complex systems. Imagine updating a page full of different forms like this one. Adding a new UI element or a new interaction would require carefully checking all existing code to make sure you haven't introduced a bug (for example, forgetting to show or hide something).
-
-React was built to solve this problem.
+تعديل واجهة المستخدم (UI) أمريًّا يعمل بشكل جيد كفاية للأمثلة المعزولة، ولكنه يصبح أكثر صعوبة بشكل استثنائي عندما تدير أنظمة أكثر تعقيدًا. تخيل تحديث صفحة مليئة بالنماذج المختلفة مثل هذه هنا. إضافة عنصر واجهة مستخدم جديد سيتطلب فحص كامل الكود الموجود بحرص للتأكد من أنك لم تقم بعمل خطأ (على سبيل المثال، نسيان إظهار أو إخفاء شيء ما).
-In React, you don't directly manipulate the UI--meaning you don't enable, disable, show, or hide components directly. Instead, you **declare what you want to show,** and React figures out how to update the UI. Think of getting into a taxi and telling the driver where you want to go instead of telling them exactly where to turn. It's the driver's job to get you there, and they might even know some shortcuts you haven't considered!
+صُنعت React لحل هذه المشكلة.
-
+في React، لن تقوم بتعديل واجهة المستخدم مباشرة -- يعني أنك لن تقوم بتفعيل، تعطيل، إظهار، أو إخفاء مكوّنات مباشرة. بدلًا عن ذلك، سوف **تصف ما تريده أن يظهر،** و React سوف تدبر كيفية تحديث واجهة المستخدم. فكر في أخذ سيارة أجرة وإخبار السائق إلي أين تريد أنت تذهب بدلًا من إخباره إلي أين ينعطف. وظيفة السائق هي أن يوصلك إلى هناك، وربما قد يعرف اختصارات لم تأخذها أنت بالحُسبان.
-## Thinking about UI declaratively {/*thinking-about-ui-declaratively*/}
+
-You've seen how to implement a form imperatively above. To better understand how to think in React, you'll walk through reimplementing this UI in React below:
+## التفكير في واجهة المستخدم (UI) تصريحيًا {/*thinking-about-ui-declaratively*/}
-1. **Identify** your component's different visual states
-2. **Determine** what triggers those state changes
-3. **Represent** the state in memory using `useState`
-4. **Remove** any non-essential state variables
-5. **Connect** the event handlers to set the state
+لقد رأيت كيفية تنفيذ نموذج أمريَّا أعلاه. لفهم أفضل لكيفية التفكير في React، سوف تمر بإعادة تنفيذ واجهة المستخدم (UI) هذه باستخدام React أدناه:
-### Step 1: Identify your component's different visual states {/*step-1-identify-your-components-different-visual-states*/}
+1. **عيّن** الحالات المرئية المختلفة لمكوّنك
+2. **حدد** ما ينشط تغييرات تلك الحالات
+3. **مثّل** الحالة في الذاكرة باستخدام `useState`
+4. **احذف** أيّ متغيرات حالة غير ضرورية
+5. **اربط** معالجات الأحداث لتعيين الحالة
-In computer science, you may hear about a ["state machine"](https://en.wikipedia.org/wiki/Finite-state_machine) being in one of several “states”. If you work with a designer, you may have seen mockups for different "visual states". React stands at the intersection of design and computer science, so both of these ideas are sources of inspiration.
+### الخطوة 1: عيّن الحالات المرئية المختلفة لمكوّنك {/*step-1-identify-your-components-different-visual-states*/}
-First, you need to visualize all the different "states" of the UI the user might see:
+في علوم الحاسب، ربما تسمع عن ["آلة الحالة (state machine)"](https://ar.wikipedia.org/wiki/%D8%A2%D9%84%D8%A9_%D9%85%D8%AD%D8%AF%D9%88%D8%AF%D8%A9_%D8%A7%D9%84%D8%AD%D8%A7%D9%84%D8%A7%D8%AA) كونها واحدة من ضمن "حالات" متعددة. إذا كنت تعمل مع مصمم، لربما رأيت نماذج تجريبية لـ"الحالات المرئية" المختلفة
-* **Empty**: Form has a disabled "Submit" button.
-* **Typing**: Form has an enabled "Submit" button.
-* **Submitting**: Form is completely disabled. Spinner is shown.
-* **Success**: "Thank you" message is shown instead of a form.
-* **Error**: Same as Typing state, but with an extra error message.
+أولًا، أنت تحتاج لتصوّر جميع "الحالات" المختلفة لواجهة المستخدم (UI) التي قد يراها المستخدم:
+* **فارغة**: النموذج يحتوي على زر "إرسال" معطل.
+* **كتابة**: النموذج يحتوي على زر "إرسال" مفعّل.
+* **إرسال**: النموذج معطل تمامًا. يتم عرض مؤشر التحميل.
+* **نجاح**: يتم عرض رسالة "شكرًا لك" بدلًا من النموذج.
+* **خطأ**: مثل حالة الكتابة، ولكن مع رسالة خطأ إضافية
-Just like a designer, you'll want to "mock up" or create "mocks" for the different states before you add logic. For example, here is a mock for just the visual part of the form. This mock is controlled by a prop called `status` with a default value of `'empty'`:
+تمامًا مثل المصمم، سترغب في "تجربة" أو إنشاء "نماذج تجريبية" للحالات المختلفة قبل أن تضيف المنطق. على سبيل المثال، ها هو نموذج تجريبي للجزء المرئي فقط من النموذج. هذا النموذج التجريبي متحكم به بواسطة خاصيّة تدعى `status` مع قيمة افتراضية `'empty'`:
@@ -170,19 +170,19 @@ export default function Form({
status = 'empty'
}) {
if (status === 'success') {
- return
That's right!
+ return
هذا صحيح!
}
return (
<>
-
City quiz
+
اختبار المدينة
- In which city is there a billboard that turns air into drinkable water?
+ في أي مدينة يوجد لوحة إعلانية تقوم بتحويل الهواء لمياه صالحة للشرب؟
>
@@ -192,23 +192,23 @@ export default function Form({
-You could call that prop anything you like, the naming is not important. Try editing `status = 'empty'` to `status = 'success'` to see the success message appear. Mocking lets you quickly iterate on the UI before you wire up any logic. Here is a more fleshed out prototype of the same component, still "controlled" by the `status` prop:
+يمكنك تسمية الخاصيّة أيّ شيء تريد، التسمية ليست مهمة. جرب تعديل `status = 'empty'` إلى `status = 'success'` لترى رسالة النجاح تظهر. التجربة تتيح لك التكرار السريع على واجهة المستخدم قبل ربط أي منطق. ها هو نموذج تجريبي أكثر تفصيلًا لنفس المكوّن، يظل "متحكمًا به" بواسطة الخاصية `status`:
```js
export default function Form({
- // Try 'submitting', 'error', 'success':
+ // جرب 'submitting'، 'error'، 'success':
status = 'empty'
}) {
if (status === 'success') {
- return
That's right!
+ return
هذا صحيح!
}
return (
<>
City quiz
- In which city is there a billboard that turns air into drinkable water?
+ في أي مدينة يوجد لوحة إعلانية تقوم بتحويل الهواء لمياه صالحة للشرب؟
@@ -233,6 +233,7 @@ export default function Form({
```
```css
+body { direction: rtl; }
.Error { color: red; }
```
@@ -240,9 +241,9 @@ export default function Form({
-#### Displaying many visual states at once {/*displaying-many-visual-states-at-once*/}
+#### عرض عديد من الحالات المرئية مرة واحدة {/*displaying-many-visual-states-at-once*/}
-If a component has a lot of visual states, it can be convenient to show them all on one page:
+لو أن لمكون العديد من الحالات المرئية، قد يكون ملائمًا عرضها جميعها في صفحة واحدة:
@@ -262,7 +263,7 @@ export default function App() {
<>
{statuses.map(status => (
-
Form ({status}):
+
نموذج ({status}):
))}
@@ -274,7 +275,7 @@ export default function App() {
```js Form.js
export default function Form({ status }) {
if (status === 'success') {
- return
That's right!
+ return
هذا صحيح!
}
return (
@@ -301,67 +302,67 @@ export default function Form({ status }) {
```css
section { border-bottom: 1px solid #aaa; padding: 20px; }
h4 { color: #222; }
-body { margin: 0; }
+body { margin: 0; direction: rtl; }
.Error { color: red; }
```
-Pages like this are often called "living styleguides" or "storybooks".
+صفحات مثل هذه غالبًا يطلق عليها "living styleguides" أو "storybooks"
-### Step 2: Determine what triggers those state changes {/*step-2-determine-what-triggers-those-state-changes*/}
+### الخطوة 2: حدد ما ينشط تغييرات تلك الحالة {/*step-2-determine-what-triggers-those-state-changes*/}
-You can trigger state updates in response to two kinds of inputs:
+يمكنك تنشيط تحديثات الحالة كاستجابة إلى نوعين من المدخلات:
-* **Human inputs,** like clicking a button, typing in a field, navigating a link.
-* **Computer inputs,** like a network response arriving, a timeout completing, an image loading.
+* **مدخلات الإنسان،** مثل الضغط على زر، أو الكتابة في حقل، أو زيارة رابط.
+* **مدخلات الكمبيوتر،** مثل وصول رد الشبكة، أو استكمال المؤقت، أو تحميل الصورة.
-
-
+
+
-In both cases, **you must set [state variables](/learn/state-a-components-memory#anatomy-of-usestate) to update the UI.** For the form you're developing, you will need to change state in response to a few different inputs:
+في كلتا الحالتين، **يجب عليك تعيين [متغيرات الحالة (state variables)](/learn/state-a-components-memory#anatomy-of-usestate) لتُحدّث واجهة المستخدم (UI).** من أجل تطوير النموذج سوف تحتاج لتغيير الحالة كنتيجة لبعض من المدخلات المختلفة:
-* **Changing the text input** (human) should switch it from the *Empty* state to the *Typing* state or back, depending on whether the text box is empty or not.
-* **Clicking the Submit button** (human) should switch it to the *Submitting* state.
-* **Successful network response** (computer) should switch it to the *Success* state.
-* **Failed network response** (computer) should switch it to the *Error* state with the matching error message.
+* **تغيّر حقل إدخال النص** (الإنسان) سوف يغيرها من الحالة *الفارغة* إلى حالة *الكتابة* أو العكس، يعتمد على ما إذا كان حقل النص فارغًا أم لا.
+* **الضغط على زر الإرسال** (الإنسان) سوف يغيرها إلى حالة *الإرسال*.
+* **استجابة ناجحة للشبكة** (الكمبيوتر) سوف يغيرها إلى حالة *النجاح*.
+* **استجابة فاشلة للشبكة** (الكمبيوتر) سوف يغيرها إلى حالة *الخطأ* مع رسالة الخطأ المناسبة.
-Notice that human inputs often require [event handlers](/learn/responding-to-events)!
+لاحظ أن مدخلات الإنسان غالبًا تتطلب [معالجات أحداث (event handlers)](/learn/responding-to-events)!
-To help visualize this flow, try drawing each state on paper as a labeled circle, and each change between two states as an arrow. You can sketch out many flows this way and sort out bugs long before implementation.
+للمساعدة على تصوّر هذا التدفق، جرّب رسم كل حالة على ورقة كدائرة مُعنّوَنة. وكل تغيّر بين حالتين كسهم. تستطيع رسم العديد من التدفقات بهذه الطريقة وحل الأخطاء مبكرًا قبل التنفيذ.
-
+
-Form states
+حالات النموذج
-### Step 3: Represent the state in memory with `useState` {/*step-3-represent-the-state-in-memory-with-usestate*/}
+### الخطوة 3: مثّل الحالة في الذاكرة باستخدام `useState` {/*step-3-represent-the-state-in-memory-with-usestate*/}
-Next you'll need to represent the visual states of your component in memory with [`useState`.](/reference/react/useState) Simplicity is key: each piece of state is a "moving piece", and **you want as few "moving pieces" as possible.** More complexity leads to more bugs!
+بعد ذلك ستحتاج لتمثّل الحالات المرئية لمكوّنك في الذاكرة باستخدام [`useState`.](/reference/react/useState) البساطة هي المفتاح: كل قطعة من الحالة هي "قطعة متحركة"، **وبالـتأكيد تريد تقليل "القطع المتحركة" قدر الإمكان.** ;كثرة التعقيدات تؤدي إلى كثرة الأخطاء!
-Start with the state that *absolutely must* be there. For example, you'll need to store the `answer` for the input, and the `error` (if it exists) to store the last error:
+ابدأ بالحالة التي *لا بدّ* من وجودها. على سبيل المثال، سوف تحتاج لتخزين الإجابة `answer` للمدخل، والخطأ `error` (لو وُجد) لتخزين آخر خطأ:
```js
const [answer, setAnswer] = useState('');
const [error, setError] = useState(null);
```
-Then, you'll need a state variable representing which one of the visual states that you want to display. There's usually more than a single way to represent that in memory, so you'll need to experiment with it.
+بعد ذلك، سوف تحتاج لمتغير حالة يمثّل أي من الحالات المرئية التي تريد عرضها. يوجد غالبًا أكثر من طريقة واحدة لتمثيل ذلك في الذاكرة، لذلك سوف يتعين عليك تجريبها.
-If you struggle to think of the best way immediately, start by adding enough state that you're *definitely* sure that all the possible visual states are covered:
+إذا واجهت صعوبة في التفكير في أفضل طريقة على الفور، ابدا بإضافة حالة كافية حتى تكون متأكدًا *تمامًا* من تغطية جميع الحالات المرئية المحتملة:
```js
const [isEmpty, setIsEmpty] = useState(true);
@@ -371,19 +372,19 @@ const [isSuccess, setIsSuccess] = useState(false);
const [isError, setIsError] = useState(false);
```
-Your first idea likely won't be the best, but that's ok--refactoring state is a part of the process!
+خطوتك المبدئية على الأرجح لن تكون هي الأفضل، ولكن هذا لا بأس به -- إعادة تصميم الحالة هو جزء من العملية!
-### Step 4: Remove any non-essential state variables {/*step-4-remove-any-non-essential-state-variables*/}
+### الخطوة 4: احذف أيّ متغيرات حالة غير ضرورية {/*step-4-remove-any-non-essential-state-variables*/}
-You want to avoid duplication in the state content so you're only tracking what is essential. Spending a little time on refactoring your state structure will make your components easier to understand, reduce duplication, and avoid unintended meanings. Your goal is to **prevent the cases where the state in memory doesn't represent any valid UI that you'd want a user to see.** (For example, you never want to show an error message and disable the input at the same time, or the user won't be able to correct the error!)
+ما تريده هو تجنب تكرار محتوى الحالة لذلك أنت تقوم بتعقب ما هو ضروري فقط. قضاء قليل من الوقت في إعادة تصميم هيكل حالتك سوف يجعل مكوّنك أسهل للفهم، يقلل التكرار، ويتجنب المعاني غير المقصودة. هدفك هو **منع الأوضاع التي تكون بها الحالة في الذاكرة لا تمثل أي واجهة مستخدم صالحة من التي تود للمستخدم أن يراها.** (على سبيل المثال، لن تريد أبدًا إظهار رسالة خطأ مع تعطيل الإدخال في نفس الوقت، أو أن المستخدم لن يكون قادرًا على تصحيح الخطأ!)
-Here are some questions you can ask about your state variables:
+هنا بعض الاسئلة التي يمكن أن تسألها عن متغيرات الحالة:
-* **Does this state cause a paradox?** For example, `isTyping` and `isSubmitting` can't both be `true`. A paradox usually means that the state is not constrained enough. There are four possible combinations of two booleans, but only three correspond to valid states. To remove the "impossible" state, you can combine these into a `status` that must be one of three values: `'typing'`, `'submitting'`, or `'success'`.
-* **Is the same information available in another state variable already?** Another paradox: `isEmpty` and `isTyping` can't be `true` at the same time. By making them separate state variables, you risk them going out of sync and causing bugs. Fortunately, you can remove `isEmpty` and instead check `answer.length === 0`.
-* **Can you get the same information from the inverse of another state variable?** `isError` is not needed because you can check `error !== null` instead.
+* **هل هذه الحالة تسبب معضلة؟** على سبيل المثال، `isTyping` و `isSubmitting` لا يمكن لكليهما أن يكونا بقيمة `true`. المعضلة غالبًا تعني أن الحالة ليست مقيدة بالشكل الكافي. هناك أربع احتمالات ممكنة لقيميتين منطقيتين (boolean). لكن ثلاث منهن فقط يوافقن حالات صالحة. لحذف الحالة "المستحيلة"، يمكنك جمع تلك الحالات داخل `status` التي يجب أن تكون واحدة من ثلاث قيم: `'typing'`, `'submitting'`, أو `'success'`.
+* **هل نفس المعلومات متاحة بالفعل لمتغير حالة آخر؟** معضلة أخرى: `isEmpty` و `isTyping` لا يمكنها أن يكونا `true` في نفس الوقت. بجعلهما متغيرين حالة منفصلين، تخاطر بفقدان الترابط بينهما وإحداث الأخطاء. لحسن الحظ، يمكن حذف `isEmpty` والتحقق من `answer.length === 0` بدلًا عن ذلك.
+* **هل يمكنك الحصول على نفس المعلومات من عكس متغير حالة آخر؟** `isError` غير ضروري لأنه يمكنك التحقق من `error !== null` بدلًا عن ذلك.
-After this clean-up, you're left with 3 (down from 7!) *essential* state variables:
+بعد هذا التبسيط، تبقى لديك 3 (من أصل 7!) متغيرات حالة *ضرورية*:
```js
const [answer, setAnswer] = useState('');
@@ -391,19 +392,19 @@ const [error, setError] = useState(null);
const [status, setStatus] = useState('typing'); // 'typing', 'submitting', or 'success'
```
-You know they are essential, because you can't remove any of them without breaking the functionality.
+أنت تعلم أنها ضرورية، لأنك لا تستطيع إزالة أيّ منها بدون تخريب آلية العمل.
-#### Eliminating “impossible” states with a reducer {/*eliminating-impossible-states-with-a-reducer*/}
+#### إزالة الحالات "المستحيلة" باستخدام مخفض (reducer) {/*eliminating-impossible-states-with-a-reducer*/}
-These three variables are a good enough representation of this form's state. However, there are still some intermediate states that don't fully make sense. For example, a non-null `error` doesn't make sense when `status` is `'success'`. To model the state more precisely, you can [extract it into a reducer.](/learn/extracting-state-logic-into-a-reducer) Reducers let you unify multiple state variables into a single object and consolidate all the related logic!
+هذه الثلاث متغيرات تمثيل جيد كفاية لحالة النموذج. مع ذلك، لا تزال هناك بعض الحالات المتوسطة الغير منطقية بشكل كافٍ. على سبيل المثال، `error` التي لا تحمل القيمة null غير منطقية عندما تكون `status` تحمل قيمة `success`. لتمثيل الحالة بطريقة أكثر دقة، يمكنك [استخلاصها إلى مخفض.](/learn/extracting-state-logic-into-a-reducer) المخفضات تتيح ليك توحيد العديد من متغيرات الحالة داخل كائن (object) واحد وتجميع كل المنطق المتعلق بها.
-### Step 5: Connect the event handlers to set state {/*step-5-connect-the-event-handlers-to-set-state*/}
+### الخطوة 5: اربط معالجات الأحداث لتعيين الحالة {/*step-5-connect-the-event-handlers-to-set-state*/}
-Lastly, create event handlers that update the state. Below is the final form, with all event handlers wired up:
+أخيرًا، إنشاء معالجات الأحداث التي تحدّث الحالة. أدناه هو النموذج النهائي، مع كل معالجات الأحداث متصلة ببعضها:
@@ -437,9 +438,9 @@ export default function Form() {
return (
<>
-
City quiz
+
اختبار المدينة
- In which city is there a billboard that turns air into drinkable water?
+ في أي مدينة يوجد لوحة إعلانية تقوم بتحويل الهواء إلى مياه صالحة للشرب؟
-Although this code is longer than the original imperative example, it is much less fragile. Expressing all interactions as state changes lets you later introduce new visual states without breaking existing ones. It also lets you change what should be displayed in each state without changing the logic of the interaction itself.
+بالرغم من أن هذا الكود أطول من المثال الأمريّ الأصلي، إلا أنه أقل هشاشة بكثير. التعبير عن جميع الأوامر على أنها تغيّرات في الحالة يتيح لك لاحقًا إضافة حالات مرئية جديدة دون تعطيل الحالات القائمة بالفعل. كما يتيح لك أيضًا تغيير ما يجب عرضه في كل حالة دون تغيير منطق الأمر نفسه.
-* Declarative programming means describing the UI for each visual state rather than micromanaging the UI (imperative).
-* When developing a component:
- 1. Identify all its visual states.
- 2. Determine the human and computer triggers for state changes.
- 3. Model the state with `useState`.
- 4. Remove non-essential state to avoid bugs and paradoxes.
- 5. Connect the event handlers to set state.
+* البرمجة التصريحية تعني وصف واجهة المستخدم لكل حالة مرئية عوضًا عن الإدارة التفصيلية لواجهة المستخدم (الأمريّة).
+* عند تطوير مكوّن:
+ 1. حدد كل حالاته المرئية.
+ 2. عيّن المنشطات الوادة الإنسان والكمبيوتر لتغيّرات الحالة.
+ 3. مثل الحالة عن طريق `useState`.
+ 4. احذف الحالة غير الضرورية لتجنب الأخطاء والمعضلات.
+ 5. اربط معالجات الأحداث لتعيين الحالة.
@@ -503,11 +505,11 @@ Although this code is longer than the original imperative example, it is much le
-#### Add and remove a CSS class {/*add-and-remove-a-css-class*/}
+#### إضافة وحذف صنف (class) CSS {/*add-and-remove-a-css-class*/}
-Make it so that clicking on the picture *removes* the `background--active` CSS class from the outer `
`, but *adds* the `picture--active` class to the ``. Clicking the background again should restore the original CSS classes.
+نفذ ذلك بحيث يكون النقر على الصورة *يحذف* صنف CSS `background--active`من الـ`
` الخارجي، لكن *يضيف* الصنف `picture--active` لـ``. النقر على الخلفية مجددًا يجب أن يعيد أصناف CSS الأصلية.
-Visually, you should expect that clicking on the picture removes the purple background and highlights the picture border. Clicking outside the picture highlights the background, but removes the picture border highlight.
+عمليًا، يمكنك توقع أن النقر على الصورة يحذف الخلفية البنفسجية ويقوم بتحديد (highlight) إطار الصورة. النقر خارج الصورة يقوم بتحديد الخلفيةـ ولكن يحذف تحديد إطار الصورة.
@@ -556,14 +558,13 @@ body { margin: 0; padding: 0; height: 250px; }
-This component has two visual states: when the image is active, and when the image is inactive:
-
-* When the image is active, the CSS classes are `background` and `picture picture--active`.
-* When the image is inactive, the CSS classes are `background background--active` and `picture`.
+هذا المكوّن لديه حالتين مرئيتين: عندما تكون الصورة نشطة، وعندما تكون الصورة غير نشطة:
-A single boolean state variable is enough to remember whether the image is active. The original task was to remove or add CSS classes. However, in React you need to *describe* what you want to see rather than *manipulate* the UI elements. So you need to calculate both CSS classes based on the current state. You also need to [stop the propagation](/learn/responding-to-events#stopping-propagation) so that clicking the image doesn't register as a click on the background.
+* عندما تكون الصورة نشطة، أصناف CSS هي `background` و `picture picture--active`.
+* عندما تكون الصورة غير نشطة، أصناف CSS هي `background background--active` و `picture`.
+متغير حالة قيمة منطقية (boolean) واحد يكفي لتذكر ما إذا كانت نشطة. المهمة الأصلية كانت إزالة أو إضافة أصناف CSS. على أية حال، في React تحتاج لـ*تصف* ما تريد رؤيته فضلًا عن *تعديل* عناصر واجهة المستخدم. لذلك تحتاج لحساب كلا صنفيّ CSS اعتمادًا على الحالة الحالية. تحتاج أيضًا إلى [إيقاف الانتشار (propagation)](/learn/responding-to-events#stopping-propagation) بحيث لا يتم تسجيل النقر على الصورة كنقر على الخلفية.
-Verify that this version works by clicking the image and then outside of it:
+تأكد من أن هذا الإصدار يعمل عن طريق النقر على الصور وخارجها:
@@ -630,7 +631,7 @@ body { margin: 0; padding: 0; height: 250px; }
-Alternatively, you could return two separate chunks of JSX:
+بديلًا عن ذلك، يمكنك إرجاع (return) جزئين مختلفين من JSX:
@@ -697,27 +698,27 @@ body { margin: 0; padding: 0; height: 250px; }
-Keep in mind that if two different JSX chunks describe the same tree, their nesting (first `
` → first ``) has to line up. Otherwise, toggling `isActive` would recreate the whole tree below and [reset its state.](/learn/preserving-and-resetting-state) This is why, if a similar JSX tree gets returned in both cases, it is better to write them as a single piece of JSX.
+ضع في الحسبان أنه إذا وصف جزئين مختلفين من JSX الشجرة نفسها، فتضمينهما (أول `
` ← أول ``) يجب أن يصطف. وإلا تغيّر `isActive` سوف يعيد إنشاء الشجرة بأكملها أدناه و [يعيد تعيين حالتها.](/learn/preserving-and-resetting-state) هذا هو السبب، إذا كان يتم إرجاع شجرة JSX مشابهة في كلا الحالتين، فمن الأفضل كتابتهما كجزء واحد من JSX.
-#### Profile editor {/*profile-editor*/}
+#### محرر الملف الشخصي {/*profile-editor*/}
-Here is a small form implemented with plain JavaScript and DOM. Play with it to understand its behavior:
+ها هو نموذج مصغر تم تنفيذه بواسطة JavaScript و DOM خالصيّن. جربه لتفهم طريقة عمله:
```js index.js active
function handleFormSubmit(e) {
e.preventDefault();
- if (editButton.textContent === 'Edit Profile') {
- editButton.textContent = 'Save Profile';
+ if (editButton.textContent === 'عدّل الملف الشخصي') {
+ editButton.textContent = 'احفظ الملف الشخصي';
hide(firstNameText);
hide(lastNameText);
show(firstNameInput);
show(lastNameInput);
} else {
- editButton.textContent = 'Edit Profile';
+ editButton.textContent = 'عدّل الملف الشخصي';
hide(firstNameInput);
hide(lastNameInput);
show(firstNameText);
@@ -728,7 +729,7 @@ function handleFormSubmit(e) {
function handleFirstNameChange() {
firstNameText.textContent = firstNameInput.value;
helloText.textContent = (
- 'Hello ' +
+ 'أهلًا ' +
firstNameInput.value + ' ' +
lastNameInput.value + '!'
);
@@ -737,7 +738,7 @@ function handleFirstNameChange() {
function handleLastNameChange() {
lastNameText.textContent = lastNameInput.value;
helloText.textContent = (
- 'Hello ' +
+ 'أهلًا ' +
firstNameInput.value + ' ' +
lastNameInput.value + '!'
);
@@ -772,7 +773,7 @@ lastNameInput.oninput = handleLastNameChange;
```html public/index.html
```
-This form switches between two modes: in the editing mode, you see the inputs, and in the viewing mode, you only see the result. The button label changes between "Edit" and "Save" depending on the mode you're in. When you change the inputs, the welcome message at the bottom updates in real time.
+هذا النموذج يتغيّر بين وضعين: في وضع التعديل، ترى حقول الإدخال، وفي وضع المعاينة، ترى النتيجة فقط. عنوان الزر يتغيّر ما بين "عدّل" و"احفظ" اعتمادًا على الوضع الذي أنت عليه. عندما تقوم بتغيير حقول الإدخال، يتم تحديث رسالة الترحيب في الأسفل للوقت الحالي.
-Your task is to reimplement it in React in the sandbox below. For your convenience, the markup was already converted to JSX, but you'll need to make it show and hide the inputs like the original does.
+مهمتك هي إعادة تنفيذها بواسطة React في الـsandbox أدناه. لضمان راحتك، تم تحويل التوصيف (markup) إلى JSX, لكن يتعين عليك جعلها تُظهر وتُخفي المدخلات كما تفعل الأصلية.
-Make sure that it updates the text at the bottom, too!
+تأكد من أنها تقوم بتحديث النص في الأسفل أيضًا!
@@ -813,25 +814,26 @@ export default function EditProfile() {
return (
);
}
```
```css
+body { direction: rtl; }
label { display: block; margin-bottom: 20px; }
```
@@ -839,9 +841,9 @@ label { display: block; margin-bottom: 20px; }
-You will need two state variables to hold the input values: `firstName` and `lastName`. You're also going to need an `isEditing` state variable that holds whether to display the inputs or not. You should _not_ need a `fullName` variable because the full name can always be calculated from the `firstName` and the `lastName`.
+ستحتاج لمتغيريّ حالة لحمل قيم الإدخال: `firstName` و `lastName`. سوف تحتاج أيَا متغير حالة `isEditing` الذي يحمل ما إذا كان سيعرض حقول الإدخال أم لا. _ليس_ عليك استعمال متغير `fullName` لأن الاسم الكامل يمكن دائمًا إيجاده من الاسم الأول `firstName` واسم العائلة `lastName`.
-Finally, you should use [conditional rendering](/learn/conditional-rendering) to show or hide the inputs depending on `isEditing`.
+أخيرًا، يمكنك استخدام [التصيّير الشرطي](/learn/conditional-rendering) لإظهار أو إخفاء حقول الإدخال اعتمادًا على `isEditing`.
@@ -859,7 +861,7 @@ export default function EditProfile() {
setIsEditing(!isEditing);
}}>
-Compare this solution to the original imperative code. How are they different?
+قارن بين هذا الحل والكود الأمريّ الأصلي. ما مدى الاختلاف؟
-#### Refactor the imperative solution without React {/*refactor-the-imperative-solution-without-react*/}
+#### إعادة تصميم الحل الأمري بدون React {/*refactor-the-imperative-solution-without-react*/}
-Here is the original sandbox from the previous challenge, written imperatively without React:
+ها هي الـ sandbox الأصلية من التحدي الماضي، مكتوبة بشكل أمري بدون React:
```js index.js active
function handleFormSubmit(e) {
e.preventDefault();
- if (editButton.textContent === 'Edit Profile') {
- editButton.textContent = 'Save Profile';
+ if (editButton.textContent === 'عدّل الملف الشخصي') {
+ editButton.textContent = 'احفظ الملف الشخصي';
hide(firstNameText);
hide(lastNameText);
show(firstNameInput);
show(lastNameInput);
} else {
- editButton.textContent = 'Edit Profile';
+ editButton.textContent = 'عدّل الملف الشخصي';
hide(firstNameInput);
hide(lastNameInput);
show(firstNameText);
@@ -930,7 +933,7 @@ function handleFormSubmit(e) {
function handleFirstNameChange() {
firstNameText.textContent = firstNameInput.value;
helloText.textContent = (
- 'Hello ' +
+ 'أهلًا ' +
firstNameInput.value + ' ' +
lastNameInput.value + '!'
);
@@ -939,7 +942,7 @@ function handleFirstNameChange() {
function handleLastNameChange() {
lastNameText.textContent = lastNameInput.value;
helloText.textContent = (
- 'Hello ' +
+ 'أهلًا ' +
firstNameInput.value + ' ' +
lastNameInput.value + '!'
);
@@ -974,7 +977,7 @@ lastNameInput.oninput = handleLastNameChange;
```html public/index.html
```
-Imagine React didn't exist. Can you refactor this code in a way that makes the logic less fragile and more similar to the React version? What would it look like if the state was explicit, like in React?
+تصوّر لو أن React غير موجودة. هل يمكنك إعادة تصميم الكود بطريقة تجعل المنطق أقل هشاشة وأكثر مقاربة لنسخة React؟ كيف سيبدو لو كانت حالته بيّنة، كما هو الحال في React؟
-If you're struggling to think where to start, the stub below already has most of the structure in place. If you start here, fill in the missing logic in the `updateDOM` function. (Refer to the original code where needed.)
+إذا كنت تواجه صعوبة في تحديد من أين تبدأ، فالمُلحق أدناه يحتوي أغلب الهيكل معدًّا. لو بدأت من هنا، املئ المنطق المفقود داخل الدالة `updateDOM`. (راجع الكود الكود الأصلي عند الحاجة.)
@@ -1043,13 +1046,13 @@ function setIsEditing(value) {
function updateDOM() {
if (isEditing) {
- editButton.textContent = 'Save Profile';
- // TODO: show inputs, hide content
+ editButton.textContent = 'احفظ الملف الشخصي';
+ // قائمة المهام: إظهار حقول الإدخال، إخفاء المحتوى
} else {
- editButton.textContent = 'Edit Profile';
- // TODO: hide inputs, show content
+ editButton.textContent = 'عدّل الملف الشخصي';
+ // قائمة المهام: إخفاء حقول الإدخال، إظهار المحتوى
}
- // TODO: update text labels
+ // (text labels) قائمة المهام: تحديث عنواين النص
}
function hide(el) {
@@ -1081,7 +1084,7 @@ lastNameInput.oninput = handleLastNameChange;
```html public/index.html
```
@@ -1111,7 +1114,7 @@ label { display: block; margin-bottom: 20px; }
-The missing logic included toggling the display of inputs and content, and updating the labels:
+المنطق المفقود تضمّن تغيير عرض حقول الإدخال والمحتوى، وتحديث العناوين:
@@ -1150,13 +1153,13 @@ function setIsEditing(value) {
function updateDOM() {
if (isEditing) {
- editButton.textContent = 'Save Profile';
+ editButton.textContent = 'احفظ الملف الشخصي';
hide(firstNameText);
hide(lastNameText);
show(firstNameInput);
show(lastNameInput);
} else {
- editButton.textContent = 'Edit Profile';
+ editButton.textContent = 'عدّل الملف الشخصي';
hide(firstNameInput);
hide(lastNameInput);
show(firstNameText);
@@ -1165,7 +1168,7 @@ function updateDOM() {
firstNameText.textContent = firstName;
lastNameText.textContent = lastName;
helloText.textContent = (
- 'Hello ' +
+ 'أهلًا ' +
firstName + ' ' +
lastName + '!'
);
@@ -1200,7 +1203,7 @@ lastNameInput.oninput = handleLastNameChange;
```html public/index.html
```
-The `updateDOM` function you wrote shows what React does under the hood when you set the state. (However, React also avoids touching the DOM for properties that have not changed since the last time they were set.)
+الدالة `updateDOM` التي كتبتها تُظهر ما تقوم به React تحت الستار عندما تقوم بتعيين الحالة. (مع ذلك، React تتجنب المسّ بالـ DOM لأجل الخصائص التي لم تتغير من أخر مرة تم تعيينها فيها.)
diff --git a/src/sidebarLearn.json b/src/sidebarLearn.json
index 56de0f4c4..e14e4a8dd 100644
--- a/src/sidebarLearn.json
+++ b/src/sidebarLearn.json
@@ -130,7 +130,7 @@
"tags": ["intermediate"],
"routes": [
{
- "title": "Reacting to Input with State",
+ "title": "الاستجابة للمدخلات باستخدام الحالة",
"path": "/learn/reacting-to-input-with-state"
},
{