Last active
November 9, 2017 12:09
-
-
Save codeocelot/b4b27fff646bed8c3afcde8db5d3fb3b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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