You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
لجعل الواجهة تفاعلية؛ يجب أن تسمح للمستخدم بتعديل أنموذج بياناتك. لإنجاز ذلك، سيتعين عليك توظيف*الحالات*.
209
+
لجعل الواجهة تفاعلية؛ يجب أن تسمح للمستخدم بتعديل نموذج بياناتك. لإنجاز ذلك، سيتعين عليك استخدام*الحالات*.
210
210
211
-
اعتبر الحالات كما لو أنها عدّتك من البيانات المتغيرة التي يجب أن يتذكرها تطبيقك. أهم مبدأ يجب أخذه في الاعتبار عند تحديد حالاتك هي أن تكون [فريدة](https://ar.wikipedia.org/wiki/%D9%84%D8%A7_%D8%AA%D9%83%D8%B1%D8%B1_%D9%86%D9%81%D8%B3%D9%83). حاول استنباط القدر الأدنى لتمثيل حالات تطبيقك المختلفة التي سيحتاجها، وقم باحتساب أي حالة أخرى تزيد على ذلك عند الحاجة. مثلا، إذا كنت تقوم ببناء قائمة مشتريات، يمكنك حفظ الأصناف كمصفوفة في حالة التطبيق. أما إذا احتجت لعرض عدد الأصناف في القائمة، فلا تقم بحفظ عدد الأصناف كحالة أخرى. عوضا عن ذلك؛ يمكنك دائما قراءة طول المصفوفة.
211
+
اعتبر الحالات كما لو أنها عدّتك من البيانات المتغيرة التي يجب أن يتذكرها تطبيقك. أهم مبدأ يجب أخذه في الاعتبار عند تحديد حالاتك هو [عدم التكرار DRY](https://ar.wikipedia.org/wiki/%D9%84%D8%A7_%D8%AA%D9%83%D8%B1%D8%B1_%D9%86%D9%81%D8%B3%D9%83). حاول استنباط القدر الأدنى لتمثيل حالات تطبيقك المختلفة التي سيحتاجها، وقم باحتساب أي حالة أخرى تزيد على ذلك عند الحاجة. مثلا، إذا كنت تقوم ببناء قائمة مشتريات، يمكنك حفظ الأصناف كمصفوفة في حالة التطبيق. أما إذا احتجت لعرض عدد الأصناف في القائمة، فلا تقم بحفظ عدد الأصناف كحالة أخرى. عوضا عن ذلك؛ يمكنك دائما قراءة طول المصفوفة`Array.length`.
212
212
213
-
الآن فكر في كل ما قد تحتاجه من بيانات في تطبيقنا المفترض:
213
+
الآن فكر في كل ما قد تحتاجه من بيانات في تطبيقنا:
214
214
215
215
1. القائمة الأصلية للمنتجات.
216
216
2. كلمات البحث التي قام المستخدم بكتابتها.
217
217
3. حالة مربع الاختيار (الخاص بإظهار المنتجات التي لها رصيد فقط).
218
218
4. قائمة المنتجات بعد التصفية بكلمات البحث.
219
219
220
-
أيا مما سبق يعتبر حالة؟ يمكنك تمييزها بأنها لا تنطبق عليها المواصفات التالية:
220
+
أي مما سبق يعتبر حالة؟ يمكنك تمييزها بأنها لا تنطبق عليها المواصفات التالية:
221
221
222
222
* هل تبقى دائما **ثابتة** لا تتغير؟ إذا ليست حالة..
223
223
* هل **تم تمريرها من المكون الأب** عن طريق الخصائص؟ إذا ليست حالة.
@@ -227,7 +227,7 @@ td {
227
227
228
228
لنقم بمراجعتهم واحد تلو الآخر مرة أخرى:
229
229
230
-
1. القائمة الأصلية للمنتجات **يتم تمريرها ضمن الخصائص،فهي ليست حالة.**
230
+
1. القائمة الأصلية للمنتجات **يتم تمريرها ضمن الخصائص،فهي ليست حالة.**
231
231
2. كلمات البحث تبدو كحالة بما أنها تتغير مع مرور الوقت ولا يمكن اشتقاقها من أي شيء آخر.
232
232
3. حالة مربع الاختيار تبدو كحالة بما أنها تتغير مع مرور الوقت ولا يمكن اشتقاقها من أي شيء آخر.
233
233
4. قائمة المنتجات بعد التصفية **ليست حالة إذ يمكن اشتقاقها** عبر تصفية قائمة المنتجات الأصلية وفقا لكلمات البحث وحالة مربع الاختيار.
@@ -238,36 +238,35 @@ td {
238
238
239
239
#### الخصائص والحالات {/*props-vs-state*/}
240
240
241
-
يعتبر كل منهما من أحد أنواع البيانات "النموذجية" في React: الخصائص والحالة. يختلف كلاهما عن الآخر بفارق كبير:
241
+
هناك نوعان من البيانات "الافتراضية" في React: الخصائص والحالة. يختلف كلاهما عن الآخر بفارق كبير:
242
242
243
-
*[**الخصائص (Props)** تشبه المعطيات](/learn/passing-props-to-a-component) التي تقوم بتمريرها لإحدى الدوال. تتيح لمكون أعلى أن تمرر بيانات لمكون تابع له وتنسيق مظهره أيضا. فمثلا، مكون`Form` يمكن أن يمرر خاصية `color` إلى `Button` لتغيير لونه.
244
-
*[**الحالة (State)** تشبه ذاكرة المكون.](/learn/state-a-components-memory) تتيح للمكون إمكانية أن يحاقظ على اطلاعه على بعض البيانات وأن يغيرها تجاوبا مع تفاعل المستخدم. فمثلا, يمكن للزر `Button` أن يبقى على اطلاع لحالة `isHovered`.
243
+
*[**الخصائص (Props)** تشبه المعطيات](/learn/passing-props-to-a-component) التي تقوم بتمريرها لإحدى الدوال. تتيح لمكون أعلى أن تمرر بيانات لمكون فرعي عنه وتنسيق مظهره أيضا. فمثلا، مكون `Form` يمكن أن يمرر خاصية `color` إلى `Button` لتغيير لونه.
244
+
*[**الحالة (State)** تشبه ذاكرة المكون.](/learn/state-a-components-memory) تتيح للمكون إمكانية أن يبقى مطلعًا على بعض البيانات وأن يغيرها تجاوبا مع تفاعل المستخدم. فمثلا, يمكن للزر `Button` أن يبقى على اطلاع لحالة `isHovered`.
245
245
246
-
الخصائص والحالات أمران مختلفان، لكن يكملان بعضهما. قد يحتوي مكون ما على بعض البيانات في حالات (كي يتمكن من تغييرها) و *يمررها* لمكون تابع كخصائص لها. لا بأس إن كنت تشعر أن الفارق بينهما لا يزال غامضا. قد يستلزم الأمر بعض الممارسة لتتمكن من الإلمام به!
246
+
الخصائص والحالات أمران مختلفان، لكن يكملان بعضهما. قد يحتوي مكون ما على بعض البيانات في حالات (كي يتمكن من تغييرها) و *يمررها* لمكون تابع كخصائص لها. لا بأس إن كنت تشعر أن الفارق بينهما لا يزال غامضا. قد يستلزم الأمر بعض الممارسة لتلمّ به!
247
247
248
248
</DeepDive>
249
249
250
250
## الخطوة 4: حدد أين تضع الحالات {/*step-4-identify-where-your-state-should-live*/}
251
251
252
-
بعد أن حدد القدر الأدنى من بيانات الحالات اللازمة، عليك الأن أن تحدد أي المكونات مسءول عن تغيير كلٌّ من هذه الحالات، أو *يملك* تلك الحالة. تذكر أن React يستخدم سيل البيانات في اتجاه واحد، وهو تمرير البيانات من المكون الأب لمكون تابع له في التسلسل الشجري. قد لا يبدو واضحا من الوهلة الأولى أي مكون يجب أن يملك تلك "الحالة" ويكون مسؤولا عنها. ربما يكون هذا تحديا لك إن كان هذا المفهوم جديدا عليك،لكن ستتمكن من إيجاد الإجابة باتباع الخطوات التالية!
252
+
بعد تحديد القدر الأدنى من بيانات الحالات اللازمة، عليك الآن أن تحدد أي المكونات مسئول عن تغيير كلٌّ من هذه الحالات، أو *يملك* تلك الحالة. تذكر أن React يستخدم سيل البيانات في اتجاه واحد، وهو تمرير البيانات من المكون الأب لمكون تابع له في التسلسل الشجري. قد لا يبدو واضحا من الوهلة الأولى أي مكون يجب أن يملك تلك "الحالة" ويكون مسؤولا عنها. ربما يكون هذا تحديا لك إن كان هذا المفهوم جديدا عليك،لكن ستتمكن من إيجاد الإجابة باتباع الخطوات التالية!
253
253
254
254
لكل حالة على حدة في تطبيقك:
255
255
256
256
1. حدد *جميع* المكونات التي تعرض أي شيء له علاقة بهذه الحالة.
257
-
2. حدد السلف الأقرب المشترك بينهم؛ مكون يكون أعلى منهم جميعا في التسلسل الشجري.
257
+
2. حدد السلف المشترك الأقرب بينهم؛ مكون يكون أعلى منهم جميعا في التسلسل الشجري.
258
258
3. حدد أين يجب أن تتمركز الحالة:
259
259
1. عادة، يمكنك وضع الحالة مباشرة في سلفهم المشترك.
260
260
2. يمكنك أيضا أن تضع الحالة في مكون أعلى من السلف المشترك.
261
261
3. إن لم يكن بإمكانك تحديد مكون حيث يبدو من المنطقي وضع الحالة فيه، قم بعمل مكون جديد خصيصا لحفظ تلك الحالة، وقم بوضعه في مكان ما في التسلسل الشجري يسبق سلفهم المشترك.
262
262
263
263
في الخطوة السابقة، وجدت حالتين في هذا التطبيق: نص البحث المكتوب، وحالة مربع الاختيار. في هذا المثال، يظهران دائما معا، فمن المنطقي وضعهم معا في نفس المكان.
264
264
265
-
Now let's run through our strategy for them:
266
-
حسنا، لنقوم باختبار طريقتنا عليهم:
265
+
حسنا، لنختبر طريقتنا عليهم:
267
266
268
267
1.**حدد المكونات التي تستخدم الحالة:**
269
-
* مكون (جدول المنتجات)`ProductTable` يحتاج الحالة ليقوم بتصفية قائمة المنتجات (نص البحث وحالة مربع الاختيار).
270
-
* مكون (خانة البحث)`SearchBar` يقوم بعرض الحالة نفسها (نص البحث).
268
+
* مكون `ProductTable`(جدول المنتجات) يحتاج الحالة ليقوم بتصفية قائمة المنتجات (نص البحث وحالة مربع الاختيار).
269
+
* مكون `SearchBar`(خانة البحث) يقوم بعرض الحالة نفسها (نص البحث).
271
270
1.**حدد لهم سلفا مشتركا:** السلف المشترك للمكونين هو `FilterableProductTable`.
272
271
2.**حدد أين تضع الحالة**: سنضع نص البحث وحالة مربع الاختيار في المكون `FilterableProductTable`.
273
272
@@ -281,7 +280,7 @@ function FilterableProductTable({ products }) {
ثم مرر المتغير `filterText` و`inStockOnly` للمكونين `ProductTable` و`SearchBar` كخاصية ضمن خصائص كلا منهما:
283
+
ثم مرر المتغير `filterText` و`inStockOnly` للمكونين `ProductTable` و`SearchBar` كخاصية ضمن خصائص كل منهما:
285
284
286
285
```js
287
286
<div>
@@ -291,12 +290,10 @@ function FilterableProductTable({ products }) {
291
290
<ProductTable
292
291
products={products}
293
292
filterText={filterText}
294
-
inStockOnly={inStockOnly} />
295
-
</div>
293
+
inStockOnly={inStockOnly} /></div>
296
294
```
297
295
298
-
You can start seeing how your application will behave. Edit the `filterText` initial value from `useState('')` to `useState('fruit')` in the sandbox code below. You'll see both the search input text and the table update:
299
-
قد يبدو واضحا لك من الآن كيف سيبدو سلوك تطبيقك. قم بتعديل قيمة `filterText` الأولية من `useState('')` إلى `useState('fruit')` في الكود التالي داخل الـsandbox المدرج. سترى نتيجة التعديل على كلا من محتوى خانة البحث وجدول المنتجات:
296
+
قد يبدو واضحا لك من الآن كيف سيبدو سلوك تطبيقك. قم بتعديل قيمة `filterText` الأولية من `useState('')` إلى `useState('fruit')` في الكود التالي داخل الـsandbox المدرج. سترى نتيجة التعديل على كل من محتوى خانة البحث وجدول المنتجات:
300
297
301
298
<Sandpack>
302
299
@@ -393,13 +390,13 @@ function SearchBar({ filterText, inStockOnly }) {
393
390
<input
394
391
type="text"
395
392
value={filterText}
396
-
placeholder="Search..."/>
393
+
placeholder="بحث..."/>
397
394
<label>
398
395
<input
399
396
type="checkbox"
400
397
checked={inStockOnly} />
401
398
{''}
402
-
Only show products in stock
399
+
عرض المنتجات المتوفرة فقط
403
400
</label>
404
401
</form>
405
402
);
@@ -438,15 +435,17 @@ td {
438
435
439
436
</Sandpack>
440
437
441
-
لاحظ أنك لو عدلت مباشرة على نموذج البحث فلن يحدث شيء. هناك رسالة خطأ في الـsandbox أعلاه تخبرك لماذا:
438
+
لاحظ أنك لو عدّلت مباشرة على نموذج البحث فلن يحدث شيء. هناك رسالة خطأ في الـsandbox أعلاه تخبرك لماذا:
442
439
443
440
<ConsoleBlock level="error">
441
+
442
+
You provided a \`value\` prop to a form field without an \`onChange\` handler. This will render a read-only field.
444
443
445
444
لقد قمت بتمرير \`قيمة\` إحدى الخصائص لإحدى خانات نموذج دون تحديد معالج لحدث تغير القيمة \`onChange\`. سينتج عن هذا خانة قابلة للقراءة فقط.
446
445
447
446
</ConsoleBlock>
448
447
449
-
في الـsandbox أعلاه؛ المكونان `ProductTable` و`SearchBar` يقرآن الخصائص `filterText` و`inStockOnly` لعرض الجدول، مربع البحث، ومربع الاختيار. إليك مثلا كيف يقوم المكون `SearchBar` بكتابة محتوى مربع البحث:
448
+
في الـsandbox أعلاه؛ المكونان `ProductTable` و`SearchBar` يقرآن الخصائص `filterText` و`inStockOnly` لعرض الجدول، ومربع البحث، ومربع الاختيار. إليك مثلا كيف يقوم المكون `SearchBar` بكتابة محتوى مربع البحث:
450
449
451
450
```js {1,6}
452
451
functionSearchBar({ filterText, inStockOnly }) {
@@ -455,10 +454,10 @@ function SearchBar({ filterText, inStockOnly }) {
455
454
<input
456
455
type="text"
457
456
value={filterText}
458
-
placeholder="Search..."/>
457
+
placeholder="بحث..."/>
459
458
```
460
459
461
-
برغم ذلك، فأنت لم تقم بعد بكتابة أي كود للتجاوب مع تفاعلات المستخدم (كالكتابة). هذه ستكون خطوتك الأخيرة.
460
+
برغم ذلك، فأنت لم تكتب بعد أي كود للتجاوب مع تفاعلات المستخدم (كالكتابة). هذه ستكون خطوتك الأخيرة.
462
461
463
462
464
463
## الخطوة 5: إضافة تدفق البيانات العكسي {/*step-5-add-inverse-data-flow*/}
0 commit comments