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?

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

2 Comments

body is undefined in the first method tho
My bad, little typo: use data instead of body. I edited my answer accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.