I'm getting an infinite Loop in my React application.
I'm trying to get a previous Image and next Image button. In developement I handle this with an image tag. If my component is loading up the error accures.
Has somebody an idea how I can solve this issue?
Sorry for the spagetti-code I'm trying try and error and there I issued lots of useState's :D.
Thank you in advance!
Some explaining: the "imageArray" does contain an array with all picture names.
The "activeIndex" does contain the active index of the imageArray providing by another component.
The other two useStates should be self explaining :)
function FullImage(props) {
const [imageArray, setImageArray] = [props.imageArray];
const [activeIndex, setActiveIndex] = useState(props.activeIndex);
const [imageLink, setImageLink] = useState("/uploads/1/" active "");
const [newImageLink, setNewImageLink] = useState(null);
setNewImageLink("/uploads/1/" imageArray[activeIndex - 1] "");
return (
<div className="activeImage">
<img
src="/img/websrc/prev.png"
className="prevImage"
onClick={() => setImageLink(newImageLink)}
></img>
<img src={imageLink} className="mainImage"></img>
<img src="/img/websrc/next.png" className="nextImage"></img>
</div>
);
}
The error:
Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
The above error occurred in the <FullImage> component:
CodePudding user response:
I fixed it with a lot of try and error. But for anyone who has the same problem i fixed it by getting a second array with the actual links. Also I was able to reduce my useState's and as well I added a keydown listener to navigate with arrow keys
function FullImage(props) {
const [activeIndex, setActiveIndex] = useState(props.activeIndex);
const [imageLink, setImageLink] = useState(
"/uploads/" props.pid "/" props.active ""
);
const imageArrayWithLinks = [];
for (let index = 0; index < props.imageArray.length; index ) {
imageArrayWithLinks.push(
"/uploads/" props.pid "/" props.imageArray[index]
);
}
useEffect(() => {
document.addEventListener("keydown", detectKeyDown, true);
}, []);
const detectKeyDown = (e) => {
console.log(e.key);
if (e.key === "ArrowLeft") {
setImageLink(imageArrayWithLinks[activeIndex - 1]);
setActiveIndex(activeIndex - 1);
} else if (e.key === "ArrowRight") {
setImageLink(imageArrayWithLinks[activeIndex 1]);
setActiveIndex(activeIndex 1);
}
};
return (
<div className="activeImage">
<img
src="/img/websrc/prev.png"
className="prevImage"
onClick={() => {
setImageLink(imageArrayWithLinks[activeIndex - 1]);
setActiveIndex(activeIndex - 1);
}}
></img>
<img src={imageLink} className="mainImage"></img>
<img
src="/img/websrc/next.png"
className="nextImage"
onClick={() => {
setImageLink(imageArrayWithLinks[activeIndex 1]);
setActiveIndex(activeIndex 1);
}}
></img>
</div>
);
}
Hope this will help some people.
CodePudding user response:
In React, you can use the onClick
event to handle a click on an image and change the src
attribute of another image. However, if you are not careful, you can accidentally create an infinite loop where the onClick
event keeps firing and changing the src
attribute, causing the event to fire again, and so on.
To avoid this, you can use a boolean
flag to track whether the onClick
event has already fired and stop it from firing again until the flag is reset. Here is an example of how to do this:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
isClicked: false,
};
}
handleClick() {
if (!this.state.isClicked) {
// Change the src attribute of another image
// ...
this.setState({ isClicked: true });
}
}
render() {
return (
<div>
<img src={image1Src} onClick={this.handleClick} />
<img src={image2Src} />
</div>
);
}
}
In this example, the handleClick
method is called when the first image is clicked. It checks the isClicked
flag in the component's state, and if it is not set, it changes the src
attribute of the second image and sets the flag to true. This prevents the handleClick
method from being called again until the flag is reset.
You can reset the flag by adding a button or some other UI element that allows the user to reset the state, or you can reset it automatically after a certain amount of time using setTimeout
.