Skip to content

Instantly share code, notes, and snippets.

@codeocelot
Last active November 9, 2017 12:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codeocelot/b4b27fff646bed8c3afcde8db5d3fb3b to your computer and use it in GitHub Desktop.
Save codeocelot/b4b27fff646bed8c3afcde8db5d3fb3b to your computer and use it in GitHub Desktop.
import React from 'react';
import PropTypes from 'prop-types';
const route = 'https://jsonplaceholder.typicode.com/posts';
class AsyncPostHoC extends React.Component{
constructor(props){
super(props);
this.state = {
isFetching: true,
error: false,
};
}
componentDidMount = () => {
makeRequest(this.props.postId);
}
componentDidUpdate = (nextProps) => {
// make a request if props.postId changes, or the previous request failed.
if (nextProps.postId !== this.props.postId || this.state.error) {
this.makeRequest();
}
}
makeRequest = () => {
const postId = this.props.postId;
/* this.setState is actually an asynchronous function. You should never use this.setState and assume
you can then use this.state on subsequent lines. However, this.setState accepts a callback function
as a second argument. We'll use this to set isFetching: false before making the request. Otherwise,
it's possible (although unlikely) you'll receive the data before the component actually updates and
the component's state will read isFetching: true despite having the result */
this.setState(
{
isFetching: true,
post: undefined,
error: false,
},
() => {
fetch(`${route}/${postId}`)
.then((response) => response.json())
.then((post) => this.setState({
post,
isFetching: false,
}))
.catch((error) => this.setState({
isFetching: false,
error,
}))
}
)
}
render = () => {
const { children, postId, ...otherProps } = this.props;
// we want to render <ChildComponent {...this.props} post={this.state.post} />
// We must never mutate another component, but we can clone the child and stuff any
// extra props we desire.
return React.cloneElement(
children, // children is actually a single react component,
{
...otherProps,
isFetching: this.state.isFetching,
error: this.state.error,
post: this.state.post,
}
)
}
}
AsyncPostHoC.propTypes = {
postId: PropTypes.string.isRequired,
children: PropTypes.node.isRequired,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment