الفرق بين المراجعتين لصفحة: «React/forms»

من موسوعة حسوب
لا ملخص تعديل
لا ملخص تعديل
سطر 57: سطر 57:


== العنصر <code>textarea</code> ==
== العنصر <code>textarea</code> ==
في HTML يُعرَّف نص العنصر <code>[[HTML/textarea|<textarea>]]</code> عن طريق عناصره الأبناء:<syntaxhighlight lang="html">
في HTML يُعرَّف نص العنصر <code>[[HTML/textarea|<textarea>]]</code> بشكلٍ مباشر كما يلي:<syntaxhighlight lang="html">
<textarea>
<textarea>
   مرحبًا، هذا نص ما موجود ضمن العنصر textarea
   مرحبًا، هذا نص ما موجود ضمن العنصر textarea
</textarea>
</textarea>
</syntaxhighlight>أمّا في React يستخدم العنصر <code>[[HTML/textarea|<textarea>]]</code> الخاصيّة <code>value</code> بدلًا من ذلك، وبهذه الطريقة يُمكِن كتابة الحقل الذي يستخدم <code>[[HTML/textarea|<textarea>]]</code> بشكلٍ مُشابِه للحقل الذي يستخدم عنصر الإدخال <code>[[HTML/input|<input>]]</code>:
</syntaxhighlight>أمّا في React يستخدم العنصر <code>[[HTML/textarea|<textarea>]]</code> الخاصيّة <code>value</code> بدلًا من ذلك، وبهذه الطريقة يُمكِن كتابة الحقل الذي يستخدم <code>[[HTML/textarea|<textarea>]]</code> بشكلٍ مُشابِه للحقل الذي يستخدم عنصر الإدخال <code>[[HTML/input|<input>]]</code>:<syntaxhighlight lang="javascript">
class EssayForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 'اكتب من فضلك مقالًا حول العنصر المفضّل لديك في DOM'
    };
 
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
 
  handleChange(event) {
    this.setState({value: event.target.value});
  }
 
  handleSubmit(event) {
    alert('قُدِّم المقال: ' + this.state.value);
    event.preventDefault();
  }
 
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          المقال:
          <textarea value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="تقديم المقال" />
      </form>
    );
  }
}
</syntaxhighlight>لاحظ أنّنا هيَّأنا <code>this.state.value</code> بقيمة مبدئيّة في الدالة البانية (constructor)، وبذلك نضمن وجود نص ضمن العنصر  <code>[[HTML/textarea|<textarea>]]</code> منذ البداية.

مراجعة 12:35، 19 يوليو 2018

تعمل عناصر الحقول (forms) بشكلٍ مختلفٍ قليلًا عن بقيّة عناصر DOM الأخرى في React بسبب احتفاظ عناصر الحقول بشكل طبيعي بحالة داخلية خاصّة بها. فمثلًا يقبل هذا الحقل في HTML اسمًا واحدًا:

<form>
  <label>
    الاسم:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="تقديم البيانات" />
</form>

يمتلك هذا الحقل نفس السّلوك الافتراضي لحقول HTML من حيث الانتقال إلى صفحة جديدة عندما يضغط المستخدم على زر تقديم البيانات (Submit)، وإن أردت فقط هذا السّلوك في React فسيعمل بشكل جيّد معك، ولكن في معظم الأحيان من الملائم أكثر أن نمتلك دالة في JavaScript تتعامل مع تقديم البيانات ولديها الوصول إلى البيانات التي أدخلها المستخدم في الحقل. الطريقة القياسيّة لتحقيق هذا الأمر هي باستخدام تقنيّة تدعى المُكوِّنات المضبوطة (controlled components).

المكونات المضبوطة

تُحافِظ عناصر الحقول في HTML مثل <input>، و <textarea>، و <select> على حالتها الخاصّة وتُحدِثها وفقًا لمُدخلات المستخدم. أمّا في React فيُحتفَظ بحالة قابلة للتعديل ضمن خاصيّة الحالة للمُكوِّنات وتُحدَّث فقط عن طريق التابع setState()‎.

بإمكاننا الجمع بينهما بأن نجعل حالة React المصدر الوحيد للحقيقة، فبذلك يُصبِح مُكوِّن React الذي يُصيِّر الحقل مُتحكِّمًا أيضًا بما يحدث في ذلك الحقل مع تتالي مُدخلات المستخدم. يُدعى عنصر حقل الإدخال والذي تتحكّم React بقيمته بالمُكوِّن المضبوط.

على سبيل المثال إن أردنا في المثال السّابق أن نعرض الاسم بعد تقديمه فبإمكاننا كتابة الحقل كمُكوِّن مضبوط:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('قُدِّم الاسم: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          الاسم:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="تقديم البيانات" />
      </form>
    );
  }
}

جرب المثال على موقع CodePen.

لمّا كانت خاصيّة القيمة value مُعيَّنة عن طريق عنصر الحقل فستكون قيمتها المعروضة دومًا هي this.state.value، وبذلك نجعل حالة React المصدر الوحيد للحقيقة. وبما أنّ التابع handleChange يُنفَّذ عند كل ضغطة زر من المستخدم ليُحدِّث حالة React، فستتحدّث القيمة المعروضة بينما يكتب المستخدم.

في المكونات المضبوطة يكون لكل تغيير للحالة دالة للتعامل مع ذلك مُوافِقة له. يجعل ذلك من تعديل دخل المستخدم والتحقّق منه أمرًا سهلًا، فمثلًا لو أردنا إجبار المستخدم على كتابة الأحرف بحالة كبيرة سنكتب الدالة handleChange كما يلي:

handleChange(event) {
  this.setState({value: event.target.value.toUpperCase()});
}

العنصر textarea

في HTML يُعرَّف نص العنصر <textarea> بشكلٍ مباشر كما يلي:

<textarea>
  مرحبًا، هذا نص ما موجود ضمن العنصر textarea
</textarea>

أمّا في React يستخدم العنصر <textarea> الخاصيّة value بدلًا من ذلك، وبهذه الطريقة يُمكِن كتابة الحقل الذي يستخدم <textarea> بشكلٍ مُشابِه للحقل الذي يستخدم عنصر الإدخال <input>:

class EssayForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: 'اكتب من فضلك مقالًا حول العنصر المفضّل لديك في DOM'
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('قُدِّم المقال: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          المقال:
          <textarea value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="تقديم المقال" />
      </form>
    );
  }
}

لاحظ أنّنا هيَّأنا this.state.value بقيمة مبدئيّة في الدالة البانية (constructor)، وبذلك نضمن وجود نص ضمن العنصر <textarea> منذ البداية.