I'm currently working on a website where I use Strapi as a CMS and Next.js(React) in Frontend. The site also has an image slider which obviousely contains an image, a headline and a description.
After some time on the website the following error occurs and the slider stops from working or does things like showing all slides really fast one behind the other. What can I do to solve this?
Unhandled Runtime Error TypeError: Canot read property 'classList' of undefined
I've already tried many solutions I found here on StackOverflow, but nothing worked... I am just not able to find the error in my code, which is the following: (/components/image-slider file)
import ...
const Slider = ({...}) => {
if (typeof window !== 'undefined') {
var slides = document.querySelectorAll('.slide');
var btns = document.querySelectorAll('.btn-navig');
let currentSlide = 1;
// Javascript for image slider manual navigation
var manualNav = function(manual){
slides.forEach((slide) => {
slide.classList.remove('active');
btns.forEach((btn) => {
btn.classList.remove('active');
});
});
slides[manual].classList.add('active');
btns[manual].classList.add('active');
}
btns.forEach((btn, i) => {
btn.addEventListener("click", () => {
manualNav(i);
currentSlide = i;
});
});
// // Javascript for image slider autoplay navigation
var repeat = function(activeClass){
let active = document.getElementsByClassName('active');
let i = 1;
var repeater = () => {
setTimeout(function(){
[...active].forEach((activeSlide) => {
activeSlide.classList.remove('active');
});
slides[i].classList.add('active');
btns[i].classList.add('active');
i++;
if(slides.length == i){
i = 0;
}
if(i >= slides.length){
return;
}
repeater();
}, 10000);
}
repeater();
}
repeat();
}
if (error) {
return <div>An error occured: {error.message}</div>;
}
return (
<div className="img-slider">
<div className="slide active">
<div className="info">
// content
</div>
</div>
<div className="slide">
<div className="info">
// content
</div>
</div>
// further slides
<div className="navigation">
<div className="btn-navig active"></div>
<div className="btn-navig"></div>
<div className="btn-navig"></div>
</div>
</div>
);
};
// axios request ...
export default Slider;
I hope someone can help me with the above mentioned problem. Thanks a lot!
Your first flaw in the code is this one
var manualNav = function(manual){
slides.forEach((slide) => {
slide.classList.remove('active');
btns.forEach((btn) => {
btn.classList.remove('active');
});
});
slides[manual].classList.add('active');
btns[manual].classList.add('active');
}
Here, with every new slide
of slides[]
, you start a new btns[]
loop.
btns.forEach((btn) => {
btn.classList.remove('active');
});
But this is just unnecessary processing time that gets lost. Do it this way:
var manualNav = function(manual){
slides.forEach((slide) => {
slide.classList.remove('active');
});
btns.forEach((btn) => {
btn.classList.remove('active');
});
slides[manual].classList.add('active');
btns[manual].classList.add('active');
}
Your actual problem is this.
You have 3 div
with the class btn-navig
but only 2 with the class slide
. But in your repeater()
you increase i
by 1 with every new loop.
slides[i].classList.add('active');
btns[i].classList.add('active');
i++;
With the second iteration you have the following situation:
slides[2].classList.add('active'); // undefined
btns[2].classList.add('active'); // value
There is no slides[2]
as only slides[0]
and slides[1]
have values.
You have to rethink your indexing-approach.