Drews FR
Drews FR

Reputation: 19

redux-saga spams with new requests after dispatching a single action

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

Answers (2)

Krit
Krit

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

Alex Shtromberg
Alex Shtromberg

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

Related Questions