كيفية مسح قيم حقول الإدخال في النماذج الديناميكية باستخدام React

دقائق القراءة: 5

تحدي مسح حقول الإدخال في نماذج React الديناميكية

عند العمل على تطبيقات React، وخاصة تلك التي تتضمن النماذج (forms)، هناك العديد من الجوانب التي يجب أخذها في الاعتبار. حتى لو تمكنت من إنشاء زر إرسال (submit button) وتحديث حالة التطبيق (app's state) بالطريقة التي تريدها، فإن مسح قيم النماذج بعد الإرسال أو إعادة التعيين يمكن أن يكون مهمة صعبة. تخيل أن تطبيقك يحتوي على نماذج ديناميكية معقدة.

بناء النموذج الديناميكي الأولي في React

لنبدأ بمثال يوضح بنية نموذج React ديناميكي. يتكون هذا النموذج من ثلاثة مكونات رئيسية: App، Cart، و Form. المكون App يدير الحالة (state) الرئيسية للتطبيق ويحتوي على منطق التعامل مع التغييرات وإعادة التعيين والإرسال. المكون Cart يعمل كوسيط، بينما المكون Form مسؤول عن عرض حقول الإدخال بناءً على البيانات المقدمة.

 import React from "react" ;
 import ReactDOM from "react-dom" ;
 import Cart from "./Cart" ;
 import "./styles.css" ;
 
 class App extends React . Component {
  constructor (props) {
  super (props);
  this .state = {
  Items : [
  { name : "item1" , description : "item1" , group : "groupA" , dtype : "str" },
  { name : "item2" , description : "item2" , group : "groupA" , dtype : "str" },
  { name : "item3" , description : "item3" , group : "groupB" , dtype : "str" },
  { name : "item4" , description : "item4" , group : "groupB" , dtype : "str" }
  ],
  itemvalues : [{}]
  };
  this .onChangeText = this .onChangeText.bind( this );
  this .handleReset = this .handleReset.bind( this );
  this .handleSubmit = this .handleSubmit.bind( this );
  this .findFieldIndex = this .findFieldIndex.bind( this );
  this .trimText = this .trimText.bind( this );
  }
 
  onChangeText = e => {
  const valuesCopy = [...this.state.itemvalues];
  //debugger;
  // get data-group value
  const itemvalue = e.target.dataset.group;
  if (!valuesCopy[ 0 ][itemvalue]) {
  valuesCopy[ 0 ][itemvalue] = [];
  }
  const itemvalues = valuesCopy[ 0 ][itemvalue];
  const index = this .findFieldIndex(itemvalues, e.target.name);
  if (index < 0 ) {
  valuesCopy[ 0 ][itemvalue] = [
  ...itemvalues,
  { [e.target.name]: e.target.value.split( "," ).map( this .trimText) }
  ];
  } else {
  // update the value
  valuesCopy[ 0 ][itemvalue][index][e.target.name] = e.target.value
  .split( "," )
  .map( this .trimText);
  }
  // console.log(itemsCopy);
  this .setState({
  itemvalues : valuesCopy
  });
  };
 
  findFieldIndex = ( array, name ) => {
  return array.findIndex(
  item => item[name] !== undefined
  );
  };
 
  trimText(str) {
  return str.trim();
  }
 
  handleReset = () => {
  this .setState({
  itemvalues : [{}]
  });
  };
 
  handleSubmit = () => {
  console .log( this .state.itemvalues);
  };
 
  render() {
  return (
  < Cart
  Items = {this.state.Items}
  handleSubmit = {this.handleSubmit}
  handleReset = {this.handleReset}
  onChangeText = {this.onChangeText}
  />
  );
  }
 }
 
 ReactDOM.render(
  < App /> ,
  document .getElementById( "root" )
 );
 import React from "react" ;
 import Form from "./Form" ;
 
 const Cart = props => {
  return (
  < div >
  < Form
  Items = {props.Items}
  onChangeText = {props.onChangeText}
  />
  < button onClick = {props.handleSubmit} > Submit </ button >
  < button onClick = {props.handleReset} > Reset </ button >
  </ div >
  );
 };
 
 export default Cart;
 import React from "react" ;
 
 const Form = props => {
  return (
  < div >
  {props.Items.map((item, index) => (
  < input
  name = {item.name}
  placeholder = {item.description}
  data-type = {item.dtype}
  data-group = {item.group}
  onChange = {e => props.onChangeText(e)}
  key={index}
  />
  ))}
  </ div >
  );
 };
 
 export default Form;

كيفية عرض حقول الإدخال وتخزين القيم

مع هذا الإعداد، يتم عرض مربعات إدخال بسيطة على الصفحة كما هو موضح في الصورة:

نموذج React ديناميكي يعرض حقول إدخال متعددة

عندما يقوم المستخدم بإدخال نص في أحد مربعات الإدخال، يتم حفظه في حالة التطبيق (application state) في مجموعات منظمة على النحو التالي:

Itemvalues:
0 :
groupA:
item1: itemvalue1
item2 : itemvalue2
groupB :
item3: itemvalue3
item4 : itemvalue4

قد يبدو هذا معقدًا بعض الشيء، لكنك نجحت في جعله يعمل بكفاءة.

المشكلة: مسح الحالة لا يعني مسح الواجهة الرسومية

في دالة handleReset، يمكنك إعادة تعيين itemvalues إلى حالة فارغة عند الضغط على زر “Reset” (إعادة التعيين):

handleReset = () => {
 this .setState({
 itemvalues : [{}]
 });
 };

ولكن المشكلة تكمن في أن النص لا يتم مسحه من جميع مربعات الإدخال على الواجهة الرسومية، كما يتضح في الصورة التالية:

فيديو يوضح عدم مسح حقول الإدخال بعد الضغط على زر إعادة التعيين

لقد قمت بالفعل بالتعامل مع تخزين النص الفعلي في الحالة (state)، لذا إليك طريقة بسيطة لمسح النص من جميع مربعات الإدخال.

الحل الفعال: مسح قيم جميع حقول الإدخال مباشرة من DOM

الخطوة 1: تحديد جميع عناصر الإدخال

في الجزء العلوي من دالة handleReset، استخدم document.querySelectorAll('input') لتحديد جميع عناصر الإدخال (input elements) في الصفحة:

handleReset = () => {
 document .querySelectorAll( 'input' );
 this .setState({
 itemvalues : [{}]
 });
 };

الخطوة 2: تحويل NodeList إلى مصفوفة

تقوم الدالة document.querySelectorAll('input') بإرجاع NodeList، وهو يختلف قليلاً عن المصفوفة العادية (array)، لذا لا يمكنك استخدام أي من دوال المصفوفات المفيدة عليه مباشرة. لتحويله إلى مصفوفة، قم بتمرير document.querySelectorAll('input') إلى الدالة Array.from():

handleReset = () => {
 Array .from(
 document .querySelectorAll( 'input' )
 );
 this .setState({
 itemvalues : [{}]
 });
 };

الخطوة 3: تصفير قيمة كل حقل إدخال

الآن كل ما عليك فعله هو التكرار على كل حقل إدخال وتعيين خاصية value الخاصة به إلى سلسلة نصية فارغة (empty string). تعتبر دالة forEach خيارًا ممتازًا لهذه المهمة:

handleReset = () => {
 Array .from(
 document .querySelectorAll( "input" )
 ).forEach( input => (input.value = "" ) );
 this .setState({
 itemvalues : [{}]
 });
 };

النتيجة النهائية: مسح شامل للحقول

الآن، عندما يضغط المستخدم على زر “Reset” (إعادة التعيين)، يتم مسح قيمة كل حقل إدخال أيضًا، مما يوفر تجربة مستخدم متكاملة:

فيديو يوضح مسح جميع حقول الإدخال بنجاح بعد الضغط على زر إعادة التعيين

الخلاصة التقنية

في هذا المقال، استعرضنا تحديًا شائعًا في تطوير تطبيقات React يتعلق بمسح قيم حقول الإدخال في النماذج الديناميكية. بينما يسهل تحديث حالة التطبيق (state) لإعادة تعيين البيانات، فإن مسح الواجهة الرسومية يتطلب أحيانًا التفاعل المباشر مع DOM. لقد تعلمنا أن استخدام document.querySelectorAll('input') مع Array.from().forEach() يوفر حلاً فعالاً ومباشرًا لهذه المشكلة. هذه الطريقة تضمن مزامنة البيانات في الحالة مع العرض المرئي للحقول، مما يعزز تجربة المستخدم ويحافظ على نظافة الواجهة. من المهم دائمًا الموازنة بين إدارة الحالة في React والتلاعب المباشر بالـ DOM عند الضرورة لتحقيق التأثيرات المطلوبة.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *