maslak
maslak

Reputation: 1255

Components render multiple times - multiple fetch functions

My component renders 4 times and it seems to be caused by fetching and multiple setState functions. How can I make it use just one setState() including all fetched data?

I have already tried to create one function instead of one, create three variables to store fetch results and pass them to setState but it did not help me. Thanks in advance!

class DuelList extends React.Component {
    state = {
        duels: [],
        users: [],
        datasets: []
    };

    fetchDuels = () => {
        axios.get("http://127.0.0.1:8000/api/duel/user/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})
            .then(res => {
                this.setState({
                    duels: res.data
                });
            });
    };

    fetchUsers = () => {
        axios.get("http://127.0.0.1:8000/api/user/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})
            .then(res => {
                this.setState({
                    users: res.data
                });
            });
    };

    fetchDatasets = () => {
        axios.get("http://127.0.0.1:8000/api/dataset/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})
            .then(res => {
                this.setState({
                    datasets: res.data
                });
            });
    };


    componentDidMount() {
        this.fetchDuels();
        this.fetchUsers();
        this.fetchDatasets();
    }


    render() {
        return (
            <div>
                <Duels data={this.state.duels}/> <br/>
                <h2> Add duel </h2>
                <AddDuelForm users={this.state.users} datasets={this.state.datasets} requestType="post" articleID={null}
                             btnText="Challenge"/>
            </div>
        );
    }
}

export default DuelList;```


Upvotes: 2

Views: 427

Answers (2)

Shubham Khatri
Shubham Khatri

Reputation: 281726

Make use of Promise.all and setState once all the apis resulted in success response like

class DuelList extends React.Component {
    state = {
        duels: [],
        users: [],
        datasets: []
    };

    fetchDuels = () => {
        return axios.get("http://127.0.0.1:8000/api/duel/user/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})

    };

    fetchUsers = () => {
        return axios.get("http://127.0.0.1:8000/api/user/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})

    };

    fetchDatasets = () => {
        return axios.get("http://127.0.0.1:8000/api/dataset/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})

    };


    componentDidMount() {
        Promise.all([this.fetchDuels(), this.fetchUsers(), this.fetchDatasets()]).then(([duels, users, datasets]) => {
            this.setState({
                 duels,
                 users,
                 datasets
            })
        });
    }


    render() {
        return (
            <div>
                <Duels data={this.state.duels}/> <br/>
                <h2> Add duel </h2>
                <AddDuelForm users={this.state.users} datasets={this.state.datasets} requestType="post" articleID={null}
                             btnText="Challenge"/>
            </div>
        );
    }
}

export default DuelList;

Upvotes: 1

Davin Tryon
Davin Tryon

Reputation: 67296

You would need to group and resolve all the promises together:

    fetchDuels = () => {
        return axios.get("http://127.0.0.1:8000/api/duel/user/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})
    };

    fetchUsers = () => {
        return axios.get("http://127.0.0.1:8000/api/user/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})
    };

    fetchDatasets = () => {
        return axios.get("http://127.0.0.1:8000/api/dataset/",
            {'headers': {'Authorization': `Token ${localStorage.getItem('token')}`}})
    };


    componentDidMount() {
        const promises = [this.fetchDuels(), this.fetchUsers(), this.fetchDatasets()];

        Promise.all(promises).then(([ duelsReponse, usersResponse, datasetsReponse ]) => {
            this.setState({ duels: duelsReponse.data, users: usersReponse.data, datasets: datasetsResponse.data });
        });
    }

This way, you reduce the number setState calls.

Upvotes: 3

Related Questions