'Animation will not run even after adding animation class to the element via addEventListener in React

I am trying to trigger a progress bar animation when a scroll eventlistener is triggered by adding the animation class when a scroll is detected. But it only runs when the page loads and does not run after that, when I scroll. The following are the JS and CSS files. Is there something wrong with the code or am I using setState wrongly?

.body2 {
  background-color: #151515;
  height: 700px;
}

.title2 {
  font-size: 40px;
  font-family: handwritten;
  color: #d10100;
  text-align: center;
  padding-top: 100px;
  grid-area: 1 / 1 / 2 / 2;
  letter-spacing: 5px;
  font-stretch: extra-condensed;
}

.titleback2 {
  font-size: 90px;
  font-family: ARCHIVO-bold;
  -webkit-text-stroke-color: #212121;
  -webkit-text-stroke-width: 3px;
  color: #151515;
  text-align: center;
  padding-top: 75px;
  grid-area: 1 / 1 / 2 / 2;
}

.bar{
  background-color: #e3e3e3;
  width: 400px;
  height: 20px;

}

.bargrid {
  margin: 200px;
  height: 500px;
  display: grid;
  grid-template: 1fr 1fr  1fr/ 1fr 1fr;
  justify-items: center;
}

.barlabel {
  color: #e3e3e3;
  font-family: cafe;
  padding-bottom: 10px;
}

.progress{
  background-color: #d10100;
  background-image: linear-gradient(to right, #d10100 30%,#ff3231, #ff5f5e);
  height: 20px;
  position: relative;
  bottom: 20px;
  padding-left: 2px;
  padding-right: 2px;
  
}

.loadpage {
  animation: progressbar 2s normal;
}

@keyframes progressbar{
  0% {width: 0%}
  100% {width: 100%}

}

import React from "react";
import './Skills.css';

class Skills extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            progress: 'progress',
        }
        this.changeState = this.changeState.bind(this)
    }

    changeState = () => {
        this.setState({
            progress: 'progress loadpage'
        })
    }

    componentDidMount(){
        window.addEventListener('scroll', this.changeState)
        this.setState({
            progress: 'progress'
        })
    }

    render() { 

        return (
        <div className="body2">
            <div className="container">
                <div className="titleback2">SKILLS</div>
                <div className="title2">skills</div>
            </div>
            <div className="bargrid">
                <div className="cell1">
                    <div className="barlabel">HTML</div>
                    <div className="bar" />
                    <div className={this.state.progress} />
                </div>
                <div className="cell2">
                    <div className="barlabel">CSS</div>
                    <div className="bar" />
                    <div className={this.state.progress} />
                </div>
                <div className="cell3">
                <div className="barlabel">JAVASCRIPT</div>
                    <div className="bar" />
                    <div className={this.state.progress} />
                </div>
                <div className="cell4">
                    <div className="barlabel">REACT.JS</div>
                    <div className="bar" />
                    <div className={this.state.progress} />
                </div>
                <div className="cell5">
                    <div className="barlabel">FRAMER MOTION</div>
                    <div className="bar" />
                    <div className={this.state.progress} />
                </div>
                <div className="cell6">
                    <div className="barlabel">HTML</div>
                    <div className="bar" />
                    <div className={this.state.progress} />
                </div>
            </div>
        </div>
        );
    }
}

export default Skills;


Solution 1:[1]

It can be handled simply by using the animationend event in JavaScript.
mdn document address. ( https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationend_event )

I'll show you the code sandbox address, so it might be helpful for reference.
Code sandbox address. ( https://codesandbox.io/s/react-playground-forked-yzmjrn?file=/index.js )

Skills.js

import React from "react";
import "./Skills.css";

class Skills extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      progress: "progress"
    };
    this.changeState = this.changeState.bind(this);
  }

  changeState = () => {
    this.setState({
      progress: "progress loadpage"
    });
  };

  componentDidMount() {
    window.addEventListener("scroll", () => {
      console.log("scrolling...");
      this.changeState();
    });
    this.setState({
      progress: "progress"
    });

    // const animated = document.querySelector(".progress");

    // animated.addEventListener("animationend", () => {
    //   console.log("Animation ended");
    //   this.setState({
    //     progress: "progress"
    //   });
    // });

    // I think this is better than above code.
    document.addEventListener("animationend", (e) => {
      // console.log(e);
      console.log("Animation ended");
      // remove loadpage classname
      if (e.animationName === "progressbar") {
        this.setState({
          progress: "progress"
        });
      }
    });
  }

  render() {
    return (
      <div className="body2">
        <div className="container">
          <div className="titleback2">SKILLS</div>
          <div className="title2">skills</div>
        </div>
        <div className="bargrid">
          <div className="cell1">
            <div className="barlabel">HTML</div>
            <div className="bar" />
            <div className={this.state.progress} />
          </div>
          <div className="cell2">
            <div className="barlabel">CSS</div>
            <div className="bar" />
            <div className={this.state.progress} />
          </div>
          <div className="cell3">
            <div className="barlabel">JAVASCRIPT</div>
            <div className="bar" />
            <div className={this.state.progress} />
          </div>
          <div className="cell4">
            <div className="barlabel">REACT.JS</div>
            <div className="bar" />
            <div className={this.state.progress} />
          </div>
          <div className="cell5">
            <div className="barlabel">FRAMER MOTION</div>
            <div className="bar" />
            <div className={this.state.progress} />
          </div>
          <div className="cell6">
            <div className="barlabel">HTML</div>
            <div className="bar" />
            <div className={this.state.progress} />
          </div>
        </div>
      </div>
    );
  }
}

export default Skills;

It's not perfect, but I hope it helps?.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1