Sanewa
Sanewa

Reputation: 44

JavaScript - fetch api data is run too late

I am fetching data from api to pass it as array to Select's options. The problem is that data is fetched too late. My constructor():

constructor(props) {
    super(props);
    this.state = {
      optionSelected: null,
      options: []
    };
  }

My componentDidMount():

componentDidMount() {
    fetch('/authors/')
      .then(response => response.json())
      .then(data => {
        for (var x in data) {
          this.state.options.push({"value": x, "label": data[x]})
        }
      })
  ;}

With code like that I get empty drop down, with only "select all" option available. But when I choose that "select all", drop down options are instantly populated with api data and all are selected. If I unselect all of them they remain as avaialble options. Can you please advice how can I make fetch populate options earlier then this so they were shown as select options from the very beggining?

Upvotes: 1

Views: 715

Answers (3)

Sudhansu Choudhary
Sudhansu Choudhary

Reputation: 3360

Keep note of how to update the state in an component - manage component state

componentDidMount() {
    fetch('/authors/')
      .then(response => response.json())
      .then(data => {           
          let options = Object.keys(data).reduce((accum, elem) => {
            accum.push[{"value": elem, "label": data[elem]}];
            return accum;
          }, []);

          this.setState((state) => {
            return {
              ...state,
              options: options
            }
          });
      });
}

Upvotes: 0

k-wasilewski
k-wasilewski

Reputation: 4623

Never modify a React state via this.state outside the constructor! Use a setState function instead.

Modify your function to:

componentDidMount() {
    fetch('/authors/')
      .then(response => response.json())
      .then(data => {
        let options = Object.assign({}, ...this.state.data);

        for (var x in data) {
          options.push({"value": x, "label": data[x]})
        }

        this.setState({ data });
      });
}

Upvotes: 0

user15118714
user15118714

Reputation:

Try out to update options by using spread operator :

componentDidMount() {
    fetch('/authors/')
      .then(response => response.json())
      .then(data => {
           let options=[]
           for (var x in data) {
             options.push({"value": x, "label": data[x]})
            }
        

        this.setState({...this.state,options:options});
      });
}

Upvotes: 3

Related Questions