NZJames
NZJames

Reputation: 5055

Saga watcher not receiving or processing dispatched action

I have a watcher saga that is constantly listening for actions of a certain type. This is started up from the saga.run(). When it receives an action of a certain type, it should then call into another saga which performs async actions. However a breakpoint inside the second saga is never getting called.

So either the originating code is not dispatching the action correctly, or the watcher saga is configured wrong.

Watcher saga code

import { all, fork, takeLatest } from 'redux-saga/effects'
import {fetchItems} from './itemsSaga';

function* watchLoadItemsRequest() {
  while(true) {
    yield takeLatest('FETCH_ITEMS_REQUEST', fetchItems);
  }
}    

export default function* root() {
  yield all ([
    fork(watchLoadItemsRequest)
  ])
}

My itemsSaga (that isn't being called)

import { call, put } from 'redux-saga/effects'
import fetchItemsCompleted from '../actions/fetchItemsCompleted';
import httpCallCompleted from '../actions/httpCallCompleted';
import httpCallStarted from '../actions/httpCallStarted';
import itemAPI from '../api/itemAPI';
import ItemsEntity from '../api/itemEntity';

// worker Saga: will be fired on FETCH_ITEMS_REQUEST actions
export function* fetchItems(action:any) {
  let items : ItemEntity[];

  yield put(httpCallStarted());
  trades = yield call(itemAPI.getAllItemsAsync)
  trades = [new ItemEntity(), new ItemEntity()]
  yield put(fetchItemsCompleted(items))
  yield put(httpCallCompleted());
}

My store creation code

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

import reducers  from '../reducers';
import watchersSaga from '../sagas/watchersSaga';

export default function getStore() {
const sagaMiddleware = createSagaMiddleware();

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

    sagaMiddleware.run(watchersSaga);

    return store;
  }  

And lastly the control which should send the FETCH_ITEMS_REQUEST action

import * as React from 'react';
import { connect, Dispatch } from 'react-redux';
import ItemEntity from './api/itemEntity';
import './App.css';
import IStoreState from './interfaces/IStoreState';

interface IContentProps {
  groupingType : string,
  items: ItemEntity[],
  loadItems : () => void
}

class MyContent extends React.Component<IContentProps,{}> {

  constructor(props: any) {
    super(props);
  }

  public componentDidMount() {
    this.props.loadItems();
  }

  public render() {
    return (
      <div className="Center-content">
        <div className="Center-content White">
        <br/><br/>Grouped by {this.props.groupingType}<br/><br/>{this.props.items.length} items loaded
        </div>
      </div>
    );
  }


}

function mapStateToProps(state: IStoreState) {
  return {
    groupingType: state.navigation.groupingType,
    trades: state.item.items
  };
}    

const mapDispatchToProps = (dispatch: Dispatch) => {
  return {
    loadItems: () => dispatch({type:'FETCH_ITEMS_REQUEST'})
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(PnlContent);

Why isn't this working? Is there a way I can tell whether or not the FETCH_ITEMS_REQUEST is actually being generated and sent to redux or not? That way at least I could narrow down where the problem is occurring.

UPDATE: I've tweaked one of my reducers to listen to the FETCH_ITEMS_REQUEST and it picks up the event, so my control is dispatching the action fine. It just seems the WatcherSaga is not triggering the ItemsSaga fetchItems() method when it receives a FETCH_ITEMS_REQUEST action so I think the problem is in my watchersSaga

SECOND UPDATE:

More and more I think the problem lies with the lines

while(true) {
    yield takeLatest('FETCH_ITEMS_REQUEST', fetchItems);
  }

This doesn't seem to be responding to a received FETCH_ITEMS_REQUEST message and calling fetchItems

Upvotes: 2

Views: 3105

Answers (1)

NZJames
NZJames

Reputation: 5055

For anyone with a similar problem I ended up solving it by changing my watchers Saga to the following

function* watchLoadTradesRequest() {
    yield takeEvery('FETCH_TRADES_REQUEST', fetchTrades);
}

// Register all your watchers
export default function* watchersRootSaga() {
  yield all ([
    watchLoadTradesRequest()
  ])
}

Upvotes: 5

Related Questions