جافاسكريبت - كيف يمكنني ضبط خانة الاختيار على الحالة المحددة في نموذج React Hook؟


أنا أجرب React-Hook-form

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

import React from 'react'
import { useForm } from 'react-hook-form'

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm()
  const onSubmit = (data: any) => console.log(data)
  console.log(errors)

  return (
    <div className='mx-auto justify-center p-32 flex'>
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className='p-2'>
          <label htmlFor=''>January</label>
          <input
            type='checkbox'
            placeholder='January'
            {...register('January', {})}
            className='mx-3'
            checked
          />
        </div>
        <div className='p-2'>
          <label htmlFor=''>February</label>
          <input
            type='checkbox'
            placeholder='February'
            {...register('February', {})}
            className='mx-3'
          />
        </div>
        <input type='submit' />
      </form>
    </div>
  )
}

يمكنني إرسال النموذج بشكل صحيح لكن لدي مثل خانة اختيار يناير لتبدأ كخانة محددة، ولكن عندما أضع 'checked' كما هو موضح في الكود، somehow لا أستطيع 'إلغاء تحديدها'.

يبدو أنني أفتقد شيئًا وأي مساعدة ستكون محل تقدير كبير.

الإجابة رقم 1

المشكلة في تمرير checked هي أنه يأخذ السيطرة من useForm لإدارة خانة الاختيار. يستخدم useForm register() معالجات التغيير (onChange/onBlur) لتحديث خصائص checked (أو value للحقول غير الخاصة بخانات الاختيار) للعُنصر الفعلي <input> في DOM.

بتمرير الخاصية checked، أنت تتجاوز سمة checked في DOM التي يتم إدارتها بواسطة useForm. هذا يجعل خانة الاختيار غير قادرة على تغيير الحالة.


الآن بعد أن وضحت سبب حدوث هذه المشكلة، دعونا ننتقل إلى الحل. يمكن حل ذلك بطريقتين:

  1. useForm يسمح لك بتمرير قيم افتراضية عند استدعاء الخطاف لأول مرة.

    const {
      register,
      handleSubmit,
      formState: { errors },
    } = useForm({ defaultValues: { January: true } });
    
    // ...
    
    <input
      type="checkbox"
      {...register("January")}
    />
    
  2. أو استخدم الخاصية defaultChecked لعنصر <input type="checkbox" /> هذا يحتفظ بالقيمة المحددة الأولية ولا يتجاوز القيمة الحالية كما يفعل checked.

    const {
      register,
      handleSubmit,
      formState: { errors },
    } = useForm();
    
    // ...
    
    <input
      type="checkbox"
      {...register("January")}
      defaultChecked
    />
    

لاحظ أنه ليس من الجيد دمج الطريقتين. استخدم واحدة فقط. يوضح useForm ما يلي في قسم defaultValues:

خاصية defaultValues تملأ النموذج بأكمله بالقيم الافتراضية. تدعم كل من التعيين المتزامن وغير المتزامن للقيم الافتراضية. بينما يمكنك تعيين القيمة الافتراضية لحقل إدخال باستخدام defaultValue أو defaultChecked (كما هو موضح في الوثائق الرسمية لـ React)، يُستحسن استخدام defaultValues للنموذج بأكمله.


في السيناريو المعطى، من المحتمل أن يكون من الأفضل استخدام مصفوفة من القيم المحددة ["January", "March"] بدلاً من كائن { January: true, February: false, March: true }.

يمكنك الحصول على نتيجة المصفوفة باستخدام مصفوفة (فارغة) كقيمة افتراضية، وتسجيل مربعات الاختيار تحت نفس الاسم. إذا كانت هناك أي قيم موجودة داخل المصفوفة، فسيتم تحديدها افتراضيًا. القيم المستخدمة في المصفوفة ستطابق خاصية value لمربع الاختيار.

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm({
  defaultValues: { months: ["January"] }
  // mark months as array and ^ check the checkbox with value "January"
});

// ...

// add the `value` prop to the checkboxes
<input
  type="checkbox"
  value="January"
  {...register("months")}
/>
<input
  type="checkbox"
  value="February"
  {...register("months")}
/>

الإجابة رقم 2

إذا كنت تستخدم React Material UI مع React-Hook-Form، فإليك أبسط طريقة لجعله يعمل

import {
  Box
  Checkbox,
  FormControlLabel,
} from '@mui/material'
...
const {
  handleSubmit,
  control,
  formState: { errors },
} = useForm({
})
...

<Box>
<Controller
  control={control}
  name={`${dimension.id}-${dimension.name}`}
  defaultValue={false}
  render={({ field: { onChange, value } }) => (
    <FormControlLabel
      control={
        <Checkbox checked={value} onChange={onChange} />
      }
    />
  )}
/>
</Box>