skip to Main Content

I am working on a checkbox control.
And this method does not seem to be optimal.

I don’t know if this is the correct usage of react-hook-form.

function App() {
  const methods = useForm();
  const { setValue, register } = methods;

  const cbxOnchange = (e) => {
    const { checked } = e.target;
    if(!checked)
      setValue('cbxall', false);
    const cbx1 = document.getElementsByName('cbx1')[0].checked;
    const cbx2 = document.getElementsByName('cbx2')[0].checked;
    if(cbx1 && cbx2)
      setValue('cbxall', true);
  };
  return (
    <>
      <div>
        <input type='checkbox' {...register('cbxall',{ onChange: (e) => {
          setValue('cbx1', e.target.checked);
          setValue('cbx2', e.target.checked);
        } })} defaultChecked />
        <input type='checkbox' {...register('cbx1',{ onChange: cbxOnchange })} defaultChecked />
        <input type='checkbox' {...register('cbx2',{ onChange: cbxOnchange })} defaultChecked />
      </div>
    </>
  )
}

Please, somebody help me.

2

Answers


  1. I do not understand deeply what you need. If you want to clean up the code a little bit you can use the event.target.name and event.target.checked.
    Something like:

    import React, { useState } from 'react';
    import { useForm } from 'react-hook-form';
    
    function App() {
      const methods = useForm();
      const { setValue, register } = methods;
    
      const [cbx1Checked, setCbx1Checked] = useState(true);
      const [cbx2Checked, setCbx2Checked] = useState(true);
      const [cbxAllChecked, setCbxAllChecked] = useState(true);
    
      const cbxOnchange = (e) => {
        const { name, checked } = e.target;
    
        if (name === 'cbx1') {
          setCbx1Checked(checked);
        } else if (name === 'cbx2') {
          setCbx2Checked(checked);
        }
    
        if (checked === false) {
          setCbxAllChecked(false);
          setValue('cbxall', false);
        } else if (cbx1Checked && cbx2Checked) {
          setCbxAllChecked(true);
          setValue('cbxall', true);
        }
      };
    
      const cbxAllOnChange = (e) => {
        const { checked } = e.target;
        setCbxAllChecked(checked);
        setCbx1Checked(checked);
        setCbx2Checked(checked);
        setValue('cbx1', checked);
        setValue('cbx2', checked);
      };
    
      return (
        <>
          <div>
            <input
              type='checkbox'
              {...register('cbxall', { onChange: cbxAllOnChange })}
              checked={cbxAllChecked}
            />
            <input
              type='checkbox'
              {...register('cbx1', { onChange: cbxOnchange })}
              name='cbx1'
              checked={cbx1Checked}
            />
            <input
              type='checkbox'
              {...register('cbx2', { onChange: cbxOnchange })}
              name='cbx2'
              checked={cbx2Checked}
            />
          </div>
        </>
      );
    }
    
    export default App;
    
    Login or Signup to reply.
  2. Here are some optimizations that can be made:

    1. Use the Controller component from react-hook-form, which provides better integration with the form state.
    2. Add default values for all checkboxes, ensuring a consistent initial state.
    3. Use watch function to observe changes in cbx1 and cbx2, which allows to update cbxall reactively.
    4. The useEffect hook is used to update cbxall whenever cbx1 or cbx2 change, eliminating the need for manual DOM manipulation.
    5. The handleAllChange function is simplified and only handles updating cbx1 and cbx2 when cbxall changes.
    6. Each checkbox is now rendered using a Controller, which provides better control over the input and its interactions with the form state.

    import React from ‘react’;
    import { useForm, Controller } from ‘react-hook-form’;

    function App() {
      const { control, watch, setValue } = useForm({
        defaultValues: {
          cbxall: true,
          cbx1: true,
          cbx2: true,
        }
      });
    
      const cbx1 = watch('cbx1');
      const cbx2 = watch('cbx2');
    
      React.useEffect(() => {
        setValue('cbxall', cbx1 && cbx2);
      }, [cbx1, cbx2, setValue]);
    
      const handleAllChange = (e) => {
        const { checked } = e.target;
        setValue('cbx1', checked);
        setValue('cbx2', checked);
      };
    
      return (
        <div>
          <Controller
            name="cbxall"
            control={control}
            render={({ field }) => (
              <input
                type="checkbox"
                {...field}
                onChange={(e) => {
                  field.onChange(e);
                  handleAllChange(e);
                }}
              />
            )}
          />
          <Controller
            name="cbx1"
            control={control}
            render={({ field }) => <input type="checkbox" {...field} />}
          />
          <Controller
            name="cbx2"
            control=
    {control}
            render={({ field }) => <input type="checkbox" {...field} />}
          />
        </div>
      );
    }
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search