I am working on adding some progress indicators to my React web application.
So far I have been using the following as a basis.
react-suspense-data-fetching.
export interface ISuspender<T> {
read(): T;
}
const createSuspender = <T,>(promise: Promise<T>): ISuspender<T> => {
let status: string = 'pending';
let response: T;
const suspender: Promise<void> = promise.then(
(result) => {
status = "susccess";
response = result;
},
(error) => {
status = "error";
response = error;
}
);
const read = (): T => {
switch (status) {
case 'pending':
throw suspender;
case 'error':
throw response;
default:
return response;
}
}
return { read }
}
const getSetsSuspender: ISuspender<Scry.Set[]> = createSuspender(Scry.Sets.all());
export const MtgSetList: React.FunctionComponent = () => {
const sets: Scry.Set[] = getSetsSuspender.read();
return (
<SetList sets={sets} />
)
}
It works but not as well as I would like it to. For starters the data returned is not stored in state so I am unable to interact with it and add filtering capabilities.
I am also not a huge fan of how the suspender needs to be declared outside of the component.
Ideally I would like to write the MtgSetList like this
export const MtgSetList: React.FunctionComponent = () => {
const getSetsSuspender: ISuspender<Scry.Set[]> = createSuspender(Scry.Sets.all());
const [sets, setSets] = React.useState<Scry.Set[]>();
useEffect(() => {
setSets(getSetsSuspender.read());
}, [getSetsSuspender]);
return (
<SetList sets={sets} />
)
}
Any and all advice would be greatly appreciated.
2
Answers
While still not perfect I have gotten it somewhat working by creating the suspender instance outside of the component. That was causing some weird refreshing behavior. So I added a check to see if I needed to retrieve the data or not.
Move getSetsSuspender inside a useEffect hook. Then, use getSetsSuspender.read() to retrieve the data and set the state using setSets.