Reputation: 39
I have a card carousel that I want to "slide" through by updating the cards and selected "dot" for navigation.
An value is grabbed from a "dot" (used for navigation) from
<div className = "dots" onClick = {() => currentSlide(1)}></div>
<div className = "dots" onClick = {() => currentSlide(2)}></div>
<div className = "dots" onClick = {() => currentSlide(3)}></div>
The code is then sent to the following javascript that takes the index and uses it to update the carousel and display the appropiate slide.
// Initially displaying first slide:
var slideIndex = 1;
showSlides(slideIndex);
// Getting current slide from navigation dot
function currentSlide(n) {
console.log("pressed on the dot: " + n)
showSlides(slideIndex = n)
}
const dotStyle = {
}
function showSlides(n) {
var i; // variable for indexing
var slides = document.getElementsByClassName("slide_container");
var dots = document.getElementsByClassName("dots");
// Clearing All Slides:
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none"
}
// Setting Current Dot to Active:
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
// Displaying Other Slides:
slides[slideIndex - 1].style.display = "flex";
dots[slideIndex - 1].className += " active";
}
When I first ran this code it worked but upon reloading the page I recieved the error Cannot read property 'style' of undefined
Here is the rest of my project code for reference as well as a image to show what it should look like
import React, { useState, useEffect } from 'react';
import "./Message.css"
import quote from '../Home/icons/quote.svg'
import user from './imgs/user.svg'
const Message = () => {
// Initially displaying first slide:
var slideIndex = 1;
showSlides(slideIndex);
// Getting current slide from navigation dot
function currentSlide(n) {
console.log("pressed on the dot: " + n)
showSlides(slideIndex = n)
}
const dotStyle = {
}
function showSlides(n) {
var i; // variable for indexing
var slides = document.getElementsByClassName("slide_container");
var dots = document.getElementsByClassName("dots");
// Clearing All Slides:
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none"
}
// Setting Current Dot to Active:
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
// Displaying Other Slides:
slides[slideIndex - 1].style.display = "flex";
dots[slideIndex - 1].className += " active";
}
// Main/Return Function
return (
<>
<div className = "carousel_container">
<div className = "slide_container">
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 1</h2>
<p className = "card_position">Position 1</p>
</div>
</div>
</div>
</div>
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 2</h2>
<p className = "card_position">Position 2</p>
</div>
</div>
</div>
</div>
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 3</h2>
<p className = "card_position">Position 3</p>
</div>
</div>
</div>
</div>
</div>
<div className = "slide_container">
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 4</h2>
<p className = "card_position">Position 4</p>
</div>
</div>
</div>
</div>
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 5</h2>
<p className = "card_position">Position 5</p>
</div>
</div>
</div>
</div>
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 6</h2>
<p className = "card_position">Position 6</p>
</div>
</div>
</div>
</div>
</div>
<div className = "slide_container">
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 7</h2>
<p className = "card_position">Position 7</p>
</div>
</div>
</div>
</div>
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 8</h2>
<p className = "card_position">Position 8</p>
</div>
</div>
</div>
</div>
<div className = "card_container">
<div className = "message_icon_background">
<img src = {quote} className = "message_icon" />
</div>
<div className = "card">
<p className = "card_text">
Far far away, behind the word <br />
mountains, far from the countries <br />
Vokalia and Consonantia, there live the <br />
blind texts.
</p>
<div className = "card_info">
<img src = {user} className = "card_photo" />
<div className = "card_id">
<h2 className = "card_name">Name 9</h2>
<p className = "card_position">Position 9</p>
</div>
</div>
</div>
</div>
</div>
</div>
{/* Navigation Dots */}
<div className = "navigation_dots">
<div className = "dots" onClick = {() => currentSlide(1)}></div>
<div className = "dots" onClick = {() => currentSlide(2)}></div>
<div className = "dots" onClick = {() => currentSlide(3)}></div>
</div>
</>
)
}
export default Message
html {
background: no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
* {
all: none;
box-sizing: border-box;
margin: 0;
padding: 0;
scroll-behavior: smooth;
}
.carousel_container {
display: flex;
justify-content: center;
margin-top: -17vh;
-webkit-user-drag: none;
}
.slide_container {
display: grid;
gap: 7vw;
grid-auto-flow: column;
display: none; /* setting display intitally to nothing */
}
.card_container {
background-color: white;
border-radius: 3%;
background-color: #f8f9fd;
box-shadow: red;
}
.message_icon_background {
height: 40px;
width: 40px;
background-color: #55B441;
border-radius: 50%;
margin-top: -20px;
margin-left: 20px;
}
.message_icon {
height: 14px;
width: 14px;
margin: 30%;
filter: invert(100%);
}
.card {
border: none;
padding: 10px 20px 20px;
color: grey;
background-color: #f8f9fd;
}
.card_text{
font-size: 15px;
line-height: 1.8;
font-weight: 400;
}
.card_info {
display: flex;
gap: 20px;
}
.card_photo {
width: 80px;
height: 80px;
}
.navigation_dots {
margin-top: 20px;
display: flex;
justify-content: center;
gap: 1rem;
}
.dots {
height: 20px;
width: 20px;
background-color: #55B441;
border-radius: 50%;
transition: background-color 0.6s ease;
}
.active, .dots:hover {
background-color: darkgreen;
}
/* Fading Animation */
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Upvotes: 0
Views: 1759
Reputation: 366
The error is within var slides = document.getElementsByClassName("slide_container");
, which is initially display:none
and throws undefined.
You can probably just initialize it with an empty array if it's undefined and work from there:
function showSlides(n) {
var i; // variable for indexing
var slides = document.getElementsByClassName("slide_container") ? document.getElementsByClassName("slide_container") : []; // <---- here
Upvotes: 0
Reputation: 128
Your problem is a quite simple problem to solve.
Since you are calling the showSlides() function before the actual component is created it will try to get an element that does not exist, hence the "Cannot read property of undefined" error.
To fix this you can simply add a useEffect() hook which runs the showSlides() function once the component is mounted.
If you want a more in depth explanation I recommend watching Fireship's tutorial on React hooks. Here is a link for that: https://youtu.be/TNhaISOUy6Q
Here is a fixed version of your code!
// Initially displaying first slide:
var slideIndex = 1;
// Getting current slide from navigation dot
function currentSlide(n) {
console.log("pressed on the dot: " + n);
showSlides((slideIndex = n));
}
const dotStyle = {};
function showSlides(n) {
var i; // variable for indexing
var slides = document.getElementsByClassName("slide_container");
var dots = document.getElementsByClassName("dots");
// Clearing All Slides:
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
// Setting Current Dot to Active:
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
// Displaying Other Slides:
slides[slideIndex - 1].style.display = "flex";
dots[slideIndex - 1].className += " active";
}
useEffect(() => {
showSlides(slideIndex);
},[]);
Please tell me if this works.
Upvotes: 2
Reputation: 3777
Don't use document.getElementsByClassName
, document.getElementById
, etc... React uses "state variables". You are mixing different programming techniques.
I'd suggest you to read a React tutorial to understand the basic concepts: https://reactjs.org/tutorial/tutorial.html
Upvotes: 0
Reputation: 9779
Use null check to avoid such cases
slides.length > 0 && slides[index].style
or
slides[index]?.style
Upvotes: 0