interface Response<T> { status: 'success' | 'pending' | 'error'; data: T | null; } /** * A promise tracker that will be updated * when promise resolves or rejects */ const response: Response<unknown> = { status: 'pending', data: null }; /** * This is our suspender function * that throws promise if it is not fulfilled yet */ export function suspend<T>(fn: () => Promise<T>) { /** * suspender is the promise we will throw * so react can re-render when it is fulfilled */ const suspender = fn().then( (res) => { response.status = 'success'; response.data = res; }, (error) => { response.status = 'error'; response.data = error; } ); switch (response.status) { case 'pending': throw suspender; case 'error': throw response.data as T; default: return response.data as T; } }