Recientemente comencé a usar redux-saga y realmente me está gustando.
Tengo el siguiente envoltorio que estaba usando para mis llamadas a la API que aceptaría una promesa (mi llamada a la API) y mostraría un precargador y manejaría los errores.
export const callApi = (promise: Promise<any>, errorMsg: string = 'Api error') => (dispatch: Dispatch) => { dispatch(setLoading(true)); return promise.then( (response) => { dispatch(setLoading(false)); return response.body; }, (error) => { dispatch(setLoading(false)); dispatch(apiError(errorMsg, error)); return error; }); };No estoy seguro de cómo replicaría un comportamiento como este en la saga redux. No pude encontrar ningún ejemplo de hacer algo como esto?
Hasta ahora se me ha ocurrido
const camelizeKeysPromise = (obj) => Promise.resolve(camelizeKeys(obj)); export function* sagaCallApi(promise: Promise<any>, errorMsg: string = 'Api error') { yield put(setLoading(true)); try { const response = yield call(promise); try { const result = yield call(camelizeKeysPromise(response.body)); return result; } catch (e) { return response.body; } } catch (exception) { yield put(setLoading(false)); yield put(apiError(errorMsg, error)); }; }Hacer una call a la promesa no devolverá la respuesta deseada. Puede usar eventChannel de redux-saga para crear un canal que emita la respuesta en caso de éxito o el objeto de error en caso de falla y luego suscribirse al canal en su saga.
const promiseEmitter = promise => { return eventChannel(emit => { promise.then( response => emit({response}), error => emit({error}) ); }); };Modifica tu nueva saga reemplazando la llamada a la promesa con esto:
const channel = yield call(promiseEmitter, promise); const {response, error} = yield take(channel); if(response){ // handle success return response; }else if(error){ // handle failure yield put(setLoading(false)); yield put(apiError(errorMsg, error)); }Tenga en cuenta que puede haber errores sintácticos en mi código ya que escribí esto sin un editor, pero puede obtener el enfoque general.