Search code examples
javascriptreactjscallbacksetstatechain

Chain React setState callbacks


I need to load three different json files in an ordered sequence and with a fetch (the reason is i'm using nextjs export and i need those files to be read dynamically, so I fetch them when needed and their content can change even after the export)

The first file contains data that is used to create the url for the second file and so on, so each fetch needs an actually updated state to be fetched,

ATM the solution i'm using, since the second and third files are dependent from the first and second respectively, is fetching the first file and setting some state with setState, then in the setState callback fetch the second file and set some other state and so on:

fetch(baseUrl).then(
            response => response.json()
        ).then(
            res => { 
                this.setState({
                    ...
                }, () => {
                    fetch(anotherUrl+dataFromUpdatedState).then(
                        response => response.json()
                    ).then(
                        res => { 
                            this.setState({
                                ...
                            }, () => {                                 
                                fetch(anotherUrl+dataFromUpdatedState).then(
                                    response => response.json()
                                ).then(
                                    res => {
                                        this.setState({

                                        })
                                    }
                                )
                            })
                        }
                    ).catch(
                        error => {
                            //error handling
                        }
                    )
                })
            }
        ).catch(
            error => {
                this.setState({ //an error occured, fallback to default
                    market: defaultMarket,
                    language: defaultLanguage,
                    questions: defaultQuestions
                })
                //this.setLanguage();
            }
        )

Now: I know that setState must be used carefully as it is async, but as far as I know the callback function is called after state is updated so from that point of view the state should update correctly. Is this solution anti-pattern, bad practice or should be avoided for some reason?

The code actually works, but i'm not sure if this is the way to do it.


Solution

  • You don't need to use the setState callback and read it from the state, since you can just read the data directly from the res object. This way you can make a flat promise chain.

    Example

    fetch(baseUrl)
      .then(response => response.json())
      .then(res => {
        this.setState({
          // ...
        });
    
        return fetch(anotherUrl + dataFromRes);
      })
      .then(response => response.json())
      .then(res => {
        this.setState({
          // ...
        });
    
        return fetch(anotherUrl + dataFromRes);
      })
      .then(response => response.json())
      .then(res => {
        this.setState({
          // ...
        });
      })
      .catch(error => {
        this.setState({
          market: defaultMarket,
          language: defaultLanguage,
          questions: defaultQuestions
        });
      });