Alias
Alias

Reputation: 3091

ReactJS Loading icon while waiting for data

I'm experimenting with ReactJS, and much of my application relies on loading data from an API, using jQuery to help me with that.

I have loading text/icon setup, but it feels a bit hacky and not very reusable:

ListWrapper = React.createClass({
    getInitialState: function() {
        return {
            loading: true,
            listData: []
        };
    },
    componentDidMount: function() {
        Api.get('/v1/listdata', function (data) {
            react.setState({
                    loading: false,
                    listData: data
            });
        });
    },
    render: function() {
        return (
            <List loading={this.state.loading} data={this.state.listData} />
        );
    }
});

List = React.createClass({
    render: function() {

        var mapData;
        if (this.props.loading)
            mapData = <Loader />; 
        else {
            mapData = this.props.data.map(function(item) {
                return (
                    <ListItem name={item.name} />
                );
            });
        }

        return (
            <div>
                {mapData}
            </div>
        );
    }
});

This works fine, however the whole if/else statement has hints of code smells since I'd have to do that logic all over the place.

Can't really find anything on the web about how to best approach this... Whats a better way?

Upvotes: 7

Views: 10194

Answers (1)

trekforever
trekforever

Reputation: 3922

You can simplify your existing code to be less verbose just by removing the else statement:

render: function() {
        if (this.props.loading) {
            return <Loader />;
        }
        var mapData = this.props.data.map(function(item) {
            return (
                <ListItem name={item.name} />
             );
        });
        return (
            <div>
                {mapData}
            </div>
        );
    }

But one solution I can think of is have your component accept a isActive bool and moving the if logic into the loader component instead of the individual components. When isActive = true it shows the spinner/loading icon. Otherwise it just returns a null component or empty .

List = React.createClass({
    render: function() {

        var mapData = this.props.data.map(function(item) {
            return (
                <ListItem name={item.name} />
            );
        });
        return (
            <div>
                <Loader isActive={this.props.isLoading} />
                {mapData}
            </div>
        );
    }
});

This case instead of doing the if logic everywhere, you just do it once in your Loader component, and it just returns null/empty if its inactive.

Upvotes: 11

Related Questions