In my react functional component, I have a function that is executed to toggle the checkboxes as selected or unselected. It works fine.
The function (inside Parent component) goes like this:
const ParentComponent = () => {
const { state, dispatch } = useContext(FilterContext);
const onChange = useCallback((value) => {
(item) => {
const { name, selected } = item;
// this "name" comes from another sibling component on the mount, and then from child component (sideAccordian) on click
const selectedFilters = state.identifiers_checkbox.selected_checkboxes.find(
(obj) => obj === name
);
const selected_checkboxes = selectedFilters
? state.identifiers_checkbox.selected_checkboxes.filter(
(obj) => obj !== name
)
: [...state.identifiers_checkbox.selected_checkboxes, name];
const toggled_checkboxes = {
selected_checkboxes,
options_checkbox: [
...state.identifiers_checkbox.options_checkbox.map((filter) => {
return {
...filter,
options: filter.options.map((option, i) => {
return name === option.name
? {
...option,
selected,
}
: option;
}),
};
}),
],
};
dispatch({
type: "update-checkboxes",
payload: {
checkboxSelected: true,
selected_checkboxes: toggled_checkboxes.selected_checkboxes,
options_checkbox: toggled_checkboxes.options_checkbox,
},
});
},
[
dispatch,
state.identifiers_checkbox.options_checkbox,
state.identifiers_checkbox.selected_checkboxes,
]);
useEffect(() => {
if (info.prevui === "intervention") {
if (state.identifiers_checkbox.options_checkbox.length > 1) {
onChange({ name: info.abbr, selected: 1 });
}
}
}, [
info.abbr,
info.prevui,
dispatch,
state.identifiers_checkbox.options_checkbox.length,
// onChange,
]);
return (
<div>
{
state.identifiers_checkbox.options_checkbox.length > 1 ? (
<SideAccordian
filterstate={state.identifiers_checkbox}
onChange={onChange}
/>
) : (
<h6 style={{ textAlign: "center" }}>No Options Available</h6>
)
}
</div>
)
}
Child Component
export default function SideAccordian(props) {
const [options, setOptions] = useState([]);
const classes = useStyles();
useEffect(() => {
setOptions(props.filterprop);
}, [props]);
return (
<div className={classes.root}>
{
options.map((ele, id) => (
<Accordion key={id} defaultExpanded={true}>
<AccordionSummary
key={ele.key}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
</AccordionSummary>
{ele.options.map((item, i) => {
return (
<AccordionDetails key={i}>
<IndeterminateInput
key={i}
id={i}
name={item.name}
value={item.label}
selected={item.selected}
onChange={props.onChange}
/>
</AccordionDetails>
)
})}
</Accordion>
))
}
</div>
);
}
Additionally, I need to call onChange()
function as the component mounts & then automatically mark any of the checkboxes as selected according to the name of the checkbox passed as an argument.
The handler function onChange()
works fine on clicking the checkbox, but when trying to invoke it on mount on the basis of a particular condition, it doesn't work.
As soon as the component mounts:
If onChange()
is included in the dependency array, it throws Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array or one of the dependencies changes on every render.
If removed from the dependency array, it works but keeps throwing error each Hook useEffect has a missing dependency: 'onChange'. Either include it or remove the dependency array
.
Since, I need to execute this function only once on render also i.e. (when info.prevui === intervention' & info.prevui does not change every time ), this error behavior of useEffect()
is out of my understanding.
Can anyone please help out to understand and provide any working hint/solution for the same?
Thanks