0

So I have an POST API that returns the object that was just created and I would like to get the objects information in reactjs.

createItem(item){
    let temp;
    // POST to DB
    fetch(url(this.props.api), {
        method:"POST",
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            name: item,
            isCompleted:false
        })
    }).then(function (response) {
        return response.json()
    }).then(function (body) {
        temp = body; // got the objects information
        console.log(temp);
    });

    console.log(temp);

    this.state.bucket_list.push({
        name: item,
        isCompleted: false
    });
    this.setState({bucket_list: this.state.bucket_list});

}

This is what I have but the I can extract the data outside the then function. After I get the information I would like to setState and append the newly created object to my state: bucketlist. But I think due to Javascript's asynchronous issues, I am unable to do this in the correct order. Any ideas?

anderish
  • 1,709
  • 6
  • 25
  • 58

1 Answers1

1

Before giving you the answer, you should know that directly mutating the state is considered as an antipattern. You should instead consider objects as immutable.

Instead of:

this.state.bucket_list.push({
  name: item,
  isCompleted: false
});
this.setState({bucket_list: this.state.bucket_list});

You should have done

this.setState({
  bucket_list: [
    ...this.state.bucket_list,
    {
      name: item,
      isCompleted: false
    },
  ]
});

Anyway, let me give you two different wayts to handle your usecase:

1. Use async/await (Recommended)

With the async/await you will be able to wait an instruction to finish before going to the next one.

    async createItem(item){
      // POST to DB
      const data = await fetch(url(this.props.api), {
        method:"POST",
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: item,
          isCompleted:false
        })
      });

      this.setState({
        bucket_list: [
          ...this.state.bucket_list,
          data,
        ],
      });
    }

2. Keep using fetch with then and use arrow function

It allows the function to not have their own this. That is why you can use the this.setState inside the arrow function.

    createItem(item){
      // POST to DB
      fetch(url(this.props.api), {
        method:"POST",
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: item,
          isCompleted:false
        })
      })
      .then(response => response.json())
      .then(data => {
        this.setState({
          bucket_list: [
            ...this.state.bucket_list,
            data,
          ],
        });
      });
    }

Note2: If your usecase is simple, you can keep using this method. Otherwise you should definitely take a look at redux

yuantonito
  • 1,274
  • 8
  • 17