Home > Net >  How can I change multiple Checkboxes in React Hook Form Via state
How can I change multiple Checkboxes in React Hook Form Via state

Time:10-29

Oky, so wasted like 12 hours already on this. And I really need help.

I created a filter using an array via Map that returns some checkbox components

Component:

import { useEffect, useState } from "react"

interface Checkbox {
    id: string | undefined,
    name: string,
    reg: any,
    value: any,
    label: string,
    required?: boolean,
    allChecked: boolean
}



const Checkbox = ({ id, name, reg, value, label, allChecked }: Checkbox) => {

    const [checked, setChecked] = useState(false);

    useEffect(() => {
        setChecked(allChecked);
    }, [allChecked])


    return (
        <>
            <label key={id}>

                <input type="checkbox"
                    {...reg}
                    id={id}
                    value={value}
                    name={name}
                    checked={checked}
                    onClick={() => {
                        setChecked(!checked)
                    }}
                    onChange={
                        () => { }
                    }
                />

                {label}

            </label>
        </>
    )
}

export default Checkbox;

Map:


                                    dataValues.sort()
                                        ?
                                        dataValues.map((e: any, i: number) => {

                                            let slug = e.replace(' ', '-').toLowerCase();
                                            return (
                                                <div key={JSON.stringify(e)} id={JSON.stringify(e)}
                                                >
                                                    <Checkbox id={slug}

                                                        name={title as string}
                                                        label={e as string}
                                                        value={e}
                                                        reg={{ ...register(title as string) }}
                                                        allChecked={allChecked}

                                                    />
                                                </div>
                                            )
                                        })
                                        :
                                        null
                                }

State that is just above the Map:

const [allChecked, setAllChecked] = useState<boolean>(false);

When I try to change the state on the parent and check or uncheck all of the checkboxes, nothing happens.

(the form works without a problem if I manually click on the checkboxes, but I cannot do this as I have some sections with over 40 values)

Sample of array:

dataValues = [
    "Blugi",
    "Bluza",
    "Body",
    "Bratara",
    "Camasa",
    "Cardigan",
    "Ceas",
    "Cercel",
    "Colier",
    "Fusta",
    "Geanta Cross-body",
    "Hanorac",
    "Jacheta",
    "Palton",
    "Pantaloni",
    "Pulover",
    "Rochie",
    "Rucsac",
    "Sacou",
    "Salopeta",
    "Set-Accesorii",
    "Top",
    "Trench",
    "Tricou",
    "Vesta"
]

CodePudding user response:

allChecked never changes (at least in the code shown here).

Here's the timeline:

  1. The parent passes down a boolean prop allChecked. That's supposed to tell us if all the checkboxes are checked or not.

  2. useEffect in Checkbox runs on mount, and allChecked is false because that's its default. useEffect then sets checked to allChecked's value, false. Which it already is, because its default is also false.

  3. useEffect then listens for a change in allChecked via [allChecked] that never comes.

  4. Clicking on any checkbox just toggles the state of that checkbox. allChecked's setter, setAllChecked, is never passed to the child or called from the parent.

What's the solution?

Somewhere, setAllChecked(true) needs to happen. Maybe a single checkbox with a label "Check all"?

Then, allChecked in Checkbox needs to be able to control the checkbox inputs. One implementation could be:

checked={checked || allChecked}

CodePudding user response:

I managed to solve this.

There were 2 main problems:

  1. Checkboxes were not rendering again so react-hook-form would see the old value, no matter what
  2. I couldn't press clear all multiple times, because I was sending the allChecked = = false info multiple times, and the state wasn't exactly changing.

What I did was force a render by integrating the allChecked state as an object

interface checkedState { checked: boolean, render: boolean }

So, whenever I send the state, I send it something like:

{ 
checked: true, 
render: !allChecked.render 
}

meaning that the new object is always new, no matter if I send the same information.

  • Related