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:
The parent passes down a boolean prop
allChecked. That's supposed to tell us if all the checkboxes are checked or not.useEffectinCheckboxruns on mount, andallCheckedisfalsebecause that's its default.useEffectthen setscheckedtoallChecked's value,false. Which it already is, because its default is alsofalse.useEffectthen listens for a change inallCheckedvia[allChecked]that never comes.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:
- Checkboxes were not rendering again so react-hook-form would see the old value, no matter what
- 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.
