Skip to content

Instantly share code, notes, and snippets.

@camilokawerin
Last active June 22, 2020 20:45
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save camilokawerin/402533b49369c738eb3c69a499688a48 to your computer and use it in GitHub Desktop.
How to make AJAX requests to update state from props in ReactJS components

How to make AJAX requests to update state from props in ReactJS components

AJAX request should be done at the componentDidMount hook when you need to load data inmediatelly after the component is first rendered. When you wish to refresh the data after some props changed, you must use the componentDidUpdate hook.

But you'll have to take hand of another three lifecycle hooks to avoid starting an infinite loop of requests/updates. Assuming you wish to update a posts list based on props.category changes:

  • state should have two properties, category and currentCategory, set to null on the component's constructor;
  • getDerivedStateFromProps is needed to update state.category from the new props.category;
  • shouldComponentUpdate is needed to compare both state.category and state.currentCategory to determine if the component should be updated;
  • getSnapshotBeforeUpdate is needed to determine if componentDidUpdate should make an AJAX request or to change the state.currentCategory value and finish the updating cycle.

getDerivedStateFromProps and getSnapshotBeforeUpdate were introduced in React v16.3.0.

// External Dependencies
import React, { Component, Fragment } from 'react';
import axios from "axios";
class Post extends Component {
constructor(props) {
super(props);
this.state = {
posts: [],
category: null,
currentCategory: null
};
this._createMarkup = this._createMarkup.bind();
}
static getDerivedStateFromProps(props, state) {
if (props.category !== state.category) {
return {
category: props.category
};
}
return null;
}
componentDidMount() {
this._fetchData();
}
shouldComponentUpdate(nextProps, nextState) {
return this.state.currentCategory !== nextState.category;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
return prevState.currentCategory !== prevState.category;
}
componentDidUpdate(prevProps, prevState, dataDidFetch) {
// dataDidFetch is returned by getSnapshotBeforeUpdate
if (dataDidFetch) {
this.setState({
currentCategory: this.state.category
});
} else {
this._fetchData();
}
}
_fetchData() {
const category = this.state.category;
axios.get(`/some/api/endpoint?category=${category}`).then(posts => {
this.setState({
posts: posts.data
});
});
}
_createMarkup(html) {
return { __html: html };
}
render() {
return (
<Fragment>
{this.state.posts.map(post => (
<article className="post" key={post.id}>
<h2>{post.title.rendered}</h2>
<div dangerouslySetInnerHTML={this._createMarkup( post.content.rendered )} />
<p className="post-link">
<a href="{post.resource_link_url}">{post.resource_link_label}</a>
</p>
</article>
))}
</Fragment>
);
}
}
export default Post;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment