Skip to content

Instantly share code, notes, and snippets.

@ikibalnyi
Last active August 28, 2019 14:05
Show Gist options
  • Save ikibalnyi/8b78902c1d83ba2bca2dc3c1a4d49cc8 to your computer and use it in GitHub Desktop.
Save ikibalnyi/8b78902c1d83ba2bca2dc3c1a4d49cc8 to your computer and use it in GitHub Desktop.
React HoC for populating component props
import React, { useCallback, useEffect, useState } from 'react';
/**
* HoC for prefetching component data from remote server.
*
* @param fetchData(props) - async function generator for fetching data
* @param getInitialState(props)? - function to get initialState
* @param depsFn(props)? - function to set deps for useEffect
*/
function prepopulate(fetchData, getInitialState, depsFn) {
return (WrappedComponent) => {
return (props) => {
const initialState = getInitialState ? getInitialState(props) : {};
const [fetchedData, setFetchedData] = useState({ ...initialState, isFetching: true });
const populate = useCallback(async (props) => {
for await (const data of fetchData(props)) {
setFetchedData(prevState => ({
...prevState,
...data,
isFetching: true,
}));
}
setFetchedData(prevState => ({ ...prevState, isFetching: false }));
}, []);
useEffect(() => {
populate({ ...props, ...fetchedData });
}, depsFn ? depsFn(props) : []);
return <WrappedComponent { ...props } { ...fetchedData } repopulate={populate} />;
};
};
}
export default prepopulate;
import prepopulate from './prepopulate';
async function* fetchData({ id }) {
yield { isLoading: true };
try {
const user = await fetch(`/user/${id}`);
yield { user, isLoading: false };
} catch (error) {
yield { error, isLoading: false };
}
}
const getInitialState = (props) => ({
isLoading: true,
user: null,
error: false
});
const depsFn = (props) => ([ props.isAuthenticated ])
@prepopulate(fetchData, getInitialState, depsFn)
const MyComponent = ({ isLoading, user, error }) => {
if (isLoading) return 'I\'m loading...';
if (error) return 'Something went wrong :(';
return (
<div>
{user.id}
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment