Jimmy
Jimmy

Reputation: 48

React JS Custom Component Animation

I have a ReactJS component that looks like this:

import React from 'react';

class Circle extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isLoaded: false,
            percent: null
        };
    }    

    componentDidMount() {
        const url = "base url here" + this.props.endpoint;
        fetch(url)
            .then(res => res.json())
            .then(
                (result) => {
                    this.setState({
                        isLoaded: true,
                        percent: result.percent
                    });
                },
                (error) => {
                    this.setState({
                        isLoaded: true,
                        error: error
                    });
                }
            )
    }

    render() {
        return (
            <div className={"col-md-" + this.props.size + " progress-circles"} data-animate-on-scroll="on">
                <div className="progress-circle" data-circle-percent={"" + this.state.percent + ""} data-circle-text="">
                <h4>{this.props.title}</h4>
                    <svg className="progress-svg">
                        <circle r="80" cx="90" cy="90" fill="transparent" strokeDasharray="502.4" strokeDashoffset="0"></circle>
                        <circle className="bar" r="80" cx="90" cy="90" fill="transparent" strokeDasharray="502.4" strokeDashoffset="0"></circle>
                    </svg>
                </div>
            </div>
        );
    }
}

export default Circle;

So far, this works like a total charm. The only problem is that there's an animation associated with this element that fills in the progress-circle and it doesn't occur after I've set the value from the componentDidMount function. The animation does occur if I set the value via props from the parent component. Am I missing something? I'm new to React so it could be something simple. Thanks in advance!

Upvotes: 1

Views: 111

Answers (1)

Hemadri Dasari
Hemadri Dasari

Reputation: 34004

The issue with your solution is you are rendering animation always irrespective of whether you do fetch call or not.

Few things I would like to explain here before solution

  1. Make isLoaded to true before fetch call in componentDidMount
  2. When you get success/error response turn isLoaded to false
  3. When you get success response you should also change your error state to null to make it work second time
  4. When you get error response you should also change your percent state to null to make it work second time
  5. Show loader when isLoaded is true, error and percent both null
  6. Show success response when percent is not null, isLoaded false and error is null
  7. Show error response when error is not null, isLoaded false and percent is null

This is how I normally do in my application

import React from 'react';

class Circle extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
            isLoaded: false,
            percent: null
        };
    }    

    componentDidMount() {
        const url = "base url here" + this.props.endpoint;
        this.setState({
            isLoaded: true
        });
        fetch(url)
            .then(res => res.json())
            .then(
                (result) => {
                    this.setState({
                        isLoaded: false,
                        percent: result.percent,
                        error: null
                    });
                },
                (error) => {
                    this.setState({
                        isLoaded: false,
                        error: error,
                        percent: null
                    });
                }
            )
    }

    render() {
        const { isLoaded } = this.state;
        return (
            <div className={"col-md-" + this.props.size + " progress-circles"} data-animate-on-scroll="on">
                {isLoaded && percent == null && error == null && (<div className="progress-circle" data-circle-percent={"" + this.state.percent + ""} data-circle-text="">
                <h4>{this.props.title}</h4>
                    <svg className="progress-svg">
                        <circle r="80" cx="90" cy="90" fill="transparent" strokeDasharray="502.4" strokeDashoffset="0"></circle>
                        <circle className="bar" r="80" cx="90" cy="90" fill="transparent" strokeDasharray="502.4" strokeDashoffset="0"></circle>
                    </svg>
                </div>)}
                {!isLoaded && percent != null && <h2>Success response</h2>}
                {!isLoaded && error != null && <h2>error occured</h2>}
            </div>
        );
    }}

    export default Circle;

Hope this answers your query

Upvotes: 1

Related Questions