Reputation: 1466
I have had in the past similar problems of infinite recursion, but I am not understanding what I am doing wrong. Here you can have the important parts of my function I have these states on top
const PREV_ICON = <span aria-hidden="true" className="carousel-control-prev-icon" />;
const NEXT_ICON = <span aria-hidden="true" className="carousel-control-next-icon" />;
const [control, setControl] = useState({ prev: null, next: null });
So basically the NEXT_ICON
is a constant declared on top.
If I have more than 4 items on my carousel I want to show the next icon
useEffect(() => {
const fetchSkills = async () => {
try {
const result = await skillsInformationService.getSkills(sessionUserInfo.jigsawId);
setSkillGroups(result);
const slices = _(result).keys().chunk(4).value();
setGroupSlices(slices);
setLoading(false);
setControl({
prev: null,
next: (_(result).size() < 4) ? null : NEXT_ICON
});
} catch (error) {
setSkillGroups([]);
setGroupSlices([]);
}
};
fetchSkills();
}, [sessionUserInfo.jigsawId, NEXT_ICON]);
VSCode
added by default the NEXT_ICON
to the array of params of useEffect
, I didn't realize until I saw that useEffect
kept on being called.
So then I delete NEXT_ICON
and it was only being called once, but if I do that the setControl({})
seems to not be called.
But I might have misunderstood the use of useEffect
, why is useEffect
being called if NEXT_ICON
is a constant that doesn't change. And I think that if I want to use a variable inside useEffect
I have to call it the params right. So I do need to put NEXT_ICON
next to sessionUserInfo.jigsawId
, otherwise it is null
? Right?
Upvotes: 0
Views: 90
Reputation: 7428
You're having an infinite loop because the identities of objects stored in your constants PREV_ICON
and NEXT_ICON
change for every single render (as soon as you're using functional component) and while having NEXT_ICON
as a dependency for useEffect
hook - you're just basically having a new object every time (which changes for every render).
Also storing the whole components (like PREV_ICON
and NEXT_ICON
) to the internal state of the object might not be the best decision.
Possible options to fix this situation:
PREV_ICON_VISIBLE
, NEXT_ICON_VISIBLE
and based on their values later render whatever content you want.PREV_ICON
and NEXT_ICON
out of your functional component.PREV_ICON
and NEXT_ICON
(which might not be the most elegant way).Upvotes: 1
Reputation: 195992
It is a constant in the block it is defined. Since the block in your case is the functional component, each time you re-render the component the function is re-run, and thus you create a new PREV_ICON
,NEXT_ICON
, and the useEffect
will be executed.
The solution is to move the two constants outside of the function.
const PREV_ICON = <span aria-hidden="true" className="carousel-control-prev-icon" />;
const NEXT_ICON = <span aria-hidden="true" className="carousel-control-next-icon" />;
const YourComponent = () => {
const [control, setControl] = useState({ prev: null, next: null });
....
useEffect( ... ,[sessionUserInfo.jigsawId, NEXT_ICON]); // whether you have NEXT_ICON here, or not, now makes no difference.
Upvotes: 2