Bradley Bradley - 3 months ago 44
Javascript Question

Re-Render React Component After AJAX Request

I'm building a CRUD application with React and I wondered if you could help on this issue.

I am making a AJAX GET request with

componentDidMount
to the server which retrieves the data and then sets the state in the success function. In the render function I then map over the
state
array and render each state into a
<li>
element and include a
<button>
element.

When the
<button>
element is clicked it calls the
delete()
function. This then calls the AJAX DELETE request on the ID.

My problem is how do I get the component to re-render or update the state after the AJAX request is a success?

import React from 'react';

class PostList extends React.Component {
constructor() {
super();
this.state = {
posts: []
}
}

componentDidMount() {
$.ajax({
url: '/posts',
type: "GET",
dataType: 'json',
cache: false,
success: function(data) {
this.setState({posts: data})
}.bind(this)
});
}

delete(event) {
let postId = event.target.parentNode.getAttribute("data-id");
$.ajax({
url: '/posts/' + postId,
type: "DELETE",
success: function(data) {
console.log(data);
}.bind(this)
});
}

render() {
let posts = this.state.posts.map( (index) => {
return <li data-id={index._id} className="list-group-item"><a href={"posts/" + index._id}>{index.title}</a><button className="btn btn-default" onClick={this.delete.bind(this)}>Delete</button></li>
})
return (
<ul className="list-group">
{posts}
</ul>
)
}
}

export default PostList;

Answer

Update the state in the delete handler.

You've got two options:

  1. optimistic, it instantly updates the UI, however, the request could fail and you need to handle this case.

    delete(event) {
      let postId = event.target.parentNode.getAttribute("data-id");
      this.setState({
        posts: this.state.posts.filter(post => post._id !== postId)
      })
      $.ajax({
         url: '/posts/' + postId,
         type: "DELETE"
      });
    }
    
  2. pessimistic, will only mutate the state with a successful request, but could take a while before the UI is updated.

    delete(postId) {
      $.ajax({
         url: '/posts/' + postId,
         type: "DELETE",
         success: function(data) {
          this.setState({
            posts: this.state.posts.filter(post => post._id !== postId)
          })
         }.bind(this)
      });
    }
    

For handling state, you could dive into state management libraries like Redux.