Skip to content

Instantly share code, notes, and snippets.

@acdlite
Last active June 11, 2021 08:34
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save acdlite/975b4c880908fa9ae2547284aa790d6b to your computer and use it in GitHub Desktop.
Save acdlite/975b4c880908fa9ae2547284aa790d6b to your computer and use it in GitHub Desktop.
Prefetching in React
function prefetch(getKey, getValue, getInitialValue, propName) {
const inFlight = new Set();
const cache = new Map();
return ChildComponent => {
return class extends React.Component {
state = {value: getInitialValue(this.props)};
componentWillReceiveProps(nextProps) {
const key = getKey(nextProps);
if (cache.has(key)) {
// Use cached value
this.setState({value: cache.get(key)});
}
}
async componentWillUpdate(nextProps) {
const key = getKey(nextProps);
if (cache.has(key) || inFlight.has(key)) {
// Request already in-flight
return;
}
inFlight.add(key);
const value = await getValue(key);
inFlight.delete(key);
cache.set(key, value);
this.setState({value});
}
render() {
const props = {[propName]: this.state.value};
return <ChildComponent {...props} />;
}
};
};
}
// Can use on multiple components, will share same internal cache
const prefetchThing = prefetch(
props => props.thingId,
thingId => fetch(`/api/thing/${thingId}`),
() => null,
'thing'
);
function View({thing}) {
if (user === null) {
return <LoadingSpinner />;
}
return <BlahBlahRealCode thing={thing} />;
}
export default prefetchThing(View);
@acdlite
Copy link
Author

acdlite commented Jul 20, 2017

Didn't proofread, probably bugs!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment