How to handle errors in fetch () answers using Redux-Saga?

I am trying to handle a Unauthorized error from a server using redux-saga. This is my saga:

 function* logIn(action) { try { const user = yield call(Api.logIn, action); yield put({type: types.LOG_IN_SUCCEEDED, user}); } catch (error) { yield put({type: types.LOG_IN_FAILED, error}); } } 

I retrieve the data as follows:

 fetchUser(action) { const {username, password} = action.user; const body = {username, password}; return fetch(LOGIN_URL, { method, headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify(body) }) .then(res => { res.json().then(json => { if (res.status >= 200 && res.status < 300) { return json } else { throw res } }) }) .catch(error => {throw error}); } 

But in any case, the result is {type: 'LOG_IN_SUCCEEDED', user: undefined} when I expect {type: 'LOG_IN_FAILED', error: 'Unauthorized'} . Where is my mistake? How to handle errors correctly with Redux-Saga?

+6
source share
2 answers

Do not handle then and error in the fetchUser method and your saga. Since you already try / catch ing in your saga, you can process it there.

Example

Saga

 function* logIn(action) { try { const response = yield call(Api.logIn, action); if (response.status >= 200 && response.status < 300) { const user = yield response.json(); yield put({ type: types.LOG_IN_SUCCEEDED, user }); } else { throw response; } } catch (error) { yield put({ type: types.LOG_IN_FAILED, error }); } } 

Fetch

 fetchUser(action) { const { username, password } = action.user; const body = { username, password }; return fetch(LOGIN_URL, { method, headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify(body) }) } 

As a side note: I find the fetch api a bit uncomfortable because it returns a then -able response when you make a request. There are many libraries; I personally prefer axios , which returns json by default.

+8
source

if you want to have this if statement checking the status of the response if(res.status >= 200 && res.status < 300) { , you need to have it in your first promise where res is defined, it is currently in the allowed promise for res.json()

 .then(res => { if (res.status >= 200 && res.status < 300) { res.json().then(json => { return json } }) }) 
+2
source

All Articles