Last active
June 16, 2024 21:56
-
-
Save bvaughn/982ab689a41097237f6e9860db7ca8d6 to your computer and use it in GitHub Desktop.
Example for loading new external data in response to updated props
This file contains 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
// This is an example of how to fetch external data in response to updated props, | |
// If you are using an async mechanism that does not support cancellation (e.g. a Promise). | |
class ExampleComponent extends React.Component { | |
_currentId = null; | |
state = { | |
externalData: null | |
}; | |
static getDerivedStateFromProps(nextProps, prevState) { | |
// Store prevId in state so we can compare when props change. | |
// Clear out previously-loaded data (so we don't render stale stuff). | |
if (nextProps.id !== prevState.prevId) { | |
return { | |
externalData: null, | |
prevId: nextProps.id | |
}; | |
} | |
// No state update necessary | |
return null; | |
} | |
componentDidMount() { | |
this._loadAsyncData(this.props.id); | |
} | |
componentDidUpdate(prevProps, prevState) { | |
if (this.state.externalData === null) { | |
this._loadAsyncData(this.props.id); | |
} | |
} | |
componentWillUnmount() { | |
// Prevent potential setState calls after unmount, | |
// (Since these trigger DEV warnigs) | |
_currentId = null; | |
} | |
render() { | |
if (this.state.externalData === null) { | |
// Render loading state ... | |
} else { | |
// Render real UI ... | |
} | |
} | |
_loadAsyncData(id) { | |
if (id === this._currentId) { | |
// Data for this id is already loading | |
} | |
this._currentId = id; | |
asyncLoadData(id).then(externalData => { | |
// Only update state if the Promise that has just resolved, | |
// Reflects the most recently requested external data. | |
if (id === this._currentId) { | |
this.setState({ externalData }); | |
} | |
}); | |
} | |
} |
A bug:
componentDidUpdate(prevProps, prevState) { if (prevState.externalData === null) { this._loadAsyncData(this.props.id); } }
must read
componentDidUpdate(prevProps, prevState) { if (this.state.externalData === null) { this._loadAsyncData(this.props.id); } }
Yes, This will cause the second render to fail. Because prevState
is having old data now.
Blog post have the correct code
Thanks for pointing out the typo. I often don't notice comments on Gists. I've updated the example.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Stephen-ONeil I feel the same way,
if (id === this._currentId) {
is basically just an isMounted check ...