اذهب إلى المحتوى

السؤال

نشر

اذا كان ال state بسيط فيمكنني تغييره عن طريق 

 setForm((prevForm) => ({ ...prevForm,  [name]: value  }));

ماذا ان كان ال state معقد بهذا الشكل


function App() {
  const [form, setForm] = useState({
    info: { firstname: '', lastname: '', email: '', password: '', confirmPassword: '' },
    address: { country: '', city: '', line1: '', line2: '' },
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setForm((prevForm) => ({ ...prevForm,  [name]: value  }));
  };
  console.log(form);
  return (
    <div>
      <h2>signup</h2>
      <input
        type="text"
        placeholder="firstname"
        name="firstname"
        value={form.info.firstname}
        onChange={handleChange}
      />
      <input
        type="text"
        placeholder="lastname"
        name="lastname"
        value={form.info.lastname}
        onChange={handleChange}
      />
      <input
        type="email"
        placeholder="email"
        name="email"
        value={form.info.email}
        onChange={handleChange}
      />
      <input
        type="password"
        placeholder="password"
        name="password"
        value={form.info.password}
        onChange={handleChange}
      />
      <input
        type="password"
        placeholder="confirmPassword"
        name="confirmPassword"
        value={form.info.confirmPassword}
        onChange={ handleChange}
      />
      <input
        type="text"
        placeholder="country"
        name="country"
        value={form.address.country}
        onChange={ handleChange}
      />
      <input
        type="text"
        placeholder="city"
        name="city"
        value={form.address.city}
        onChange={ handleChange}
      />
      <input
        type="text"
        placeholder="line1"
        name="line1"
        value={form.address.line1}
        onChange={ handleChange}
      />
      <input
        type="text"
        placeholder="line2"
        name="line2"
        value={form.address.line2}
        onChange={ handleChange}
      />
    </div>
  );
}

export default App;

 

Recommended Posts

  • 0
نشر

في حالتك انت تحتاج الى متغير اخر ليساعدك في تحديد اسم الطبقة التي تريد تغييرها ويمكنك ان تعطيها الى handleChange بهذا الشكل

onChange={(e) => handleChange(e, 'اسم الطبقة')}

ثم يمكنك الاعتماد على ذلك لتغيير ال state بهذا الشكل

 const handleChange = (e, objKey) => {
    const { name, value } = e.target;
    setForm((prevForm) => ({ ...prevForm, [objKey]: { ...prevForm[objKey], [name]: value } }));
  };
function App() {
  const [form, setForm] = useState({
    info: { firstname: '', lastname: '', email: '', password: '', confirmPassword: '' },
    address: { country: '', city: '', line1: '', line2: '' },
  });

  const handleChange = (e, objKey) => {
    const { name, value } = e.target;
    setForm((prevForm) => ({ ...prevForm, [objKey]: { ...prevForm[objKey], [name]: value } }));
  };
  console.log(form);
  return (
    <div>
      <h2>signup</h2>
      <input
        type="text"
        placeholder="firstname"
        name="firstname"
        value={form.info.firstname}
        onChange={(e) => handleChange(e, 'info')}
      />
      <input
        type="text"
        placeholder="lastname"
        name="lastname"
        value={form.info.lastname}
        onChange={(e) => handleChange(e, 'info')}
      />
      <input
        type="email"
        placeholder="email"
        name="email"
        value={form.info.email}
        onChange={(e) => handleChange(e, 'info')}
      />
      <input
        type="password"
        placeholder="password"
        name="password"
        value={form.info.password}
        onChange={(e) => handleChange(e, 'info')}
      />
      <input
        type="password"
        placeholder="confirmPassword"
        name="confirmPassword"
        value={form.info.confirmPassword}
        onChange={(e) => handleChange(e, 'info')}
      />
      <input
        type="text"
        placeholder="country"
        name="country"
        value={form.address.country}
        onChange={(e) => handleChange(e, 'address')}
      />
      <input
        type="text"
        placeholder="city"
        name="city"
        value={form.address.city}
        onChange={(e) => handleChange(e, 'address')}
      />
      <input
        type="text"
        placeholder="line1"
        name="line1"
        value={form.address.line1}
        onChange={(e) => handleChange(e, 'address')}
      />
      <input
        type="text"
        placeholder="line2"
        name="line2"
        value={form.address.line2}
        onChange={(e) => handleChange(e, 'address')}
      />
    </div>
  );
}

export default App;

 

  • 0
نشر

في حالتك يجب نسخ state object قبل التعديل هكذا:

const handleChange = (e) => {
  const { name, value } = e.target;
  
  setForm((prevForm) => {
    const newForm = {...prevForm};
    newForm.info[name] = value;
    return newForm;
  });
};

الكود السابق سيعمل لكن المشكلة الوحيدة أننا نقوم بعمل shallow copy وليس deep copy، مشكلة الـshallow copy أنها لا تضمن immutability ﻷننا في الحالة السابقة نعدل على info بشكل مباشر وهذا سيعدل على state بشكل مباشر وهذا خاطئ وإن عمل الكود، في حالة أردنا deep copy أنا أفضل حينها استخدام مكتبة immer من هذا الرابط ، في حالتك باستعمال immer:

const handleChange = (e) => {
  const { name, value } = e.target;
  
  setForm((prevForm) => {
    return produce(prevForm,(draftForm) => {
      draftForm.info[name] = value;
    });
  });
};

لاحظ أن الكود السابق أسهل بكثير فيم لو قمنا بعمل deep copy بأيدينا حيث تضمن لك مكتبة immer أن تكون state لديك immutable بشكل كامل ومع ذلك تكتب كود مشابه للـmutable.

إذا كان state object أعقد بكثير من حالتك هنا أفضل استعمال مكتبة redux وredux-toolkit أو أي بديل تحت مسمى state management library (مثل Mobx مثلاً) حيث تسمح لك تلك المكتبات بتقسيم state الكبيرة إلى أجزاء صغيرة يعالج كل جزء فيها معالجة مستقلة عن بقية الأجزاء مما يجعل إدارة الـstate object الكبير أسهل ناهيك عن توفير ميزات أخرى مثل تنظيم هيكلية التطبيق بنظام موحد جميل وأشياء أخرى كثيرة.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...