Skip to content

Instantly share code, notes, and snippets.

@Deiru2k
Created October 6, 2017 15:55
Show Gist options
  • Save Deiru2k/a8159de6b2940775f73534a8931975c2 to your computer and use it in GitHub Desktop.
Save Deiru2k/a8159de6b2940775f73534a8931975c2 to your computer and use it in GitHub Desktop.
GENERICS, BRUH.
import * as React from 'react';
import * as Bluebird from 'bluebird';
import * as superagent from 'superagent';
type dataMapFN<T> = (originalData: any) => T;
type combineDataFN<T> = (oldData: T, newData: any) => T;
export interface FetcherPropGeneric<T> {
data?: T,
isLoading: boolean,
repeat(params: any): PromiseLike<FetcherPropGeneric<T>>;
loadMore(combineData: combineDataFN<T>,params: any): PromiseLike<FetcherPropGeneric<T>>;
}
interface FetcherStateGeneric<T> {
data?: T,
isLoading: boolean,
}
function originalDataMap<T>(obj: any) { return obj as T };
export default function fetcher<T>(path: string, startParams: any, dataMap: dataMapFN<T> = originalDataMap) {
type FetcherProp = FetcherPropGeneric<T>;
type FetcherState = FetcherStateGeneric<T>
return (Component: React.ComponentClass | React.StatelessComponent) => (
class Fetcher extends React.Component<any, FetcherState> {
state: FetcherState = { isLoading: false };
processData = (response: Response) => {
return dataMap(response.json());
}
componentDidMount() {
this.load();
}
load = (): PromiseLike<T> => {
this.setState({ isLoading: true });
return fetch(path, startParams)
.then(this.processData)
.then(data => {
this.setState({ data, isLoading: false })
return data;
});
}
repeat = (params?: any): PromiseLike<FetcherProp> => {
this.setState({ isLoading: true });
return fetch(path, params || startParams)
.then(this.processData)
.then(data => {
this.setState({ data, isLoading: false });
return {
repeat: this.repeat,
loadMore: this.loadMore,
isLoading: false,
data,
}
});
}
loadMore = (combineData: combineDataFN<T>, params?: any): PromiseLike<FetcherProp> => {
this.setState({ isLoading: true });
return fetch(path, params || startParams)
.then(this.processData)
.then(newData => {
const data = combineData(this.state.data, newData);
this.setState({ data, isLoading: false });
return {
repeat: this.repeat,
loadMore: this.loadMore,
isLoading: false,
data,
}
})
}
render() {
const fetcherProp: FetcherProp = {
...this.state,
repeat: this.repeat,
loadMore: this.loadMore,
}
return <Component {...this.props} fetcher={fetcherProp} />;
}
}
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment