utilizing class manipulation to trigger keyframe animations in react

Currently, I am delving into my very first React project.

In my project, I have implemented an onClick event for one of the elements, which happens to be a button. The aim is to smoothly transition an image's opacity to 0 to indicate that the user has successfully added an input. The keyframe setup for this transition is as follows:

#showTick {
    width: 30%;
    opacity: 0;
}

.activateKF {
    animation: showTick 0.7s;
}

@keyframes showTick {
    0% {opacity: 0;}
    25% {opacity: 0.5;}
    50% {opacity: 1;}
    75% {opacity: 0.5;}
    100% {opacity: 0;}
}

The default styling for the showtick element is what I've defined. When the button is clicked, I want to add the .activateKF class to the #showTick element using the following code:

goalCreation=()=>{
    document.getElementById("showTick").classList.remove("activateKF"); 
    let goal = document.getElementById("enterGoal").value;
    if (goal.length < 1){
        return false;
    } else {
        document.getElementById("showTick").classList.add("activateKF");            
        this.props.submitGoal(goal);
    }
}

My intention is to remove the class within the same function so that the keyframe can be re-added to the element every time the button is clicked to trigger the animation. However, I'm facing an issue where this only works the first time. Even after removing the line that removes the class, it still only works once. I'm struggling to understand why.

I would greatly appreciate some assistance so that the keyframe becomes active every time the button is clicked.

Update: I have also provided the code for the actual React component that I'm working on as part of this question.

import React, { Component } from 'react';
import '../Styles/creategoal.css';
import specificGoal from '../Images/specificgoal.png';
import cost from '../Images/cost.png';
import tick from '../Images/greentick.jpg';
import '../Styles/creategoal.css';
import '../App.css';

export default class CreateGoal extends Component {
    constructor(props){
        super(props);
        this.state = {
            showCostDiv: false,
            showSpecificDiv: false
        }
    }

    goalCreation=()=>{
        let goal = document.getElementById("enterGoal").value;
        if (goal.length < 1){
            return false;
        } else {
            document.getElementById("showTick").classList.add("activateKF");            
            this.props.submitGoal(goal);
        }
    }

    closeHelp=(e)=>{
        let currentClicked = e.target.tagName;
        if (this.state.showCostDiv && currentClicked !== "SECTION"){
            this.setState({
                showCostDiv: false
            })
        if (this.state.showSpecificDiv && currentClicked !== "SECTION"){
            this.setState({
                showSpecificDiv: false
            })
        }
        }
    }

    openSpecificWindow=()=>{
        this.setState({
            showSpecificDiv: true
        })
    }

    closeSpecificWindow=()=>{
        this.setState({
            showSpecificDiv: false
        })
    }

    openCostWindow=()=>{
        this.setState({
            showCostDiv: true
        })
    }

    closeCostWindow=()=>{
        this.setState({
            showCostDiv: false
        })
    }

    render(){

        let specificDivStatus = "hideContent";
        let costDivStatus = "hideContent";

        if (this.state.showSpecificDiv){
            specificDivStatus = "showContent";
        }

        if (this.state.showCostDiv){
            costDivStatus = "showContent";
        }

        return (
        <div onClick={this.closeHelp} className="createGoal">

            <div id="banner" className="goalSetBanner">
                <h1>SET YOUR GOAL</h1>
            </div>
            <span className="goalTip">Consider the following when setting your goal:</span>

            <section id="BeSpecificHelp" className={specificDivStatus}>
                <p>Describe exactly what your goal is, and when its possible use numbers to make it measurable. This excercise will turn your idea or dream
                even closer to reality.</p>
                <br/>
                <p>Examples:</p>

                <p><span className="incorrect">Wrong:</span> Weight loss.<br/>
                <span className="correct">Right:</span> Losing 8Kg.</p>

                <p><span className="incorrect">Wrong:</span> Read more books.<br/>
                <span className="correct">Right:</span> Read a new book every 15 days.</p>

                <p><span className="incorrect">Wrong:</span> Buying a house.<br/>
                <span className="correct">Right:</span> Buying a house within two bedrooms in a given address.</p>

                <span id="closeWindowSpecific" onClick={this.closeSpecificWindow}>Close</span>              
            </section>

            <section id="considerCostHelp" className={costDivStatus}>
                <p>Do not focus only on the result you will get.</p>
                <p><strong>Your time and energy are limited resources</strong></p>

                <p>Reflect on what it will take you to achieve this goal.</p> 

                <p>Finish completing it if you are willing to pay the price.</p>

                <span id="closeWindowCost" onClick={this.closeCostWindow}>Close</span>              
            </section>

            <main className="setGoalInfo">
                <div id="beSpecificGoal" className="considerGoal">
                    <img src={specificGoal} alt="Specific Goal" />
                    <span className="goalHelp">Be as specific as possible</span>
                    <span id="beSpecificLink" onClick={this.openSpecificWindow} className="link-span">TAP FOR MORE INFO</span>
                </div>
                <div id="considerCost" className="considerGoal">
                    <img src={cost} alt="Cost of Goal" />
                    <span className="goalHelp">What will it cost you?</span>
                    <span id="considerCost" onClick={this.openCostWindow} className="link-span">TAP FOR MORE INFO</span>
                </div>
            </main>

            <div id="goalAdded">
                <img src={tick} id="showTick" alt="Goal Added" />
            </div>

            <div className="inputDiv">
                <input type="text" id="enterGoal" placeholder="What is your goal?"></input>
            </div>

            <button onClick={this.goalCreation} id="createGoal">CREATE MY GOAL</button>

        </div>
            )
    }
}

Thank you for any assistance provided.

Answer №1

When working with React, it is important to avoid directly manipulating the DOM. React creates a virtual DOM upon rendering and only updates the parts of the actual DOM that have changed. Directly manipulating the DOM outside of React's render cycle may not produce the desired results.

Additionally, it is not recommended to use the id attribute on React components, as this can reduce component reusability (since IDs should be unique on a page) and React will manage its own IDs in the DOM.

Instead of manipulating the DOM directly, consider using the ref attribute in React. The ref attribute can contain either null (when the component unmounts) or a reference to the element after it has mounted. However, this may not be necessary for your specific use case and you may want to explore options like React animation or adding a class based on local component state.

Looking at your current code, it seems like you are still learning React. Consider refactoring your code to make it more modular and reusable. One approach could be implementing a component like the one below:

 // Code example 
 // CSS example 
 // External script references 

The logic in the example component is based on React lifecycle events. When the button is clicked, the state changes to "submitted," triggering the componentDidUpdate event. This event checks if the submitted flag is true and sets a timeout to reset the flag after a certain duration.

The handleSubmit function can be customized to call an event handler passed through props.

When redesigning your components, consider creating separate components for different parts of your UI so they can be controlled via state and props, enhancing reusability.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the capabilities of Socket.IO in Node.js for establishing a connection with an external server

Background: My localhost (referred to as Server A) hosts a node.js server, while an external server running node.js can be found at (known as Server B). Although I lack control or access over Server B, which serves as a dashboard site for an IoT device in ...

Update to react version 18.2.0, router-dom v6, and mui 5 for improved performance

Struggling to convert the following file or code into React's latest version and react-router-dom v6. I attempted it myself but encountered errors related to createBrowserHistory that I couldn't comprehend. My routes are stored in a JSON file and ...

Obtaining the designated item within the list

My list contains elements obtained from a database. I want to ensure that the selected elements remain visible at all times, even after refreshing the page. Here's an example: <select id="select-firm" class="form-control" name="firmId" size="20" ...

Personalized tooltips for numerous data sets in Highcharts

I am currently in the process of constructing a highchart that is capable of accommodating up to five different types of data series. I have arranged similar series together, resulting in three distinct y-axes for the various series. However, I have encou ...

Having trouble with Material-UI TextField state getting messed up after making uncontrolled value changes using react-hook-form?

Below is a Material-UI TextField element: <TextField variant='outlined' fullWidth name={'webhook'} label={'Webhook URL'} defaultValue={state.webhook} error={errors.webhook !== undefined} helperText= ...

JQuery is having issues with $(this) and the find function not working properly

I am attempting to access a child of the div with the class form-group, specifically, I want to display the value of the input element. <div class="form-group"> <label>text</label> <input name="text" type="text" class="form-co ...

Save the array as a variable in your JavaScript code so that you can easily access it

I am currently working on generating a list only when a specific page is visited using JS/jQuery. I then need to be able to access this list when navigating to other pages and retrieve the variables within it. How can I effectively store this list? Initia ...

Obtain an oAuth token through the use of npm

Recently, I've been working on a nodeJS service to fetch an OAuth token from a server. Unfortunately, I keep encountering errors when running the function below: var express = require('express') var http = require('http'); var htt ...

When an `angularjs select` is used with a filter, the first line may appear empty at first. However

I'm feeling a bit confused about why my ng-options is once again giving me an empty line with a filter applied. Could you please take a look at this plunker to see the issue? The goal is to show an org chart in a dropdown list that is based on a tre ...

How is it possible to encounter a Javascript unexpected token ] error within an HTML code?

While working on my project, I encountered a JavaScript error in the console of Chrome. The error message stated "Unexpected token ]" and it was pointing to a specific line of raw HTML code. I am puzzled about what could be causing this issue. Unfortunatel ...

What is the best way to halt Keyframe Animation once users have logged in?

To enhance user engagement, I incorporated keyframe animation into my login icon on the website. The main objective is to capture the attention of visitors who are not registered users. However, once a user logs in, I intend for the keyframe animation to c ...

Ways to superimpose images

Everything seems to be functioning correctly in my code, but I would like the output images to overlap slightly. This could possibly be achieved using margins, padding, or some other script. Additionally, is there a way to incorporate z-index so that the ...

Imitating CSS3 features on IE6 and other browsers

Does anyone know of a tool or resource that can replicate all the nice features of CSS3 (like shadow, glow, and round corners) but make them compatible with IE6 or at least emulate its appearance? I tried using this method, but unfortunately it resulted i ...

New options for outdated Webpack i18n plugin and loader

I am currently working on a TypeScript project that requires loading translations from individual .json files assigned to each country. For instance, we would have separate language files like en.json, es.json. The goal is to be able to access these trans ...

Tips for sending multiple values in a data object using jQuery AJAX

I am currently working on a form that contains two input fields, with the possibility of more being added later. The first input is a text field and the second is a checkbox. I want to be able to send these inputs using $.ajax. To accomplish this, I have ...

Adjusting the decimal points of numbers within a table to create the illusion of a "centered" alignment within the cell

Looking for a table design featuring a column of decimal numbers, each with varying lengths before and after the decimal point, while keeping the decimal points aligned. The width of the column should be flexible, expanding to accommodate long numbers in ...

Issue with combining jQuery-UI and Bootstrap offcanvas components

I've been struggling to understand why my Bootstrap navbar isn't working properly with jQuery-UI. It seems like they're not cooperating, and I can't seem to figure out the issue. If you have any insight into this problem, you'll be ...

Implementing a New Port Number on a ReactJs Local Server Every Time

As a newcomer to ReactJS, I recently encountered an issue while working on a project that puzzled me. Every time I shut down my local server and try to relaunch the app in the browser using npm start, it fails to restart on the same port. Instead, I have ...

Establishing specific categories for a universal element

I have been working on creating an input component that functions as a custom select for enums in my application. I have tried defining them for different types using concise one-liners but have run into various typing issues. Here is what I have so far: ...

Prop in a React component is undergoing mutation

I encountered a strange situation where a prop in a React component is being changed. Although it's technically not a mutation since it's an array in JavaScript, it should not be modified. To replicate the issue, I created a simple example: htt ...