I have a function that takes a props value in a component and flattens it into a form the component can use. This needs to happen every time the props value changes. I put the setState in a useEffect with the props value as one of the dependencies.
This works fine in the browser but I get the error from the question title when running the Jest tests.
Here's basically what my code looks like:
const mapThing = (notFlatStructure) => {
let flattendStructure = [];
notFlatStructure.forEach((mainItem) => {
flattendStructure.append({
id: mainItem.id,
text: mainItem.text,
isToggle: true
});
if (mainItem.subItems && mainItem.subItems.length > 0) {
mainItem.subItems.forEach((subItem) => {
flattendStructure.append({
id: subItem.id,
text: subItem.text,
isToggle: true
});
});
}
});
return flattendStructure;
};
const myComponent = (props) => {
const [mappedThing, setMappedThing] = useState(mapThing(props.thing));
useEffect(() => {
setMappedThing(mapThing(props.thing));
}, [props.thing]);
const handleBlur = (e) => {
props.thingChanged(e);
};
const handleClick = (row) => {
let found = mappedThing.find((el) => el.id = row.id);
found.isToggle = !found.isToggle;
setMappedThing(mappedThing);
};
return (
<div>
{
mappedThing.map((row) => {
<div>
<input onBlur={handleBlur} value={row.text}></input>
<button onClick={(e) => handleClick(row)}></button>
</div>
})
}
</div>
);
};
Is there a standard way to have mappedThing above set every time the props change without using a useEffect? Any time I take the useEffect away the component quits updating.
Drew Reese in the comments was correct. The code was an anti-pattern in React. After restructuring the component and splitting some functionality off into small, sub components, I was able to create the component without flattening the underlying data structure and removing the need for the setState in the useEffect. Thanks, Mr. Reese for pointing our my error. I learned a lot having to work through making this align with React's expectations.