Redux-saga dispatch return so many requests

Viewed 780

i am build my services with Axios my reducers and actions is build based on Duck pattern but all is working but my dispatch() in componentDidMount() it's send so many request to my API.

This send almost 3k of calls in 3 minutes!

I've already tried with yield cancel() saga middleware with take() but but nothing works :/

ducks/table.js

export const Types = {
  GET_ALL: 'booking/GET_ALL'
};

const initialState = {
  all: null
};

export default function reducer(state = initialState, action) {
  const { type, payload } = action;

  switch (type) {
    case Types.GET_ALL:
      return { 
        ...state,
        all: payload
      };
    default:
      return state;
  }

}

export const fetchAll = data => ({ type: Types.GET_ALL, payload: data });

services/table.js

import Http from "../utils/http";

export const getAll = async () => {
  try {
    const response = await Http.get('/todos/1');

    if (response.data) {
      return response.data;
    }

    throw response.data;
  } catch (error) {
    throw error;
  }
};

sagas/table.js

import { put, call } from 'redux-saga/effects';

import { getAll } from '../services/table'
import { fetchAll } from '../ducks/table';

export function* tableCheck(action) {
    try {       

        let data = yield call(getAll);
        yield put(fetchAll(data));

        console.log("tableCheck => try => action", action)      

    } catch (error) {

        //ToDo criar authError
        yield put(error)
    }
}

store/index.js

import { createStore, applyMiddleware } from "redux";
import createSagaMiddleware from "redux-saga";

import reducers from "./reducers";
import rootSaga from "./sagas";

const sagaMiddleware = createSagaMiddleware();

const store = createStore(reducers, applyMiddleware(sagaMiddleware));

sagaMiddleware.run(rootSaga);

export default store;

store/sagas.js

import { takeLatest } from 'redux-saga/effects';

import { tableCheck } from '../sagas/table';

import { Types as bookingTypes } from '../ducks/table';

export default function* rootSaga() {
    yield takeLatest(bookingTypes.GET_ALL, tableCheck)
}

store/reducer.js

import { combineReducers } from "redux";

import bookings from "../ducks/table";

const appReducer = combineReducers({
  bookings
});
const rootReducer = (state, action) => {
  return appReducer(state, action);
};

export default rootReducer;

components/app.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

import Table from "./common/table";
import { fetchAll } from './ducks/table';

class App extends Component {

  constructor(props) {
    super(props);

    this.state = {
      headers: ["#", "Name", "Check In", "Date", "Status"]
    };

    this.handleClick = this.handleClick.bind(this);    
  }

  async componentDidMount() {    
    //console.log("app => componentDidMount() => fetchAll()", await fetchAll())
    console.log("app => componentDidMount() => this.state", await this.state);
    console.log("app => componentDidMount() => this.props", await this.props);
    await this.props.dispatch(fetchAll());

    //<Table headings={this.state.headers} />

  }



  handleClick(e) {
    e.preventDefault();
    console.log("class App => handleClick() => this.props", this.props);
    console.log("class App => handleClick() => this.state", this.state);

  }

  render() {
    return (
      <div>
        <p className="header">React Table Component</p>

        <p>
          Made with ❤️ by <b>Gabriel Correa</b>
        </p>
        <button onClick={this.handleClick}>Testar</button>
      </div>
    );
  }
}

const mapStateToProps = state => ({ payload: state });

export default connect(mapStateToProps)(App);

Thanks for help xD

1 Answers
yield put(fetchAll(data));

You're dispatching fetchAll in the saga tableCheck. It will trigger the takeLatest in your root saga in an infinite loop:

yield takeLatest(bookingTypes.GET_ALL, tableCheck)

This is likely why you're seeing so many requests.


Solution

As described in the comments:

The way I would approach this instead is split up fetchAll to at least fetchAllRequest and fetchAllSuccess (GET_ALL_REQUEST and GET_ALL_SUCCESS). app.js and takeLatest use fetchAllRequest/GET_ALL_REQUEST instead. put and the reducer use fetchAllSuccess/GET_ALL_SUCCESS instead.

Related