1

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!

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

2 Comments

Hi! This helped a lot but I think I discovered the root of the problem - the animation is triggered by a function that is called in a scripts.js file on load. So I think it's just missing the element that's there since it loads after the script is run. Is there a way to re-trigger an arbitrary javascript function again? I currently have it imported to the page via index.html and the file is in my Public folder.
Share your index.html file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.