简体   繁体   中英

Redux-saga: axios is not working but fetch() does

I have been trying to use axios to fetch data by making an yield call() through workerSaga . I was never able to update the state after fetching the data.

I saw this tutorial from 2018 that uses a different mechanism. It uses yield fetch() .

My approach with axios :

export default function* rootSaga() {
    yield takeLatest('GET_NEWS', workerSaga);
}

function fetchNews(){
    return axios ({
        method: 'get',
        url: 'https://newsapi.org/v1/articles?source=cnn&apiKey=API_KEY'
    });
}

function* workerSaga() {
    try{
        const resp = yield call(fetchNews);
        const article = resp.articles;

        yield put({ type: 'NEWS_RECEIVED', news: article });
    }
    catch (error){
        yield put({ type: 'NEWS_FETCH_ERROR', error });
    }
}

Here everything seems right, the data is fetched (seen in redux devtools ) but the state fails to update, ie, the state remains null .

The other approach from 2018:

function* fetchNews() {
    const json=yield fetch('https://newsapi.org/v1/articles?source=cnn&apiKey=API_KEY')
        .then(response => response.json(), );

    yield put({ type: "NEWS_RECEIVED", json: json.articles, });
}

function* workerSaga()  {
    yield takeLatest('GET_NEWS', fetchNews)
}

export default function* rootSaga() {
    yield all([workerSaga(), ]);
}

It works flawlessly.

What could be the reason that the former axios one is not working?

You already got two correct solutions in the comments but they didn't explain why those work.

The problem is that the return values from fetch and axios are different (this is why I love typescript -- you would have noticed the difference).

The response returned by fetch has a method called .json() . You call res => res.json() to get the contents of the response.

The response returned by axois has already parsed the JSON for you (depending on your config). The contents are stored in a property of the response called data .

You are currently trying to get .articles from the response object, but you need to be getting it from the .data property. There are two ways that you can do this.

  1. You could modify the fetchNews function so that it returns just the data, as suggested by @cbr
function fetchNews(){
    return axios ({
        method: 'get',
        url: 'https://newsapi.org/v1/articles?source=cnn&apiKey=API_KEY'
    }).then( resp => resp.data );
}
  1. You could modify your workerSaga to access the articles from the right path, as suggested by @Aleksey L.
      const resp = yield call(fetchNews);
      const article = resp.data.articles;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM