6th Hokage
6th Hokage

Reputation: 39

React file throws error Cannot read property 'style' of undefined only when I refresh the page

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>

enter image description here

Upvotes: 0

Views: 1759

Answers (5)

Christian
Christian

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

Nemesis
Nemesis

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

Cequiel
Cequiel

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

akhtarvahid
akhtarvahid

Reputation: 9779

Use null check to avoid such cases

slides.length > 0 && slides[index].style

or

slides[index]?.style

Upvotes: 0

Ezequiel S. Sandoval
Ezequiel S. Sandoval

Reputation: 170

Add ? to each slides[index]?.style

Upvotes: 0

Related Questions