Reputation: 19
So, basically, I have an action, that I dispatch on Button click. Here's my saga:
import * as TYPES from '../types';
import { call, put, takeLatest} from 'redux-saga/effects';
const url = `someApiUrl`;
const api = link => fetch(link, {
method: 'GET'
}).then(res => res.json());
function* callingAPItoFetchNews (action) {
try {
const response = yield call(api, url);
yield put({type: TYPES.FETCH_NEWS, payload: response});
} catch (e) {
yield put({type: TYPES.FETCH_NEW_FAILED});
}
}
export default function* watcherSaga () {
yield takeLatest(TYPES.FETCH_NEWS, callingAPItoFetchNews)
}
and here's my root saga:
import { takeEvery, all, takeLatest, fork } from 'redux- saga/effects';
import * as TYPES from '../types';
import callingAPItoFetchNews from '../sagas';
function* mySaga() {
yield all ([
fork(callingAPItoFetchNews)
])
}
export default mySaga;
After dispatching an action I see, that each fetch request is populated every second. Actions itself looks just like that:
export const fetchNews = () => ({type: TYPES.FETCH_NEWS});
here is how I check the data that comes back basically:
componentWillReceiveProps(nextProps) {
console.log(nextProps);
if (nextProps.dataLoaded !== undefined) {
const articles = nextProps.dataLoaded.articles;
const totalResults = nextProps.dataLoaded.totalResults;
console.log('-----SEPARATION START-------');
console.log(articles);
console.log('-------SEPARATION END--------')
}
}
Here is my view where I connect app with redux and dispatch an action:
import React, { Component } from 'react';
import {
View,
Text,
Button,
ScrollView,
TouchableOpacity
} from 'react-native';
import { connect } from 'react-redux'
import { fetchNews } from './actions'
import { Ionicons } from '@expo/vector-icons'
import NavStack from './navigation';
import s from './styles';
class MainView extends React.PureComponent {
componentWillReceiveProps(nextProps) {
if (nextProps.dataLoaded !== undefined) {
const articles = nextProps.dataLoaded.articles;
const totalResults = nextProps.dataLoaded.totalResults;
console.log('-----SEPARATION START-------');
console.log(articles);
console.log('-------SEPARATION END--------')
}
}
render() {
return (
//<NavStack/>
<View style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}}>
<Button
title='Click me to fetch data'
onPress={() => {
this.props.fetchNewsData();
}}
/>
</View>
);
}
}
mapStateToProps = state => ({
dataLoaded: state.fetchNews.news
});
mapDispatchToProps = dispatch => ({
fetchNewsData: () => dispatch(fetchNews())
});
export default connect(mapStateToProps, mapDispatchToProps)(MainView);
Upvotes: 0
Views: 388
Reputation: 620
import * as TYPES from '../types';
import { call, put, takeLatest} from 'redux-saga/effects';
const url = `someApiUrl`;
const api = link => fetch(link, {
method: 'GET'
}).then(res => res.json());
function* callingAPItoFetchNews (action) {
try {
const response = yield call(api, url);
yield put({type: TYPES.FETCH_NEWS, payload: response});
} catch (e) {
yield put({type: TYPES.FETCH_NEW_FAILED});
}
}
export default function* watcherSaga () {
yield takeLatest(TYPES.FETCH_NEWS, callingAPItoFetchNews)
}
Because of the code above,
You can see that your code takes TYPES.FETCH_NEWS
action and call api.
It is the problem when you also dispatch the same action TYPES.FETCH_NEWS
when received a response from api by this line yield put({type: TYPES.FETCH_NEWS, payload: response});
.
To solve the problem with a standard way you should instead use new action type for api response. yield put({type: TYPES.FETCH_NEWS_SUCCESS, payload: response});
Upvotes: 0
Reputation: 837
Your takeLatest
:
takeLatest(TYPES.FETCH_NEWS, callingAPItoFetchNews)
is reacting on action that you put
:
yield put({type: TYPES.FETCH_NEWS, payload: response});
You should use or different name or use take
instead(and make solution with loop to catch event after handling first).
Upvotes: 1